• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.display;
18 
19 import android.animation.Animator;
20 import android.animation.ObjectAnimator;
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.app.ActivityManager;
24 import android.content.Context;
25 import android.content.pm.ParceledListSlice;
26 import android.content.res.Resources;
27 import android.database.ContentObserver;
28 import android.hardware.Sensor;
29 import android.hardware.SensorEvent;
30 import android.hardware.SensorEventListener;
31 import android.hardware.SensorManager;
32 import android.hardware.display.AmbientBrightnessDayStats;
33 import android.hardware.display.BrightnessChangeEvent;
34 import android.hardware.display.BrightnessConfiguration;
35 import android.hardware.display.BrightnessInfo;
36 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
37 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
38 import android.metrics.LogMaker;
39 import android.net.Uri;
40 import android.os.Handler;
41 import android.os.IBinder;
42 import android.os.Looper;
43 import android.os.Message;
44 import android.os.PowerManager;
45 import android.os.RemoteException;
46 import android.os.SystemClock;
47 import android.os.SystemProperties;
48 import android.os.Trace;
49 import android.os.UserHandle;
50 import android.provider.Settings;
51 import android.util.Log;
52 import android.util.MathUtils;
53 import android.util.MutableFloat;
54 import android.util.MutableInt;
55 import android.util.Slog;
56 import android.util.TimeUtils;
57 import android.view.Display;
58 
59 import com.android.internal.R;
60 import com.android.internal.annotations.GuardedBy;
61 import com.android.internal.app.IBatteryStats;
62 import com.android.internal.display.BrightnessSynchronizer;
63 import com.android.internal.logging.MetricsLogger;
64 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
65 import com.android.internal.util.FrameworkStatsLog;
66 import com.android.internal.util.RingBuffer;
67 import com.android.server.LocalServices;
68 import com.android.server.am.BatteryStatsService;
69 import com.android.server.display.RampAnimator.DualRampAnimator;
70 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
71 import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
72 import com.android.server.display.utils.SensorUtils;
73 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
74 import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
75 import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
76 import com.android.server.policy.WindowManagerPolicy;
77 
78 import java.io.PrintWriter;
79 import java.util.Objects;
80 
81 /**
82  * Controls the power state of the display.
83  *
84  * Handles the proximity sensor, light sensor, and animations between states
85  * including the screen off animation.
86  *
87  * This component acts independently of the rest of the power manager service.
88  * In particular, it does not share any state and it only communicates
89  * via asynchronous callbacks to inform the power manager that something has
90  * changed.
91  *
92  * Everything this class does internally is serialized on its handler although
93  * it may be accessed by other threads from the outside.
94  *
95  * Note that the power manager service guarantees that it will hold a suspend
96  * blocker as long as the display is not ready.  So most of the work done here
97  * does not need to worry about holding a suspend blocker unless it happens
98  * independently of the display ready signal.
99    *
100  * For debugging, you can make the color fade and brightness animations run
101  * slower by changing the "animator duration scale" option in Development Settings.
102  */
103 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
104         DisplayWhiteBalanceController.Callbacks {
105     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
106     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
107 
108     private static final boolean DEBUG = false;
109     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
110 
111     // If true, uses the color fade on animation.
112     // We might want to turn this off if we cannot get a guarantee that the screen
113     // actually turns on and starts showing new content after the call to set the
114     // screen state returns.  Playing the animation can also be somewhat slow.
115     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
116 
117     private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
118 
119     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
120     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
121 
122     private static final int MSG_UPDATE_POWER_STATE = 1;
123     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
124     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
125     private static final int MSG_SCREEN_OFF_UNBLOCKED = 4;
126     private static final int MSG_CONFIGURE_BRIGHTNESS = 5;
127     private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
128     private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
129     private static final int MSG_IGNORE_PROXIMITY = 8;
130     private static final int MSG_STOP = 9;
131     private static final int MSG_UPDATE_BRIGHTNESS = 10;
132     private static final int MSG_UPDATE_RBC = 11;
133     private static final int MSG_BRIGHTNESS_RAMP_DONE = 12;
134     private static final int MSG_STATSD_HBM_BRIGHTNESS = 13;
135     private static final int MSG_SWITCH_USER = 14;
136     private static final int MSG_BOOT_COMPLETED = 15;
137 
138     private static final int PROXIMITY_UNKNOWN = -1;
139     private static final int PROXIMITY_NEGATIVE = 0;
140     private static final int PROXIMITY_POSITIVE = 1;
141 
142     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
143     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
144     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
145 
146     private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
147 
148     // Trigger proximity if distance is less than 5 cm.
149     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
150 
151     // State machine constants for tracking initial brightness ramp skipping when enabled.
152     private static final int RAMP_STATE_SKIP_NONE = 0;
153     private static final int RAMP_STATE_SKIP_INITIAL = 1;
154     private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
155 
156     private static final int REPORTED_TO_POLICY_UNREPORTED = -1;
157     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
158     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
159     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
160     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
161 
162     private static final int RINGBUFFER_MAX = 100;
163 
164     private final String TAG;
165 
166     private final Object mLock = new Object();
167 
168     private final Context mContext;
169 
170     // Our handler.
171     private final DisplayControllerHandler mHandler;
172 
173     // Asynchronous callbacks into the power manager service.
174     // Only invoked from the handler thread while no locks are held.
175     private final DisplayPowerCallbacks mCallbacks;
176 
177     // Battery stats.
178     @Nullable
179     private final IBatteryStats mBatteryStats;
180 
181     // The sensor manager.
182     private final SensorManager mSensorManager;
183 
184     // The window manager policy.
185     private final WindowManagerPolicy mWindowManagerPolicy;
186 
187     // The display blanker.
188     private final DisplayBlanker mBlanker;
189 
190     // The LogicalDisplay tied to this DisplayPowerController.
191     private final LogicalDisplay mLogicalDisplay;
192 
193     // The ID of the LogicalDisplay tied to this DisplayPowerController.
194     private final int mDisplayId;
195 
196     // The unique ID of the primary display device currently tied to this logical display
197     private String mUniqueDisplayId;
198 
199     // Tracker for brightness changes.
200     @Nullable
201     private final BrightnessTracker mBrightnessTracker;
202 
203     // Tracker for brightness settings changes.
204     private final SettingsObserver mSettingsObserver;
205 
206     // The proximity sensor, or null if not available or needed.
207     private Sensor mProximitySensor;
208 
209     // The doze screen brightness.
210     private final float mScreenBrightnessDozeConfig;
211 
212     // The dim screen brightness.
213     private final float mScreenBrightnessDimConfig;
214 
215     // The minimum dim amount to use if the screen brightness is already below
216     // mScreenBrightnessDimConfig.
217     private final float mScreenBrightnessMinimumDimAmount;
218 
219     private final float mScreenBrightnessDefault;
220 
221     // The minimum allowed brightness while in VR.
222     private final float mScreenBrightnessForVrRangeMinimum;
223 
224     // The maximum allowed brightness while in VR.
225     private final float mScreenBrightnessForVrRangeMaximum;
226 
227     // The default screen brightness for VR.
228     private final float mScreenBrightnessForVrDefault;
229 
230     // True if auto-brightness should be used.
231     private boolean mUseSoftwareAutoBrightnessConfig;
232 
233     // True if should use light sensor to automatically determine doze screen brightness.
234     private final boolean mAllowAutoBrightnessWhileDozingConfig;
235 
236     // True if we want to persist the brightness value in nits even if the underlying display
237     // device changes.
238     private final boolean mPersistBrightnessNitsForDefaultDisplay;
239 
240     // True if the brightness config has changed and the short-term model needs to be reset
241     private boolean mShouldResetShortTermModel;
242 
243     // Whether or not the color fade on screen on / off is enabled.
244     private final boolean mColorFadeEnabled;
245 
246     @GuardedBy("mCachedBrightnessInfo")
247     private final CachedBrightnessInfo mCachedBrightnessInfo = new CachedBrightnessInfo();
248 
249     private DisplayDevice mDisplayDevice;
250 
251     // True if we should fade the screen while turning it off, false if we should play
252     // a stylish color fade animation instead.
253     private final boolean mColorFadeFadesConfig;
254 
255     // True if we need to fake a transition to off when coming out of a doze state.
256     // Some display hardware will blank itself when coming out of doze in order to hide
257     // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
258     // blank itself and begin an appropriate power on animation.
259     private final boolean mDisplayBlanksAfterDozeConfig;
260 
261     // True if there are only buckets of brightness values when the display is in the doze state,
262     // rather than a full range of values. If this is true, then we'll avoid animating the screen
263     // brightness since it'd likely be multiple jarring brightness transitions instead of just one
264     // to reach the final state.
265     private final boolean mBrightnessBucketsInDozeConfig;
266 
267     //  Maximum time a ramp animation can take.
268     private long mBrightnessRampIncreaseMaxTimeMillis;
269     private long mBrightnessRampDecreaseMaxTimeMillis;
270 
271     // The pending power request.
272     // Initially null until the first call to requestPowerState.
273     @GuardedBy("mLock")
274     private DisplayPowerRequest mPendingRequestLocked;
275 
276     // True if a request has been made to wait for the proximity sensor to go negative.
277     @GuardedBy("mLock")
278     private boolean mPendingWaitForNegativeProximityLocked;
279 
280     // True if the pending power request or wait for negative proximity flag
281     // has been changed since the last update occurred.
282     @GuardedBy("mLock")
283     private boolean mPendingRequestChangedLocked;
284 
285     // Set to true when the important parts of the pending power request have been applied.
286     // The important parts are mainly the screen state.  Brightness changes may occur
287     // concurrently.
288     @GuardedBy("mLock")
289     private boolean mDisplayReadyLocked;
290 
291     // Set to true if a power state update is required.
292     @GuardedBy("mLock")
293     private boolean mPendingUpdatePowerStateLocked;
294 
295     /* The following state must only be accessed by the handler thread. */
296 
297     // The currently requested power state.
298     // The power controller will progressively update its internal state to match
299     // the requested power state.  Initially null until the first update.
300     private DisplayPowerRequest mPowerRequest;
301 
302     // The current power state.
303     // Must only be accessed on the handler thread.
304     private DisplayPowerState mPowerState;
305 
306     // True if the device should wait for negative proximity sensor before
307     // waking up the screen.  This is set to false as soon as a negative
308     // proximity sensor measurement is observed or when the device is forced to
309     // go to sleep by the user.  While true, the screen remains off.
310     private boolean mWaitingForNegativeProximity;
311 
312     // True if the device should not take into account the proximity sensor
313     // until either the proximity sensor state changes, or there is no longer a
314     // request to listen to proximity sensor.
315     private boolean mIgnoreProximityUntilChanged;
316 
317     // The actual proximity sensor threshold value.
318     private float mProximityThreshold;
319 
320     // Set to true if the proximity sensor listener has been registered
321     // with the sensor manager.
322     private boolean mProximitySensorEnabled;
323 
324     // The debounced proximity sensor state.
325     private int mProximity = PROXIMITY_UNKNOWN;
326 
327     // The raw non-debounced proximity sensor state.
328     private int mPendingProximity = PROXIMITY_UNKNOWN;
329     private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
330 
331     // True if the screen was turned off because of the proximity sensor.
332     // When the screen turns on again, we report user activity to the power manager.
333     private boolean mScreenOffBecauseOfProximity;
334 
335     // The currently active screen on unblocker.  This field is non-null whenever
336     // we are waiting for a callback to release it and unblock the screen.
337     private ScreenOnUnblocker mPendingScreenOnUnblocker;
338     private ScreenOffUnblocker mPendingScreenOffUnblocker;
339 
340     // True if we were in the process of turning off the screen.
341     // This allows us to recover more gracefully from situations where we abort
342     // turning off the screen.
343     private boolean mPendingScreenOff;
344 
345     // True if we have unfinished business and are holding a suspend blocker.
346     private boolean mUnfinishedBusiness;
347 
348     // The elapsed real time when the screen on was blocked.
349     private long mScreenOnBlockStartRealTime;
350     private long mScreenOffBlockStartRealTime;
351 
352     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_* fields.
353     private int mReportedScreenStateToPolicy = REPORTED_TO_POLICY_UNREPORTED;
354 
355     // If the last recorded screen state was dozing or not.
356     private boolean mDozing;
357 
358     // Remembers whether certain kinds of brightness adjustments
359     // were recently applied so that we can decide how to transition.
360     private boolean mAppliedAutoBrightness;
361     private boolean mAppliedDimming;
362     private boolean mAppliedLowPower;
363     private boolean mAppliedScreenBrightnessOverride;
364     private boolean mAppliedTemporaryBrightness;
365     private boolean mAppliedTemporaryAutoBrightnessAdjustment;
366     private boolean mAppliedBrightnessBoost;
367     private boolean mAppliedThrottling;
368 
369     // Reason for which the brightness was last changed. See {@link BrightnessReason} for more
370     // information.
371     // At the time of this writing, this value is changed within updatePowerState() only, which is
372     // limited to the thread used by DisplayControllerHandler.
373     private final BrightnessReason mBrightnessReason = new BrightnessReason();
374     private final BrightnessReason mBrightnessReasonTemp = new BrightnessReason();
375 
376     // Brightness animation ramp rates in brightness units per second
377     private float mBrightnessRampRateFastDecrease;
378     private float mBrightnessRampRateFastIncrease;
379     private float mBrightnessRampRateSlowDecrease;
380     private float mBrightnessRampRateSlowIncrease;
381 
382     // Report HBM brightness change to StatsD
383     private int mDisplayStatsId;
384     private float mLastStatsBrightness = PowerManager.BRIGHTNESS_MIN;
385 
386     // Whether or not to skip the initial brightness ramps into STATE_ON.
387     private final boolean mSkipScreenOnBrightnessRamp;
388 
389     // Display white balance components.
390     @Nullable
391     private final DisplayWhiteBalanceSettings mDisplayWhiteBalanceSettings;
392     @Nullable
393     private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
394 
395     @Nullable
396     private final ColorDisplayServiceInternal mCdsi;
397     private float[] mNitsRange;
398 
399     private final HighBrightnessModeController mHbmController;
400     private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
401 
402     private final BrightnessThrottler mBrightnessThrottler;
403 
404     private final BrightnessSetting mBrightnessSetting;
405 
406     private final Runnable mOnBrightnessChangeRunnable;
407 
408     private final BrightnessEvent mLastBrightnessEvent;
409     private final BrightnessEvent mTempBrightnessEvent;
410 
411     // Keeps a record of brightness changes for dumpsys.
412     private RingBuffer<BrightnessEvent> mBrightnessEventRingBuffer;
413 
414     // A record of state for skipping brightness ramps.
415     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
416 
417     // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
418     private float mInitialAutoBrightness;
419 
420     // The controller for the automatic brightness level.
421     @Nullable
422     private AutomaticBrightnessController mAutomaticBrightnessController;
423 
424     // The controller for the sensor used to estimate ambient lux while the display is off.
425     @Nullable
426     private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
427 
428     private Sensor mLightSensor;
429     private Sensor mScreenOffBrightnessSensor;
430 
431     // The mappers between ambient lux, display backlight values, and display brightness.
432     // We will switch between the idle mapper and active mapper in AutomaticBrightnessController.
433     // Mapper used for active (normal) screen brightness mode
434     @Nullable
435     private BrightnessMappingStrategy mInteractiveModeBrightnessMapper;
436     // Mapper used for idle screen brightness mode
437     @Nullable
438     private BrightnessMappingStrategy mIdleModeBrightnessMapper;
439 
440     // The current brightness configuration.
441     @Nullable
442     private BrightnessConfiguration mBrightnessConfiguration;
443 
444     // The last brightness that was set by the user and not temporary. Set to
445     // PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
446     private float mLastUserSetScreenBrightness = Float.NaN;
447 
448     // The screen brightness setting has changed but not taken effect yet. If this is different
449     // from the current screen brightness setting then this is coming from something other than us
450     // and should be considered a user interaction.
451     private float mPendingScreenBrightnessSetting;
452 
453     // The last observed screen brightness setting, either set by us or by the settings app on
454     // behalf of the user.
455     private float mCurrentScreenBrightnessSetting;
456 
457     // The temporary screen brightness. Typically set when a user is interacting with the
458     // brightness slider but hasn't settled on a choice yet. Set to
459     // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary brightness set.
460     private float mTemporaryScreenBrightness;
461 
462     // The current screen brightness while in VR mode.
463     private float mScreenBrightnessForVr;
464 
465     // The last auto brightness adjustment that was set by the user and not temporary. Set to
466     // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
467     private float mAutoBrightnessAdjustment;
468 
469     // The pending auto brightness adjustment that will take effect on the next power state update.
470     private float mPendingAutoBrightnessAdjustment;
471 
472     // The temporary auto brightness adjustment. Typically set when a user is interacting with the
473     // adjustment slider but hasn't settled on a choice yet. Set to
474     // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
475     private float mTemporaryAutoBrightnessAdjustment;
476 
477     private boolean mUseAutoBrightness;
478 
479     private boolean mIsRbcActive;
480 
481     // Whether there's a callback to tell listeners the display has changed scheduled to run. When
482     // true it implies a wakelock is being held to guarantee the update happens before we collapse
483     // into suspend and so needs to be cleaned up if the thread is exiting.
484     // Should only be accessed on the Handler thread.
485     private boolean mOnStateChangedPending;
486 
487     // Count of proximity messages currently on this DPC's Handler. Used to keep track of how many
488     // suspend blocker acquisitions are pending when shutting down this DPC.
489     // Should only be accessed on the Handler thread.
490     private int mOnProximityPositiveMessages;
491     private int mOnProximityNegativeMessages;
492 
493     // Animators.
494     private ObjectAnimator mColorFadeOnAnimator;
495     private ObjectAnimator mColorFadeOffAnimator;
496     private DualRampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
497     private BrightnessSetting.BrightnessSettingListener mBrightnessSettingListener;
498 
499     // True if this DisplayPowerController has been stopped and should no longer be running.
500     private boolean mStopped;
501 
502     private DisplayDeviceConfig mDisplayDeviceConfig;
503 
504     // Identifiers for suspend blocker acuisition requests
505     private final String mSuspendBlockerIdUnfinishedBusiness;
506     private final String mSuspendBlockerIdOnStateChanged;
507     private final String mSuspendBlockerIdProxPositive;
508     private final String mSuspendBlockerIdProxNegative;
509     private final String mSuspendBlockerIdProxDebounce;
510 
511     private boolean mIsEnabled;
512     private boolean mIsInTransition;
513 
514     private boolean mBootCompleted;
515 
516     /**
517      * Creates the display power controller.
518      */
DisplayPowerController(Context context, DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay, BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting, Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata, boolean bootCompleted)519     public DisplayPowerController(Context context,
520             DisplayPowerCallbacks callbacks, Handler handler,
521             SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
522             BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
523             Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
524             boolean bootCompleted) {
525         mLogicalDisplay = logicalDisplay;
526         mDisplayId = mLogicalDisplay.getDisplayIdLocked();
527         final String displayIdStr = "[" + mDisplayId + "]";
528         TAG = "DisplayPowerController" + displayIdStr;
529         mSuspendBlockerIdUnfinishedBusiness = displayIdStr + "unfinished business";
530         mSuspendBlockerIdOnStateChanged = displayIdStr + "on state changed";
531         mSuspendBlockerIdProxPositive = displayIdStr + "prox positive";
532         mSuspendBlockerIdProxNegative = displayIdStr + "prox negative";
533         mSuspendBlockerIdProxDebounce = displayIdStr + "prox debounce";
534         mHighBrightnessModeMetadata = hbmMetadata;
535 
536         mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
537         mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
538         mDisplayStatsId = mUniqueDisplayId.hashCode();
539         mIsEnabled = logicalDisplay.isEnabledLocked();
540         mIsInTransition = logicalDisplay.isInTransitionLocked();
541         mHandler = new DisplayControllerHandler(handler.getLooper());
542         mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
543         mTempBrightnessEvent = new BrightnessEvent(mDisplayId);
544 
545         if (mDisplayId == Display.DEFAULT_DISPLAY) {
546             mBatteryStats = BatteryStatsService.getService();
547         } else {
548             mBatteryStats = null;
549         }
550 
551         mSettingsObserver = new SettingsObserver(mHandler);
552         mCallbacks = callbacks;
553         mSensorManager = sensorManager;
554         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
555         mBlanker = blanker;
556         mContext = context;
557         mBrightnessTracker = brightnessTracker;
558         // TODO: b/186428377 update brightness setting when display changes
559         mBrightnessSetting = brightnessSetting;
560         mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
561 
562         PowerManager pm = context.getSystemService(PowerManager.class);
563 
564         final Resources resources = context.getResources();
565 
566         // DOZE AND DIM SETTINGS
567         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
568                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
569         mScreenBrightnessDimConfig = clampAbsoluteBrightness(
570                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
571         mScreenBrightnessMinimumDimAmount = resources.getFloat(
572                 com.android.internal.R.dimen.config_screenBrightnessMinimumDimAmountFloat);
573 
574 
575         // NORMAL SCREEN SETTINGS
576         mScreenBrightnessDefault = clampAbsoluteBrightness(
577                 mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
578 
579         // VR SETTINGS
580         mScreenBrightnessForVrDefault = clampAbsoluteBrightness(
581                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR));
582         mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(
583                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR));
584         mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
585                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
586 
587         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
588                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
589 
590         mPersistBrightnessNitsForDefaultDisplay = resources.getBoolean(
591                 com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay);
592 
593         mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
594                 .getDisplayDeviceConfig();
595 
596         loadBrightnessRampRates();
597         mSkipScreenOnBrightnessRamp = resources.getBoolean(
598                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
599 
600         mHbmController = createHbmControllerLocked();
601 
602         mBrightnessThrottler = createBrightnessThrottlerLocked();
603 
604         // Seed the cached brightness
605         saveBrightnessInfo(getScreenBrightnessSetting());
606 
607         DisplayWhiteBalanceSettings displayWhiteBalanceSettings = null;
608         DisplayWhiteBalanceController displayWhiteBalanceController = null;
609         if (mDisplayId == Display.DEFAULT_DISPLAY) {
610             try {
611                 displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
612                 displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
613                         mSensorManager, resources);
614                 displayWhiteBalanceSettings.setCallbacks(this);
615                 displayWhiteBalanceController.setCallbacks(this);
616             } catch (Exception e) {
617                 Slog.e(TAG, "failed to set up display white-balance: " + e);
618             }
619         }
620         mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
621         mDisplayWhiteBalanceController = displayWhiteBalanceController;
622 
623         loadNitsRange(resources);
624 
625         if (mDisplayId == Display.DEFAULT_DISPLAY) {
626             mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
627             boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
628                 @Override
629                 public void onReduceBrightColorsActivationChanged(boolean activated,
630                         boolean userInitiated) {
631                     applyReduceBrightColorsSplineAdjustment();
632 
633                 }
634 
635                 @Override
636                 public void onReduceBrightColorsStrengthChanged(int strength) {
637                     applyReduceBrightColorsSplineAdjustment();
638                 }
639             });
640             if (active) {
641                 applyReduceBrightColorsSplineAdjustment();
642             }
643         } else {
644             mCdsi = null;
645         }
646 
647         setUpAutoBrightness(resources, handler);
648 
649         mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic();
650         mColorFadeFadesConfig = resources.getBoolean(
651                 com.android.internal.R.bool.config_animateScreenLights);
652 
653         mDisplayBlanksAfterDozeConfig = resources.getBoolean(
654                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
655 
656         mBrightnessBucketsInDozeConfig = resources.getBoolean(
657                 com.android.internal.R.bool.config_displayBrightnessBucketsInDoze);
658 
659         loadProximitySensor();
660 
661         loadNitBasedBrightnessSetting();
662         mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
663         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
664         mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
665         mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
666         mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
667         mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
668 
669         mBootCompleted = bootCompleted;
670     }
671 
applyReduceBrightColorsSplineAdjustment()672     private void applyReduceBrightColorsSplineAdjustment() {
673         mHandler.obtainMessage(MSG_UPDATE_RBC).sendToTarget();
674         sendUpdatePowerState();
675     }
676 
handleRbcChanged()677     private void handleRbcChanged() {
678         if (mAutomaticBrightnessController == null) {
679             return;
680         }
681         if ((!mAutomaticBrightnessController.isInIdleMode()
682                 && mInteractiveModeBrightnessMapper == null)
683                 || (mAutomaticBrightnessController.isInIdleMode()
684                 && mIdleModeBrightnessMapper == null)) {
685             Log.w(TAG, "No brightness mapping available to recalculate splines for this mode");
686             return;
687         }
688 
689         float[] adjustedNits = new float[mNitsRange.length];
690         for (int i = 0; i < mNitsRange.length; i++) {
691             adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
692         }
693         mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
694         mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
695     }
696 
697     /**
698      * Returns true if the proximity sensor screen-off function is available.
699      */
isProximitySensorAvailable()700     public boolean isProximitySensorAvailable() {
701         return mProximitySensor != null;
702     }
703 
704     /**
705      * Get the {@link BrightnessChangeEvent}s for the specified user.
706      * @param userId userId to fetch data for
707      * @param includePackage if false will null out the package name in events
708      */
709     @Nullable
getBrightnessEvents( @serIdInt int userId, boolean includePackage)710     public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
711             @UserIdInt int userId, boolean includePackage) {
712         if (mBrightnessTracker == null) {
713             return null;
714         }
715         return mBrightnessTracker.getEvents(userId, includePackage);
716     }
717 
onSwitchUser(@serIdInt int newUserId)718     public void onSwitchUser(@UserIdInt int newUserId) {
719         Message msg = mHandler.obtainMessage(MSG_SWITCH_USER, newUserId);
720         mHandler.sendMessage(msg);
721     }
722 
handleOnSwitchUser(@serIdInt int newUserId)723     private void handleOnSwitchUser(@UserIdInt int newUserId) {
724         handleSettingsChange(true /* userSwitch */);
725         handleBrightnessModeChange();
726         if (mBrightnessTracker != null) {
727             mBrightnessTracker.onSwitchUser(newUserId);
728         }
729     }
730 
731     @Nullable
getAmbientBrightnessStats( @serIdInt int userId)732     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
733             @UserIdInt int userId) {
734         if (mBrightnessTracker == null) {
735             return null;
736         }
737         return mBrightnessTracker.getAmbientBrightnessStats(userId);
738     }
739 
740     /**
741      * Persist the brightness slider events and ambient brightness stats to disk.
742      */
persistBrightnessTrackerState()743     public void persistBrightnessTrackerState() {
744         if (mBrightnessTracker != null) {
745             mBrightnessTracker.persistBrightnessTrackerState();
746         }
747     }
748 
749     /**
750      * Requests a new power state.
751      * The controller makes a copy of the provided object and then
752      * begins adjusting the power state to match what was requested.
753      *
754      * @param request The requested power state.
755      * @param waitForNegativeProximity If true, issues a request to wait for
756      * negative proximity before turning the screen back on, assuming the screen
757      * was turned off by the proximity sensor.
758      * @return True if display is ready, false if there are important changes that must
759      * be made asynchronously (such as turning the screen on), in which case the caller
760      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
761      * then try the request again later until the state converges.
762      */
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)763     public boolean requestPowerState(DisplayPowerRequest request,
764             boolean waitForNegativeProximity) {
765         if (DEBUG) {
766             Slog.d(TAG, "requestPowerState: "
767                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
768         }
769 
770         synchronized (mLock) {
771             if (mStopped) {
772                 return true;
773             }
774 
775             boolean changed = false;
776 
777             if (waitForNegativeProximity
778                     && !mPendingWaitForNegativeProximityLocked) {
779                 mPendingWaitForNegativeProximityLocked = true;
780                 changed = true;
781             }
782 
783             if (mPendingRequestLocked == null) {
784                 mPendingRequestLocked = new DisplayPowerRequest(request);
785                 changed = true;
786             } else if (!mPendingRequestLocked.equals(request)) {
787                 mPendingRequestLocked.copyFrom(request);
788                 changed = true;
789             }
790 
791             if (changed) {
792                 mDisplayReadyLocked = false;
793                 if (!mPendingRequestChangedLocked) {
794                     mPendingRequestChangedLocked = true;
795                     sendUpdatePowerStateLocked();
796                 }
797             }
798 
799             return mDisplayReadyLocked;
800         }
801     }
802 
getDefaultBrightnessConfiguration()803     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
804         if (mAutomaticBrightnessController == null) {
805             return null;
806         }
807         return mAutomaticBrightnessController.getDefaultConfig();
808     }
809 
810     /**
811      * Notified when the display is changed. We use this to apply any changes that might be needed
812      * when displays get swapped on foldable devices.  For example, different brightness properties
813      * of each display need to be properly reflected in AutomaticBrightnessController.
814      */
815     @GuardedBy("DisplayManagerService.mSyncRoot")
onDisplayChanged(HighBrightnessModeMetadata hbmMetadata)816     public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
817         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
818         if (device == null) {
819             Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
820                     + mLogicalDisplay.getDisplayIdLocked());
821             return;
822         }
823 
824         final String uniqueId = device.getUniqueId();
825         final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
826         final IBinder token = device.getDisplayTokenLocked();
827         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
828         final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
829         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
830         mHandler.post(() -> {
831             boolean changed = false;
832             if (mDisplayDevice != device) {
833                 changed = true;
834                 mDisplayDevice = device;
835                 mUniqueDisplayId = uniqueId;
836                 mDisplayStatsId = mUniqueDisplayId.hashCode();
837                 mDisplayDeviceConfig = config;
838                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
839                 loadNitBasedBrightnessSetting();
840 
841                 /// Since the underlying display-device changed, we really don't know the
842                 // last command that was sent to change it's state. Lets assume it is unknown so
843                 // that we trigger a change immediately.
844                 mPowerState.resetScreenState();
845             }
846             if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
847                 changed = true;
848                 mIsEnabled = isEnabled;
849                 mIsInTransition = isInTransition;
850             }
851 
852             if (changed) {
853                 if (DEBUG) {
854                     Trace.beginAsyncSection("DisplayPowerController#updatePowerState", 0);
855                 }
856                 updatePowerState();
857                 if (DEBUG) {
858                     Trace.endAsyncSection("DisplayPowerController#updatePowerState", 0);
859                 }
860             }
861         });
862     }
863 
864     /**
865      * Unregisters all listeners and interrupts all running threads; halting future work.
866      *
867      * This method should be called when the DisplayPowerController is no longer in use; i.e. when
868      * the {@link #mDisplayId display} has been removed.
869      */
stop()870     public void stop() {
871         synchronized (mLock) {
872             mStopped = true;
873             Message msg = mHandler.obtainMessage(MSG_STOP);
874             mHandler.sendMessage(msg);
875 
876             if (mDisplayWhiteBalanceController != null) {
877                 mDisplayWhiteBalanceController.setEnabled(false);
878             }
879 
880             if (mAutomaticBrightnessController != null) {
881                 mAutomaticBrightnessController.stop();
882             }
883 
884             if (mBrightnessSetting != null) {
885                 mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
886             }
887 
888             mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
889         }
890     }
891 
loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info, HighBrightnessModeMetadata hbmMetadata)892     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
893                                              HighBrightnessModeMetadata hbmMetadata) {
894         // All properties that depend on the associated DisplayDevice and the DDC must be
895         // updated here.
896         loadBrightnessRampRates();
897         loadProximitySensor();
898         loadNitsRange(mContext.getResources());
899         setUpAutoBrightness(mContext.getResources(), mHandler);
900         reloadReduceBrightColours();
901         if (mScreenBrightnessRampAnimator != null) {
902             mScreenBrightnessRampAnimator.setAnimationTimeLimits(
903                     mBrightnessRampIncreaseMaxTimeMillis,
904                     mBrightnessRampDecreaseMaxTimeMillis);
905         }
906         mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
907         mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
908                 mDisplayDeviceConfig.getHighBrightnessModeData(),
909                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
910                     @Override
911                     public float getHdrBrightnessFromSdr(float sdrBrightness) {
912                         return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
913                     }
914                 });
915         mBrightnessThrottler.resetThrottlingData(
916                 mDisplayDeviceConfig.getBrightnessThrottlingData(), mUniqueDisplayId);
917     }
918 
sendUpdatePowerState()919     private void sendUpdatePowerState() {
920         synchronized (mLock) {
921             sendUpdatePowerStateLocked();
922         }
923     }
924 
925     @GuardedBy("mLock")
sendUpdatePowerStateLocked()926     private void sendUpdatePowerStateLocked() {
927         if (!mStopped && !mPendingUpdatePowerStateLocked) {
928             mPendingUpdatePowerStateLocked = true;
929             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
930             mHandler.sendMessage(msg);
931         }
932     }
933 
initialize(int displayState)934     private void initialize(int displayState) {
935         mPowerState = new DisplayPowerState(mBlanker,
936                 mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId, displayState);
937 
938         if (mColorFadeEnabled) {
939             mColorFadeOnAnimator = ObjectAnimator.ofFloat(
940                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
941             mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
942             mColorFadeOnAnimator.addListener(mAnimatorListener);
943 
944             mColorFadeOffAnimator = ObjectAnimator.ofFloat(
945                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
946             mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
947             mColorFadeOffAnimator.addListener(mAnimatorListener);
948         }
949 
950         mScreenBrightnessRampAnimator = new DualRampAnimator<>(mPowerState,
951                 DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
952                 DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
953         mScreenBrightnessRampAnimator.setAnimationTimeLimits(
954                 mBrightnessRampIncreaseMaxTimeMillis,
955                 mBrightnessRampDecreaseMaxTimeMillis);
956         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
957 
958         noteScreenState(mPowerState.getScreenState());
959         noteScreenBrightness(mPowerState.getScreenBrightness());
960 
961         // Initialize all of the brightness tracking state
962         final float brightness = convertToNits(mPowerState.getScreenBrightness());
963         if (mBrightnessTracker != null && brightness >= PowerManager.BRIGHTNESS_MIN) {
964             mBrightnessTracker.start(brightness);
965         }
966         mBrightnessSettingListener = brightnessValue -> {
967             Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
968             mHandler.sendMessage(msg);
969         };
970 
971         mBrightnessSetting.registerListener(mBrightnessSettingListener);
972         mContext.getContentResolver().registerContentObserver(
973                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT),
974                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
975         mContext.getContentResolver().registerContentObserver(
976                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
977                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
978         mContext.getContentResolver().registerContentObserver(
979                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
980                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
981         handleBrightnessModeChange();
982     }
983 
setUpAutoBrightness(Resources resources, Handler handler)984     private void setUpAutoBrightness(Resources resources, Handler handler) {
985         mUseSoftwareAutoBrightnessConfig = mDisplayDeviceConfig.isAutoBrightnessAvailable();
986 
987         if (!mUseSoftwareAutoBrightnessConfig) {
988             return;
989         }
990 
991         float userLux = BrightnessMappingStrategy.NO_USER_LUX;
992         float userBrightness = BrightnessMappingStrategy.NO_USER_BRIGHTNESS;
993         if (mInteractiveModeBrightnessMapper != null) {
994             userLux = mInteractiveModeBrightnessMapper.getUserLux();
995             userBrightness = mInteractiveModeBrightnessMapper.getUserBrightness();
996         }
997 
998         final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
999                 R.bool.config_enableIdleScreenBrightnessMode);
1000         mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
1001                 mDisplayDeviceConfig, mDisplayWhiteBalanceController);
1002         if (isIdleScreenBrightnessEnabled) {
1003             mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
1004                     mDisplayDeviceConfig, mDisplayWhiteBalanceController);
1005         }
1006 
1007         if (mInteractiveModeBrightnessMapper != null) {
1008             final float dozeScaleFactor = resources.getFraction(
1009                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
1010                     1, 1);
1011 
1012             // Ambient Lux - Active Mode Brightness Thresholds
1013             float[] ambientBrighteningThresholds =
1014                     mDisplayDeviceConfig.getAmbientBrighteningPercentages();
1015             float[] ambientDarkeningThresholds =
1016                     mDisplayDeviceConfig.getAmbientDarkeningPercentages();
1017             float[] ambientBrighteningLevels =
1018                     mDisplayDeviceConfig.getAmbientBrighteningLevels();
1019             float[] ambientDarkeningLevels =
1020                     mDisplayDeviceConfig.getAmbientDarkeningLevels();
1021             float ambientDarkeningMinThreshold =
1022                     mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
1023             float ambientBrighteningMinThreshold =
1024                     mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
1025             HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
1026                     ambientBrighteningThresholds, ambientDarkeningThresholds,
1027                     ambientBrighteningLevels, ambientDarkeningLevels, ambientDarkeningMinThreshold,
1028                     ambientBrighteningMinThreshold);
1029 
1030             // Display - Active Mode Brightness Thresholds
1031             float[] screenBrighteningThresholds =
1032                     mDisplayDeviceConfig.getScreenBrighteningPercentages();
1033             float[] screenDarkeningThresholds =
1034                     mDisplayDeviceConfig.getScreenDarkeningPercentages();
1035             float[] screenBrighteningLevels =
1036                     mDisplayDeviceConfig.getScreenBrighteningLevels();
1037             float[] screenDarkeningLevels =
1038                     mDisplayDeviceConfig.getScreenDarkeningLevels();
1039             float screenDarkeningMinThreshold =
1040                     mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
1041             float screenBrighteningMinThreshold =
1042                     mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
1043             HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
1044                     screenBrighteningThresholds, screenDarkeningThresholds,
1045                     screenBrighteningLevels, screenDarkeningLevels, screenDarkeningMinThreshold,
1046                     screenBrighteningMinThreshold);
1047 
1048             // Ambient Lux - Idle Screen Brightness Thresholds
1049             float ambientDarkeningMinThresholdIdle =
1050                     mDisplayDeviceConfig.getAmbientLuxDarkeningMinThresholdIdle();
1051             float ambientBrighteningMinThresholdIdle =
1052                     mDisplayDeviceConfig.getAmbientLuxBrighteningMinThresholdIdle();
1053             float[] ambientBrighteningThresholdsIdle =
1054                     mDisplayDeviceConfig.getAmbientBrighteningPercentagesIdle();
1055             float[] ambientDarkeningThresholdsIdle =
1056                     mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle();
1057             float[] ambientBrighteningLevelsIdle =
1058                     mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle();
1059             float[] ambientDarkeningLevelsIdle =
1060                     mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle();
1061             HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels(
1062                     ambientBrighteningThresholdsIdle, ambientDarkeningThresholdsIdle,
1063                     ambientBrighteningLevelsIdle, ambientDarkeningLevelsIdle,
1064                     ambientDarkeningMinThresholdIdle, ambientBrighteningMinThresholdIdle);
1065 
1066             // Display - Idle Screen Brightness Thresholds
1067             float screenDarkeningMinThresholdIdle =
1068                     mDisplayDeviceConfig.getScreenDarkeningMinThresholdIdle();
1069             float screenBrighteningMinThresholdIdle =
1070                     mDisplayDeviceConfig.getScreenBrighteningMinThresholdIdle();
1071             float[] screenBrighteningThresholdsIdle =
1072                     mDisplayDeviceConfig.getScreenBrighteningPercentagesIdle();
1073             float[] screenDarkeningThresholdsIdle =
1074                     mDisplayDeviceConfig.getScreenDarkeningPercentagesIdle();
1075             float[] screenBrighteningLevelsIdle =
1076                     mDisplayDeviceConfig.getScreenBrighteningLevelsIdle();
1077             float[] screenDarkeningLevelsIdle =
1078                     mDisplayDeviceConfig.getScreenDarkeningLevelsIdle();
1079             HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels(
1080                     screenBrighteningThresholdsIdle, screenDarkeningThresholdsIdle,
1081                     screenBrighteningLevelsIdle, screenDarkeningLevelsIdle,
1082                     screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle);
1083 
1084             long brighteningLightDebounce = mDisplayDeviceConfig
1085                     .getAutoBrightnessBrighteningLightDebounce();
1086             long darkeningLightDebounce = mDisplayDeviceConfig
1087                     .getAutoBrightnessDarkeningLightDebounce();
1088             boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
1089                     com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
1090 
1091             int lightSensorWarmUpTimeConfig = resources.getInteger(
1092                     com.android.internal.R.integer.config_lightSensorWarmupTime);
1093             int lightSensorRate = resources.getInteger(
1094                     com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
1095             int initialLightSensorRate = resources.getInteger(
1096                     com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
1097             if (initialLightSensorRate == -1) {
1098                 initialLightSensorRate = lightSensorRate;
1099             } else if (initialLightSensorRate > lightSensorRate) {
1100                 Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
1101                         + initialLightSensorRate + ") to be less than or equal to "
1102                         + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
1103             }
1104 
1105             loadAmbientLightSensor();
1106             // BrightnessTracker should only use one light sensor, we want to use the light sensor
1107             // from the default display and not e.g. temporary displays when switching layouts.
1108             if (mBrightnessTracker != null && mDisplayId == Display.DEFAULT_DISPLAY) {
1109                 mBrightnessTracker.setLightSensor(mLightSensor);
1110             }
1111 
1112             if (mAutomaticBrightnessController != null) {
1113                 mAutomaticBrightnessController.stop();
1114             }
1115             mAutomaticBrightnessController = new AutomaticBrightnessController(this,
1116                     handler.getLooper(), mSensorManager, mLightSensor,
1117                     mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig,
1118                     PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor,
1119                     lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
1120                     darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
1121                     ambientBrightnessThresholds, screenBrightnessThresholds,
1122                     ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext,
1123                     mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper,
1124                     mDisplayDeviceConfig.getAmbientHorizonShort(),
1125                     mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness);
1126 
1127             mBrightnessEventRingBuffer =
1128                     new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
1129 
1130             if (mScreenOffBrightnessSensorController != null) {
1131                 mScreenOffBrightnessSensorController.stop();
1132                 mScreenOffBrightnessSensorController = null;
1133             }
1134             loadScreenOffBrightnessSensor();
1135             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
1136             if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
1137                 mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
1138                         mSensorManager,
1139                         mScreenOffBrightnessSensor,
1140                         mHandler,
1141                         SystemClock::uptimeMillis,
1142                         sensorValueToLux,
1143                         mInteractiveModeBrightnessMapper
1144                 );
1145             }
1146         } else {
1147             mUseSoftwareAutoBrightnessConfig = false;
1148         }
1149     }
1150 
loadBrightnessRampRates()1151     private void loadBrightnessRampRates() {
1152         mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease();
1153         mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
1154         mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
1155         mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
1156         mBrightnessRampDecreaseMaxTimeMillis =
1157                 mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis();
1158         mBrightnessRampIncreaseMaxTimeMillis =
1159                 mDisplayDeviceConfig.getBrightnessRampIncreaseMaxMillis();
1160     }
1161 
loadNitsRange(Resources resources)1162     private void loadNitsRange(Resources resources) {
1163         if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) {
1164             mNitsRange = mDisplayDeviceConfig.getNits();
1165         } else {
1166             Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back");
1167             mNitsRange = BrightnessMappingStrategy.getFloatArray(resources
1168                     .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits));
1169         }
1170     }
1171 
reloadReduceBrightColours()1172     private void reloadReduceBrightColours() {
1173         if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) {
1174             applyReduceBrightColorsSplineAdjustment();
1175         }
1176     }
1177 
setAutomaticScreenBrightnessMode(boolean isIdle)1178     public void setAutomaticScreenBrightnessMode(boolean isIdle) {
1179         if (mAutomaticBrightnessController != null) {
1180             if (isIdle) {
1181                 mAutomaticBrightnessController.switchToIdleMode();
1182             } else {
1183                 mAutomaticBrightnessController.switchToInteractiveScreenBrightnessMode();
1184             }
1185         }
1186         if (mDisplayWhiteBalanceController != null) {
1187             mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
1188         }
1189     }
1190 
1191     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
1192         @Override
1193         public void onAnimationStart(Animator animation) {
1194         }
1195         @Override
1196         public void onAnimationEnd(Animator animation) {
1197             sendUpdatePowerState();
1198         }
1199         @Override
1200         public void onAnimationRepeat(Animator animation) {
1201         }
1202         @Override
1203         public void onAnimationCancel(Animator animation) {
1204         }
1205     };
1206 
1207     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
1208         @Override
1209         public void onAnimationEnd() {
1210             sendUpdatePowerState();
1211             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
1212             mHandler.sendMessage(msg);
1213         }
1214     };
1215 
1216     /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
cleanupHandlerThreadAfterStop()1217     private void cleanupHandlerThreadAfterStop() {
1218         setProximitySensorEnabled(false);
1219         mHbmController.stop();
1220         mBrightnessThrottler.stop();
1221         mHandler.removeCallbacksAndMessages(null);
1222 
1223         // Release any outstanding wakelocks we're still holding because of pending messages.
1224         if (mUnfinishedBusiness) {
1225             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness);
1226             mUnfinishedBusiness = false;
1227         }
1228         if (mOnStateChangedPending) {
1229             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdOnStateChanged);
1230             mOnStateChangedPending = false;
1231         }
1232         for (int i = 0; i < mOnProximityPositiveMessages; i++) {
1233             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxPositive);
1234         }
1235         mOnProximityPositiveMessages = 0;
1236         for (int i = 0; i < mOnProximityNegativeMessages; i++) {
1237             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxNegative);
1238         }
1239         mOnProximityNegativeMessages = 0;
1240 
1241         final float brightness = mPowerState != null
1242             ? mPowerState.getScreenBrightness()
1243             : PowerManager.BRIGHTNESS_MIN;
1244         reportStats(brightness);
1245 
1246         if (mPowerState != null) {
1247             mPowerState.stop();
1248             mPowerState = null;
1249         }
1250 
1251         if (mScreenOffBrightnessSensorController != null) {
1252             mScreenOffBrightnessSensorController.stop();
1253         }
1254     }
1255 
updatePowerState()1256     private void updatePowerState() {
1257         // Update the power state request.
1258         final boolean mustNotify;
1259         final int previousPolicy;
1260         boolean mustInitialize = false;
1261         int brightnessAdjustmentFlags = 0;
1262         mBrightnessReasonTemp.set(null);
1263         mTempBrightnessEvent.reset();
1264         synchronized (mLock) {
1265             if (mStopped) {
1266                 return;
1267             }
1268             mPendingUpdatePowerStateLocked = false;
1269             if (mPendingRequestLocked == null) {
1270                 return; // wait until first actual power request
1271             }
1272 
1273             if (mPowerRequest == null) {
1274                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
1275                 updatePendingProximityRequestsLocked();
1276                 mPendingRequestChangedLocked = false;
1277                 mustInitialize = true;
1278                 // Assume we're on and bright until told otherwise, since that's the state we turn
1279                 // on in.
1280                 previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
1281             } else if (mPendingRequestChangedLocked) {
1282                 previousPolicy = mPowerRequest.policy;
1283                 mPowerRequest.copyFrom(mPendingRequestLocked);
1284                 updatePendingProximityRequestsLocked();
1285                 mPendingRequestChangedLocked = false;
1286                 mDisplayReadyLocked = false;
1287             } else {
1288                 previousPolicy = mPowerRequest.policy;
1289             }
1290 
1291             mustNotify = !mDisplayReadyLocked;
1292         }
1293 
1294         // Compute the basic display state using the policy.
1295         // We might override this below based on other factors.
1296         // Initialise brightness as invalid.
1297         int state;
1298         float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
1299         boolean performScreenOffTransition = false;
1300         switch (mPowerRequest.policy) {
1301             case DisplayPowerRequest.POLICY_OFF:
1302                 state = Display.STATE_OFF;
1303                 performScreenOffTransition = true;
1304                 break;
1305             case DisplayPowerRequest.POLICY_DOZE:
1306                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
1307                     state = mPowerRequest.dozeScreenState;
1308                 } else {
1309                     state = Display.STATE_DOZE;
1310                 }
1311                 if (!mAllowAutoBrightnessWhileDozingConfig) {
1312                     brightnessState = mPowerRequest.dozeScreenBrightness;
1313                     mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
1314                 }
1315                 break;
1316             case DisplayPowerRequest.POLICY_VR:
1317                 state = Display.STATE_VR;
1318                 break;
1319             case DisplayPowerRequest.POLICY_DIM:
1320             case DisplayPowerRequest.POLICY_BRIGHT:
1321             default:
1322                 state = Display.STATE_ON;
1323                 break;
1324         }
1325         assert(state != Display.STATE_UNKNOWN);
1326 
1327         if (mScreenOffBrightnessSensorController != null) {
1328             mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
1329                     && mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
1330                     && !mAllowAutoBrightnessWhileDozingConfig)));
1331         }
1332 
1333         boolean skipRampBecauseOfProximityChangeToNegative = false;
1334         // Apply the proximity sensor.
1335         if (mProximitySensor != null) {
1336             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
1337                 // At this point the policy says that the screen should be on, but we've been
1338                 // asked to listen to the prox sensor to adjust the display state, so lets make
1339                 // sure the sensor is on.
1340                 setProximitySensorEnabled(true);
1341                 if (!mScreenOffBecauseOfProximity
1342                         && mProximity == PROXIMITY_POSITIVE
1343                         && !mIgnoreProximityUntilChanged) {
1344                     // Prox sensor already reporting "near" so we should turn off the screen.
1345                     // Also checked that we aren't currently set to ignore the proximity sensor
1346                     // temporarily.
1347                     mScreenOffBecauseOfProximity = true;
1348                     sendOnProximityPositiveWithWakelock();
1349                 }
1350             } else if (mWaitingForNegativeProximity
1351                     && mScreenOffBecauseOfProximity
1352                     && mProximity == PROXIMITY_POSITIVE
1353                     && state != Display.STATE_OFF) {
1354                 // The policy says that we should have the screen on, but it's off due to the prox
1355                 // and we've been asked to wait until the screen is far from the user to turn it
1356                 // back on. Let keep the prox sensor on so we can tell when it's far again.
1357                 setProximitySensorEnabled(true);
1358             } else {
1359                 // We haven't been asked to use the prox sensor and we're not waiting on the screen
1360                 // to turn back on...so lets shut down the prox sensor.
1361                 setProximitySensorEnabled(false);
1362                 mWaitingForNegativeProximity = false;
1363             }
1364 
1365             if (mScreenOffBecauseOfProximity
1366                     && (mProximity != PROXIMITY_POSITIVE || mIgnoreProximityUntilChanged)) {
1367                 // The screen *was* off due to prox being near, but now it's "far" so lets turn
1368                 // the screen back on.  Also turn it back on if we've been asked to ignore the
1369                 // prox sensor temporarily.
1370                 mScreenOffBecauseOfProximity = false;
1371                 skipRampBecauseOfProximityChangeToNegative = true;
1372                 sendOnProximityNegativeWithWakelock();
1373             }
1374         } else {
1375             setProximitySensorEnabled(false);
1376             mWaitingForNegativeProximity = false;
1377             mIgnoreProximityUntilChanged = false;
1378 
1379             if (mScreenOffBecauseOfProximity) {
1380                 // The screen *was* off due to prox being near, but now there's no prox sensor, so
1381                 // let's turn the screen back on.
1382                 mScreenOffBecauseOfProximity = false;
1383                 skipRampBecauseOfProximityChangeToNegative = true;
1384                 sendOnProximityNegativeWithWakelock();
1385             }
1386         }
1387 
1388         if (!mIsEnabled
1389                 || mIsInTransition
1390                 || mScreenOffBecauseOfProximity) {
1391             state = Display.STATE_OFF;
1392         }
1393 
1394         // Initialize things the first time the power state is changed.
1395         if (mustInitialize) {
1396             initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
1397         }
1398 
1399         // Animate the screen state change unless already animating.
1400         // The transition may be deferred, so after this point we will use the
1401         // actual state instead of the desired one.
1402         final int oldState = mPowerState.getScreenState();
1403         animateScreenStateChange(state, performScreenOffTransition);
1404         state = mPowerState.getScreenState();
1405 
1406         if (state == Display.STATE_OFF) {
1407             brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
1408             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
1409         }
1410 
1411         // Always use the VR brightness when in the VR state.
1412         if (state == Display.STATE_VR) {
1413             brightnessState = mScreenBrightnessForVr;
1414             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
1415         }
1416 
1417         if ((Float.isNaN(brightnessState))
1418                 && isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
1419             brightnessState = mPowerRequest.screenBrightnessOverride;
1420             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
1421             mAppliedScreenBrightnessOverride = true;
1422         } else {
1423             mAppliedScreenBrightnessOverride = false;
1424         }
1425 
1426         final boolean autoBrightnessEnabledInDoze =
1427                 mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
1428         final boolean autoBrightnessEnabled = mUseAutoBrightness
1429                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
1430                     && Float.isNaN(brightnessState)
1431                     && mAutomaticBrightnessController != null;
1432         final boolean autoBrightnessDisabledDueToDisplayOff = mUseAutoBrightness
1433                     && !(state == Display.STATE_ON || autoBrightnessEnabledInDoze);
1434         final int autoBrightnessState = autoBrightnessEnabled
1435                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
1436                 : autoBrightnessDisabledDueToDisplayOff
1437                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
1438                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
1439 
1440         final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
1441 
1442         // Use the temporary screen brightness if there isn't an override, either from
1443         // WindowManager or based on the display state.
1444         if (isValidBrightnessValue(mTemporaryScreenBrightness)) {
1445             brightnessState = mTemporaryScreenBrightness;
1446             mAppliedTemporaryBrightness = true;
1447             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
1448         } else {
1449             mAppliedTemporaryBrightness = false;
1450         }
1451 
1452         final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
1453 
1454         // Use the autobrightness adjustment override if set.
1455         final float autoBrightnessAdjustment;
1456         if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
1457             autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
1458             brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO_TEMP;
1459             mAppliedTemporaryAutoBrightnessAdjustment = true;
1460         } else {
1461             autoBrightnessAdjustment = mAutoBrightnessAdjustment;
1462             brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO;
1463             mAppliedTemporaryAutoBrightnessAdjustment = false;
1464         }
1465         // Apply brightness boost.
1466         // We do this here after deciding whether auto-brightness is enabled so that we don't
1467         // disable the light sensor during this temporary state.  That way when boost ends we will
1468         // be able to resume normal auto-brightness behavior without any delay.
1469         if (mPowerRequest.boostScreenBrightness
1470                 && brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT) {
1471             brightnessState = PowerManager.BRIGHTNESS_MAX;
1472             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
1473             mAppliedBrightnessBoost = true;
1474         } else {
1475             mAppliedBrightnessBoost = false;
1476         }
1477 
1478         // If the brightness is already set then it's been overridden by something other than the
1479         // user, or is a temporary adjustment.
1480         boolean userInitiatedChange = (Float.isNaN(brightnessState))
1481                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
1482         boolean hadUserBrightnessPoint = false;
1483         // Configure auto-brightness.
1484         if (mAutomaticBrightnessController != null) {
1485             hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
1486             mAutomaticBrightnessController.configure(autoBrightnessState,
1487                     mBrightnessConfiguration,
1488                     mLastUserSetScreenBrightness,
1489                     userSetBrightnessChanged, autoBrightnessAdjustment,
1490                     autoBrightnessAdjustmentChanged, mPowerRequest.policy,
1491                     mShouldResetShortTermModel);
1492             mShouldResetShortTermModel = false;
1493         }
1494 
1495         if (mBrightnessTracker != null) {
1496             mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
1497         }
1498 
1499         boolean updateScreenBrightnessSetting = false;
1500 
1501         // Apply auto-brightness.
1502         boolean slowChange = false;
1503         if (Float.isNaN(brightnessState)) {
1504             float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
1505             if (autoBrightnessEnabled) {
1506                 brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness(
1507                         mTempBrightnessEvent);
1508                 newAutoBrightnessAdjustment =
1509                         mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
1510             }
1511             if (isValidBrightnessValue(brightnessState)
1512                     || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
1513                 // Use current auto-brightness value and slowly adjust to changes.
1514                 brightnessState = clampScreenBrightness(brightnessState);
1515                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
1516                     slowChange = true; // slowly adapt to auto-brightness
1517                 }
1518                 updateScreenBrightnessSetting = mCurrentScreenBrightnessSetting != brightnessState;
1519                 mAppliedAutoBrightness = true;
1520                 mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
1521                 if (mScreenOffBrightnessSensorController != null) {
1522                     mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
1523                 }
1524             } else {
1525                 mAppliedAutoBrightness = false;
1526             }
1527             if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
1528                 // If the autobrightness controller has decided to change the adjustment value
1529                 // used, make sure that's reflected in settings.
1530                 putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
1531             } else {
1532                 // Adjustment values resulted in no change
1533                 brightnessAdjustmentFlags = 0;
1534             }
1535         } else {
1536             // Any non-auto-brightness values such as override or temporary should still be subject
1537             // to clamping so that they don't go beyond the current max as specified by HBM
1538             // Controller.
1539             brightnessState = clampScreenBrightness(brightnessState);
1540             mAppliedAutoBrightness = false;
1541             brightnessAdjustmentFlags = 0;
1542         }
1543 
1544         // Use default brightness when dozing unless overridden.
1545         if ((Float.isNaN(brightnessState))
1546                 && Display.isDozeState(state)) {
1547             brightnessState = clampScreenBrightness(mScreenBrightnessDozeConfig);
1548             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
1549         }
1550 
1551         // The ALS is not available yet - use the screen off sensor to determine the initial
1552         // brightness
1553         if (Float.isNaN(brightnessState) && autoBrightnessEnabled
1554                 && mScreenOffBrightnessSensorController != null) {
1555             brightnessState = mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
1556             if (isValidBrightnessValue(brightnessState)) {
1557                 brightnessState = clampScreenBrightness(brightnessState);
1558                 updateScreenBrightnessSetting = mCurrentScreenBrightnessSetting != brightnessState;
1559                 mBrightnessReasonTemp.setReason(
1560                         BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
1561             }
1562         }
1563 
1564         // Apply manual brightness.
1565         if (Float.isNaN(brightnessState)) {
1566             brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
1567             if (brightnessState != mCurrentScreenBrightnessSetting) {
1568                 // The manually chosen screen brightness is outside of the currently allowed
1569                 // range (i.e., high-brightness-mode), make sure we tell the rest of the system
1570                 // by updating the setting.
1571                 updateScreenBrightnessSetting = true;
1572             }
1573             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
1574         }
1575 
1576         // Now that a desired brightness has been calculated, apply brightness throttling. The
1577         // dimming and low power transformations that follow can only dim brightness further.
1578         //
1579         // We didn't do this earlier through brightness clamping because we need to know both
1580         // unthrottled (unclamped/ideal) and throttled brightness levels for subsequent operations.
1581         // Note throttling effectively changes the allowed brightness range, so, similarly to HBM,
1582         // we broadcast this change through setting.
1583         final float unthrottledBrightnessState = brightnessState;
1584         if (mBrightnessThrottler.isThrottled()) {
1585             mTempBrightnessEvent.thermalMax = mBrightnessThrottler.getBrightnessCap();
1586             brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
1587             mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
1588             if (!mAppliedThrottling) {
1589                 // Brightness throttling is needed, so do so quickly.
1590                 // Later, when throttling is removed, we let other mechanisms decide on speed.
1591                 slowChange = false;
1592             }
1593             mAppliedThrottling = true;
1594         } else if (mAppliedThrottling) {
1595             mAppliedThrottling = false;
1596         }
1597 
1598         if (updateScreenBrightnessSetting) {
1599             // Tell the rest of the system about the new brightness in case we had to change it
1600             // for things like auto-brightness or high-brightness-mode. Note that we do this
1601             // before applying the low power or dim transformations so that the slider
1602             // accurately represents the full possible range, even if they range changes what
1603             // it means in absolute terms.
1604             updateScreenBrightnessSetting(brightnessState);
1605         }
1606 
1607         // Apply dimming by at least some minimum amount when user activity
1608         // timeout is about to expire.
1609         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
1610             if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
1611                 brightnessState = Math.max(
1612                         Math.min(brightnessState - mScreenBrightnessMinimumDimAmount,
1613                                 mScreenBrightnessDimConfig),
1614                         PowerManager.BRIGHTNESS_MIN);
1615                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
1616             }
1617             if (!mAppliedDimming) {
1618                 slowChange = false;
1619             }
1620             mAppliedDimming = true;
1621         } else if (mAppliedDimming) {
1622             slowChange = false;
1623             mAppliedDimming = false;
1624         }
1625         // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
1626         // as long as it is above the minimum threshold.
1627         if (mPowerRequest.lowPowerMode) {
1628             if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
1629                 final float brightnessFactor =
1630                         Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
1631                 final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
1632                 brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN);
1633                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
1634             }
1635             if (!mAppliedLowPower) {
1636                 slowChange = false;
1637             }
1638             mAppliedLowPower = true;
1639         } else if (mAppliedLowPower) {
1640             slowChange = false;
1641             mAppliedLowPower = false;
1642         }
1643 
1644         // The current brightness to use has been calculated at this point, and HbmController should
1645         // be notified so that it can accurately calculate HDR or HBM levels. We specifically do it
1646         // here instead of having HbmController listen to the brightness setting because certain
1647         // brightness sources (such as an app override) are not saved to the setting, but should be
1648         // reflected in HBM calculations.
1649         mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
1650                 mBrightnessThrottler.getBrightnessMaxReason());
1651 
1652         // Animate the screen brightness when the screen is on or dozing.
1653         // Skip the animation when the screen is off or suspended or transition to/from VR.
1654         boolean brightnessAdjusted = false;
1655         final boolean brightnessIsTemporary =
1656                 mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
1657         if (!mPendingScreenOff) {
1658             if (mSkipScreenOnBrightnessRamp) {
1659                 if (state == Display.STATE_ON) {
1660                     if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
1661                         mInitialAutoBrightness = brightnessState;
1662                         mSkipRampState = RAMP_STATE_SKIP_INITIAL;
1663                     } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
1664                             && mUseSoftwareAutoBrightnessConfig
1665                             && !BrightnessSynchronizer.floatEquals(brightnessState,
1666                             mInitialAutoBrightness)) {
1667                         mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
1668                     } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
1669                         mSkipRampState = RAMP_STATE_SKIP_NONE;
1670                     }
1671                 } else {
1672                     mSkipRampState = RAMP_STATE_SKIP_NONE;
1673                 }
1674             }
1675 
1676             final boolean wasOrWillBeInVr =
1677                     (state == Display.STATE_VR || oldState == Display.STATE_VR);
1678             final boolean initialRampSkip = (state == Display.STATE_ON && mSkipRampState
1679                     != RAMP_STATE_SKIP_NONE) || skipRampBecauseOfProximityChangeToNegative;
1680             // While dozing, sometimes the brightness is split into buckets. Rather than animating
1681             // through the buckets, which is unlikely to be smooth in the first place, just jump
1682             // right to the suggested brightness.
1683             final boolean hasBrightnessBuckets =
1684                     Display.isDozeState(state) && mBrightnessBucketsInDozeConfig;
1685             // If the color fade is totally covering the screen then we can change the backlight
1686             // level without it being a noticeable jump since any actual content isn't yet visible.
1687             final boolean isDisplayContentVisible =
1688                     mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
1689             // We only want to animate the brightness if it is between 0.0f and 1.0f.
1690             // brightnessState can contain the values -1.0f and NaN, which we do not want to
1691             // animate to. To avoid this, we check the value first.
1692             // If the brightnessState is off (-1.0f) we still want to animate to the minimum
1693             // brightness (0.0f) to accommodate for LED displays, which can appear bright to the
1694             // user even when the display is all black. We also clamp here in case some
1695             // transformations to the brightness have pushed it outside of the currently
1696             // allowed range.
1697             float animateValue = clampScreenBrightness(brightnessState);
1698 
1699             // If there are any HDR layers on the screen, we have a special brightness value that we
1700             // use instead. We still preserve the calculated brightness for Standard Dynamic Range
1701             // (SDR) layers, but the main brightness value will be the one for HDR.
1702             float sdrAnimateValue = animateValue;
1703             // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
1704             // done in HighBrightnessModeController.
1705             if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
1706                     && ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
1707                     || (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
1708                 // We want to scale HDR brightness level with the SDR level
1709                 animateValue = mHbmController.getHdrBrightnessValue();
1710             }
1711 
1712             final float currentBrightness = mPowerState.getScreenBrightness();
1713             final float currentSdrBrightness = mPowerState.getSdrScreenBrightness();
1714             if (isValidBrightnessValue(animateValue)
1715                     && (animateValue != currentBrightness
1716                     || sdrAnimateValue != currentSdrBrightness)) {
1717                 if (initialRampSkip || hasBrightnessBuckets
1718                         || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
1719                     animateScreenBrightness(animateValue, sdrAnimateValue,
1720                             SCREEN_ANIMATION_RATE_MINIMUM);
1721                 } else {
1722                     boolean isIncreasing = animateValue > currentBrightness;
1723                     final float rampSpeed;
1724                     if (isIncreasing && slowChange) {
1725                         rampSpeed = mBrightnessRampRateSlowIncrease;
1726                     } else if (isIncreasing && !slowChange) {
1727                         rampSpeed = mBrightnessRampRateFastIncrease;
1728                     } else if (!isIncreasing && slowChange) {
1729                         rampSpeed = mBrightnessRampRateSlowDecrease;
1730                     } else {
1731                         rampSpeed = mBrightnessRampRateFastDecrease;
1732                     }
1733                     animateScreenBrightness(animateValue, sdrAnimateValue, rampSpeed);
1734                 }
1735             }
1736 
1737             // Report brightness to brightnesstracker:
1738             // If brightness is not temporary (ie the slider has been released)
1739             // AND if we are not in idle screen brightness mode.
1740             if (!brightnessIsTemporary
1741                     && (mAutomaticBrightnessController != null
1742                             && !mAutomaticBrightnessController.isInIdleMode())) {
1743                 if (userInitiatedChange && (mAutomaticBrightnessController == null
1744                             || !mAutomaticBrightnessController.hasValidAmbientLux())) {
1745                     // If we don't have a valid lux reading we can't report a valid
1746                     // slider event so notify as if the system changed the brightness.
1747                     userInitiatedChange = false;
1748                 }
1749                 notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
1750                         hadUserBrightnessPoint);
1751             }
1752 
1753             // We save the brightness info *after* the brightness setting has been changed and
1754             // adjustments made so that the brightness info reflects the latest value.
1755             brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
1756         } else {
1757             brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting());
1758         }
1759 
1760         // Only notify if the brightness adjustment is not temporary (i.e. slider has been released)
1761         if (brightnessAdjusted && !brightnessIsTemporary) {
1762             postBrightnessChangeRunnable();
1763         }
1764 
1765         // Log any changes to what is currently driving the brightness setting.
1766         if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
1767             Slog.v(TAG, "Brightness [" + brightnessState + "] reason changing to: '"
1768                     + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
1769                     + "', previous reason: '" + mBrightnessReason + "'.");
1770             mBrightnessReason.set(mBrightnessReasonTemp);
1771         } else if (mBrightnessReasonTemp.reason == BrightnessReason.REASON_MANUAL
1772                 && userSetBrightnessChanged) {
1773             Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment.");
1774         }
1775 
1776 
1777         // Log brightness events when a detail of significance has changed. Generally this is the
1778         // brightness itself changing, but also includes data like HBM cap, thermal throttling
1779         // brightness cap, RBC state, etc.
1780         mTempBrightnessEvent.time = System.currentTimeMillis();
1781         mTempBrightnessEvent.brightness = brightnessState;
1782         mTempBrightnessEvent.reason.set(mBrightnessReason);
1783         mTempBrightnessEvent.hbmMax = mHbmController.getCurrentBrightnessMax();
1784         mTempBrightnessEvent.hbmMode = mHbmController.getHighBrightnessMode();
1785         mTempBrightnessEvent.flags = (mTempBrightnessEvent.flags
1786                 | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
1787                 | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
1788         mTempBrightnessEvent.physicalDisplayId = mUniqueDisplayId;
1789         mTempBrightnessEvent.rbcStrength = mCdsi != null
1790                 ? mCdsi.getReduceBrightColorsStrength() : -1;
1791         mTempBrightnessEvent.powerFactor = mPowerRequest.screenLowPowerBrightnessFactor;
1792         mTempBrightnessEvent.wasShortTermModelActive = hadUserBrightnessPoint;
1793         // Temporary is what we use during slider interactions. We avoid logging those so that
1794         // we don't spam logcat when the slider is being used.
1795         boolean tempToTempTransition =
1796                 mTempBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY
1797                 && mLastBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY;
1798         if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
1799                 || brightnessAdjustmentFlags != 0) {
1800             float lastBrightness = mLastBrightnessEvent.brightness;
1801             mTempBrightnessEvent.initialBrightness = lastBrightness;
1802             mTempBrightnessEvent.automaticBrightnessEnabled = mUseAutoBrightness;
1803             mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
1804             BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
1805 
1806             // Adjustment flags (and user-set flag) only get added after the equality checks since
1807             // they are transient.
1808             newEvent.adjustmentFlags = brightnessAdjustmentFlags;
1809             newEvent.flags |= (userSetBrightnessChanged ? BrightnessEvent.FLAG_USER_SET : 0);
1810             Slog.i(TAG, newEvent.toString(/* includeTime= */ false));
1811 
1812             if (userSetBrightnessChanged) {
1813                 logManualBrightnessEvent(newEvent);
1814             }
1815             if (mBrightnessEventRingBuffer != null) {
1816                 mBrightnessEventRingBuffer.append(newEvent);
1817             }
1818         }
1819 
1820         // Update display white-balance.
1821         if (mDisplayWhiteBalanceController != null) {
1822             if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
1823                 mDisplayWhiteBalanceController.setEnabled(true);
1824                 mDisplayWhiteBalanceController.updateDisplayColorTemperature();
1825             } else {
1826                 mDisplayWhiteBalanceController.setEnabled(false);
1827             }
1828         }
1829 
1830         // Determine whether the display is ready for use in the newly requested state.
1831         // Note that we do not wait for the brightness ramp animation to complete before
1832         // reporting the display is ready because we only need to ensure the screen is in the
1833         // right power state even as it continues to converge on the desired brightness.
1834         final boolean ready = mPendingScreenOnUnblocker == null &&
1835                 (!mColorFadeEnabled ||
1836                         (!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
1837                 && mPowerState.waitUntilClean(mCleanListener);
1838         final boolean finished = ready
1839                 && !mScreenBrightnessRampAnimator.isAnimating();
1840 
1841         // Notify policy about screen turned on.
1842         if (ready && state != Display.STATE_OFF
1843                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
1844             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
1845             mWindowManagerPolicy.screenTurnedOn(mDisplayId);
1846         }
1847 
1848         // Grab a wake lock if we have unfinished business.
1849         if (!finished && !mUnfinishedBusiness) {
1850             if (DEBUG) {
1851                 Slog.d(TAG, "Unfinished business...");
1852             }
1853             mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness);
1854             mUnfinishedBusiness = true;
1855         }
1856 
1857         // Notify the power manager when ready.
1858         if (ready && mustNotify) {
1859             // Send state change.
1860             synchronized (mLock) {
1861                 if (!mPendingRequestChangedLocked) {
1862                     mDisplayReadyLocked = true;
1863 
1864                     if (DEBUG) {
1865                         Slog.d(TAG, "Display ready!");
1866                     }
1867                 }
1868             }
1869             sendOnStateChangedWithWakelock();
1870         }
1871 
1872         // Release the wake lock when we have no unfinished business.
1873         if (finished && mUnfinishedBusiness) {
1874             if (DEBUG) {
1875                 Slog.d(TAG, "Finished business...");
1876             }
1877             mUnfinishedBusiness = false;
1878             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness);
1879         }
1880 
1881         // Record if dozing for future comparison.
1882         mDozing = state != Display.STATE_ON;
1883 
1884         if (previousPolicy != mPowerRequest.policy) {
1885             logDisplayPolicyChanged(mPowerRequest.policy);
1886         }
1887     }
1888 
1889     @Override
updateBrightness()1890     public void updateBrightness() {
1891         sendUpdatePowerState();
1892     }
1893 
1894     /**
1895      * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
1896      * currently enabled and forcing the screen to be dark.
1897      */
ignoreProximitySensorUntilChanged()1898     public void ignoreProximitySensorUntilChanged() {
1899         mHandler.sendEmptyMessage(MSG_IGNORE_PROXIMITY);
1900     }
1901 
setBrightnessConfiguration(BrightnessConfiguration c, boolean shouldResetShortTermModel)1902     public void setBrightnessConfiguration(BrightnessConfiguration c,
1903             boolean shouldResetShortTermModel) {
1904         Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS,
1905                 shouldResetShortTermModel ? 1 : 0, /* unused */ 0, c);
1906         msg.sendToTarget();
1907     }
1908 
setTemporaryBrightness(float brightness)1909     public void setTemporaryBrightness(float brightness) {
1910         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
1911                 Float.floatToIntBits(brightness), 0 /*unused*/);
1912         msg.sendToTarget();
1913     }
1914 
setTemporaryAutoBrightnessAdjustment(float adjustment)1915     public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
1916         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
1917                 Float.floatToIntBits(adjustment), 0 /*unused*/);
1918         msg.sendToTarget();
1919     }
1920 
getBrightnessInfo()1921     public BrightnessInfo getBrightnessInfo() {
1922         synchronized (mCachedBrightnessInfo) {
1923             return new BrightnessInfo(
1924                     mCachedBrightnessInfo.brightness.value,
1925                     mCachedBrightnessInfo.adjustedBrightness.value,
1926                     mCachedBrightnessInfo.brightnessMin.value,
1927                     mCachedBrightnessInfo.brightnessMax.value,
1928                     mCachedBrightnessInfo.hbmMode.value,
1929                     mCachedBrightnessInfo.hbmTransitionPoint.value,
1930                     mCachedBrightnessInfo.brightnessMaxReason.value);
1931         }
1932     }
1933 
saveBrightnessInfo(float brightness)1934     private boolean saveBrightnessInfo(float brightness) {
1935         return saveBrightnessInfo(brightness, brightness);
1936     }
1937 
saveBrightnessInfo(float brightness, float adjustedBrightness)1938     private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
1939         synchronized (mCachedBrightnessInfo) {
1940             final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
1941                     mBrightnessThrottler.getBrightnessCap());
1942             final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
1943                     mBrightnessThrottler.getBrightnessCap());
1944             boolean changed = false;
1945 
1946             changed |=
1947                 mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
1948                         brightness);
1949             changed |=
1950                 mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
1951                         adjustedBrightness);
1952             changed |=
1953                 mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
1954                         minBrightness);
1955             changed |=
1956                 mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
1957                         maxBrightness);
1958             changed |=
1959                 mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
1960                         mHbmController.getHighBrightnessMode());
1961             changed |=
1962                 mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
1963                         mHbmController.getTransitionPoint());
1964             changed |=
1965                 mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
1966                         mBrightnessThrottler.getBrightnessMaxReason());
1967 
1968             return changed;
1969         }
1970     }
1971 
postBrightnessChangeRunnable()1972     void postBrightnessChangeRunnable() {
1973         mHandler.post(mOnBrightnessChangeRunnable);
1974     }
1975 
createHbmControllerLocked()1976     private HighBrightnessModeController createHbmControllerLocked() {
1977         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
1978         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
1979         final IBinder displayToken =
1980                 mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked();
1981         final String displayUniqueId =
1982                 mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
1983         final DisplayDeviceConfig.HighBrightnessModeData hbmData =
1984                 ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
1985         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1986         return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken,
1987                 displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
1988                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
1989                     @Override
1990                     public float getHdrBrightnessFromSdr(float sdrBrightness) {
1991                         return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
1992                     }
1993                 },
1994                 () -> {
1995                     sendUpdatePowerStateLocked();
1996                     postBrightnessChangeRunnable();
1997                     // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
1998                     if (mAutomaticBrightnessController != null) {
1999                         mAutomaticBrightnessController.update();
2000                     }
2001                 }, mHighBrightnessModeMetadata, mContext);
2002     }
2003 
2004     private BrightnessThrottler createBrightnessThrottlerLocked() {
2005         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
2006         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
2007         final DisplayDeviceConfig.BrightnessThrottlingData data =
2008                 ddConfig != null ? ddConfig.getBrightnessThrottlingData() : null;
2009         return new BrightnessThrottler(mHandler, data,
2010                 () -> {
2011                     sendUpdatePowerStateLocked();
2012                     postBrightnessChangeRunnable();
2013                 }, mUniqueDisplayId);
2014     }
2015 
2016     private void blockScreenOn() {
2017         if (mPendingScreenOnUnblocker == null) {
2018             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
2019             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
2020             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
2021             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
2022         }
2023     }
2024 
2025     private void unblockScreenOn() {
2026         if (mPendingScreenOnUnblocker != null) {
2027             mPendingScreenOnUnblocker = null;
2028             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
2029             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
2030             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
2031         }
2032     }
2033 
2034     private void blockScreenOff() {
2035         if (mPendingScreenOffUnblocker == null) {
2036             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
2037             mPendingScreenOffUnblocker = new ScreenOffUnblocker();
2038             mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
2039             Slog.i(TAG, "Blocking screen off");
2040         }
2041     }
2042 
2043     private void unblockScreenOff() {
2044         if (mPendingScreenOffUnblocker != null) {
2045             mPendingScreenOffUnblocker = null;
2046             long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
2047             Slog.i(TAG, "Unblocked screen off after " + delay + " ms");
2048             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
2049         }
2050     }
2051 
2052     private boolean setScreenState(int state) {
2053         return setScreenState(state, false /*reportOnly*/);
2054     }
2055 
2056     private boolean setScreenState(int state, boolean reportOnly) {
2057         final boolean isOff = (state == Display.STATE_OFF);
2058 
2059         if (mPowerState.getScreenState() != state
2060                 || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
2061             // If we are trying to turn screen off, give policy a chance to do something before we
2062             // actually turn the screen off.
2063             if (isOff && !mScreenOffBecauseOfProximity) {
2064                 if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON
2065                         || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
2066                     setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
2067                     blockScreenOff();
2068                     mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
2069                     unblockScreenOff();
2070                 } else if (mPendingScreenOffUnblocker != null) {
2071                     // Abort doing the state change until screen off is unblocked.
2072                     return false;
2073                 }
2074             }
2075 
2076             if (!reportOnly && mPowerState.getScreenState() != state
2077                     && readyToUpdateDisplayState()) {
2078                 Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
2079                 // TODO(b/153319140) remove when we can get this from the above trace invocation
2080                 SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
2081                 mPowerState.setScreenState(state);
2082                 // Tell battery stats about the transition.
2083                 noteScreenState(state);
2084             }
2085         }
2086 
2087         // Tell the window manager policy when the screen is turned off or on unless it's due
2088         // to the proximity sensor.  We temporarily block turning the screen on until the
2089         // window manager is ready by leaving a black surface covering the screen.
2090         // This surface is essentially the final state of the color fade animation and
2091         // it is only removed once the window manager tells us that the activity has
2092         // finished drawing underneath.
2093         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
2094                 && !mScreenOffBecauseOfProximity) {
2095             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
2096             unblockScreenOn();
2097             mWindowManagerPolicy.screenTurnedOff(mDisplayId);
2098         } else if (!isOff
2099                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
2100 
2101             // We told policy already that screen was turning off, but now we changed our minds.
2102             // Complete the full state transition on -> turningOff -> off.
2103             unblockScreenOff();
2104             mWindowManagerPolicy.screenTurnedOff(mDisplayId);
2105             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
2106         }
2107         if (!isOff
2108                 && (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
2109                         || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
2110             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
2111             if (mPowerState.getColorFadeLevel() == 0.0f) {
2112                 blockScreenOn();
2113             } else {
2114                 unblockScreenOn();
2115             }
2116             mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
2117         }
2118 
2119         // Return true if the screen isn't blocked.
2120         return mPendingScreenOnUnblocker == null;
2121     }
2122 
2123     private void setReportedScreenState(int state) {
2124         Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
2125         mReportedScreenStateToPolicy = state;
2126     }
2127 
2128     private void loadAmbientLightSensor() {
2129         DisplayDeviceConfig.SensorData lightSensor = mDisplayDeviceConfig.getAmbientLightSensor();
2130         final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
2131                 ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK;
2132         mLightSensor = SensorUtils.findSensor(mSensorManager, lightSensor.type, lightSensor.name,
2133                 fallbackType);
2134     }
2135 
2136     private void loadScreenOffBrightnessSensor() {
2137         DisplayDeviceConfig.SensorData screenOffBrightnessSensor =
2138                 mDisplayDeviceConfig.getScreenOffBrightnessSensor();
2139         mScreenOffBrightnessSensor = SensorUtils.findSensor(mSensorManager,
2140                 screenOffBrightnessSensor.type, screenOffBrightnessSensor.name,
2141                 SensorUtils.NO_FALLBACK);
2142     }
2143 
2144     private void loadProximitySensor() {
2145         if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
2146             return;
2147         }
2148         final DisplayDeviceConfig.SensorData proxSensor =
2149                 mDisplayDeviceConfig.getProximitySensor();
2150         final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
2151                 ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK;
2152         mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name,
2153                 fallbackType);
2154         if (mProximitySensor != null) {
2155             mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
2156                     TYPICAL_PROXIMITY_THRESHOLD);
2157         }
2158     }
2159 
2160     private float clampScreenBrightnessForVr(float value) {
2161         return MathUtils.constrain(
2162                 value, mScreenBrightnessForVrRangeMinimum,
2163                 mScreenBrightnessForVrRangeMaximum);
2164     }
2165 
2166     private float clampScreenBrightness(float value) {
2167         if (Float.isNaN(value)) {
2168             value = PowerManager.BRIGHTNESS_MIN;
2169         }
2170         return MathUtils.constrain(value,
2171                 mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax());
2172     }
2173 
2174     // Checks whether the brightness is within the valid brightness range, not including off.
2175     private boolean isValidBrightnessValue(float brightness) {
2176         return brightness >= PowerManager.BRIGHTNESS_MIN
2177                 && brightness <= PowerManager.BRIGHTNESS_MAX;
2178     }
2179 
2180     private void animateScreenBrightness(float target, float sdrTarget, float rate) {
2181         if (DEBUG) {
2182             Slog.d(TAG, "Animating brightness: target=" + target + ", sdrTarget=" + sdrTarget
2183                     + ", rate=" + rate);
2184         }
2185         if (mScreenBrightnessRampAnimator.animateTo(target, sdrTarget, rate)) {
2186             Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
2187             // TODO(b/153319140) remove when we can get this from the above trace invocation
2188             SystemProperties.set("debug.tracing.screen_brightness", String.valueOf(target));
2189             noteScreenBrightness(target);
2190         }
2191     }
2192 
2193     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
2194         // If there is already an animation in progress, don't interfere with it.
2195         if (mColorFadeEnabled &&
2196                 (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
2197             if (target != Display.STATE_ON) {
2198                 return;
2199             }
2200             // If display state changed to on, proceed and stop the color fade and turn screen on.
2201             mPendingScreenOff = false;
2202         }
2203 
2204         if (mDisplayBlanksAfterDozeConfig
2205                 && Display.isDozeState(mPowerState.getScreenState())
2206                 && !Display.isDozeState(target)) {
2207             // Skip the screen off animation and add a black surface to hide the
2208             // contents of the screen.
2209             mPowerState.prepareColorFade(mContext,
2210                     mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
2211             if (mColorFadeOffAnimator != null) {
2212                 mColorFadeOffAnimator.end();
2213             }
2214             // Some display hardware will blank itself on the transition between doze and non-doze
2215             // but still on display states. In this case we want to report to policy that the
2216             // display has turned off so it can prepare the appropriate power on animation, but we
2217             // don't want to actually transition to the fully off state since that takes
2218             // significantly longer to transition from.
2219             setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
2220         }
2221 
2222         // If we were in the process of turning off the screen but didn't quite
2223         // finish.  Then finish up now to prevent a jarring transition back
2224         // to screen on if we skipped blocking screen on as usual.
2225         if (mPendingScreenOff && target != Display.STATE_OFF) {
2226             setScreenState(Display.STATE_OFF);
2227             mPendingScreenOff = false;
2228             mPowerState.dismissColorFadeResources();
2229         }
2230 
2231         if (target == Display.STATE_ON) {
2232             // Want screen on.  The contents of the screen may not yet
2233             // be visible if the color fade has not been dismissed because
2234             // its last frame of animation is solid black.
2235             if (!setScreenState(Display.STATE_ON)) {
2236                 return; // screen on blocked
2237             }
2238             if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
2239                 // Perform screen on animation.
2240                 if (mPowerState.getColorFadeLevel() == 1.0f) {
2241                     mPowerState.dismissColorFade();
2242                 } else if (mPowerState.prepareColorFade(mContext,
2243                         mColorFadeFadesConfig ?
2244                                 ColorFade.MODE_FADE :
2245                                         ColorFade.MODE_WARM_UP)) {
2246                     mColorFadeOnAnimator.start();
2247                 } else {
2248                     mColorFadeOnAnimator.end();
2249                 }
2250             } else {
2251                 // Skip screen on animation.
2252                 mPowerState.setColorFadeLevel(1.0f);
2253                 mPowerState.dismissColorFade();
2254             }
2255         } else if (target == Display.STATE_VR) {
2256             // Wait for brightness animation to complete beforehand when entering VR
2257             // from screen on to prevent a perceptible jump because brightness may operate
2258             // differently when the display is configured for dozing.
2259             if (mScreenBrightnessRampAnimator.isAnimating()
2260                     && mPowerState.getScreenState() == Display.STATE_ON) {
2261                 return;
2262             }
2263 
2264             // Set screen state.
2265             if (!setScreenState(Display.STATE_VR)) {
2266                 return; // screen on blocked
2267             }
2268 
2269             // Dismiss the black surface without fanfare.
2270             mPowerState.setColorFadeLevel(1.0f);
2271             mPowerState.dismissColorFade();
2272         } else if (target == Display.STATE_DOZE) {
2273             // Want screen dozing.
2274             // Wait for brightness animation to complete beforehand when entering doze
2275             // from screen on to prevent a perceptible jump because brightness may operate
2276             // differently when the display is configured for dozing.
2277             if (mScreenBrightnessRampAnimator.isAnimating()
2278                     && mPowerState.getScreenState() == Display.STATE_ON) {
2279                 return;
2280             }
2281 
2282             // Set screen state.
2283             if (!setScreenState(Display.STATE_DOZE)) {
2284                 return; // screen on blocked
2285             }
2286 
2287             // Dismiss the black surface without fanfare.
2288             mPowerState.setColorFadeLevel(1.0f);
2289             mPowerState.dismissColorFade();
2290         } else if (target == Display.STATE_DOZE_SUSPEND) {
2291             // Want screen dozing and suspended.
2292             // Wait for brightness animation to complete beforehand unless already
2293             // suspended because we may not be able to change it after suspension.
2294             if (mScreenBrightnessRampAnimator.isAnimating()
2295                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
2296                 return;
2297             }
2298 
2299             // If not already suspending, temporarily set the state to doze until the
2300             // screen on is unblocked, then suspend.
2301             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
2302                 if (!setScreenState(Display.STATE_DOZE)) {
2303                     return; // screen on blocked
2304                 }
2305                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
2306             }
2307 
2308             // Dismiss the black surface without fanfare.
2309             mPowerState.setColorFadeLevel(1.0f);
2310             mPowerState.dismissColorFade();
2311         } else if (target == Display.STATE_ON_SUSPEND) {
2312             // Want screen full-power and suspended.
2313             // Wait for brightness animation to complete beforehand unless already
2314             // suspended because we may not be able to change it after suspension.
2315             if (mScreenBrightnessRampAnimator.isAnimating()
2316                     && mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
2317                 return;
2318             }
2319 
2320             // If not already suspending, temporarily set the state to on until the
2321             // screen on is unblocked, then suspend.
2322             if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
2323                 if (!setScreenState(Display.STATE_ON)) {
2324                     return;
2325                 }
2326                 setScreenState(Display.STATE_ON_SUSPEND);
2327             }
2328 
2329             // Dismiss the black surface without fanfare.
2330             mPowerState.setColorFadeLevel(1.0f);
2331             mPowerState.dismissColorFade();
2332         } else {
2333             // Want screen off.
2334             mPendingScreenOff = true;
2335             if (!mColorFadeEnabled) {
2336                 mPowerState.setColorFadeLevel(0.0f);
2337             }
2338 
2339             if (mPowerState.getColorFadeLevel() == 0.0f) {
2340                 // Turn the screen off.
2341                 // A black surface is already hiding the contents of the screen.
2342                 setScreenState(Display.STATE_OFF);
2343                 mPendingScreenOff = false;
2344                 mPowerState.dismissColorFadeResources();
2345             } else if (performScreenOffTransition
2346                     && mPowerState.prepareColorFade(mContext,
2347                             mColorFadeFadesConfig ?
2348                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
2349                     && mPowerState.getScreenState() != Display.STATE_OFF) {
2350                 // Perform the screen off animation.
2351                 mColorFadeOffAnimator.start();
2352             } else {
2353                 // Skip the screen off animation and add a black surface to hide the
2354                 // contents of the screen.
2355                 mColorFadeOffAnimator.end();
2356             }
2357         }
2358     }
2359 
2360     private final Runnable mCleanListener = this::sendUpdatePowerState;
2361 
2362     private void setProximitySensorEnabled(boolean enable) {
2363         if (enable) {
2364             if (!mProximitySensorEnabled) {
2365                 // Register the listener.
2366                 // Proximity sensor state already cleared initially.
2367                 mProximitySensorEnabled = true;
2368                 mIgnoreProximityUntilChanged = false;
2369                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
2370                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
2371             }
2372         } else {
2373             if (mProximitySensorEnabled) {
2374                 // Unregister the listener.
2375                 // Clear the proximity sensor state for next time.
2376                 mProximitySensorEnabled = false;
2377                 mProximity = PROXIMITY_UNKNOWN;
2378                 mIgnoreProximityUntilChanged = false;
2379                 mPendingProximity = PROXIMITY_UNKNOWN;
2380                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
2381                 mSensorManager.unregisterListener(mProximitySensorListener);
2382                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
2383             }
2384         }
2385     }
2386 
2387     private void handleProximitySensorEvent(long time, boolean positive) {
2388         if (mProximitySensorEnabled) {
2389             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
2390                 return; // no change
2391             }
2392             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
2393                 return; // no change
2394             }
2395 
2396             // Only accept a proximity sensor reading if it remains
2397             // stable for the entire debounce delay.  We hold a wake lock while
2398             // debouncing the sensor.
2399             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
2400             if (positive) {
2401                 mPendingProximity = PROXIMITY_POSITIVE;
2402                 setPendingProximityDebounceTime(
2403                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
2404             } else {
2405                 mPendingProximity = PROXIMITY_NEGATIVE;
2406                 setPendingProximityDebounceTime(
2407                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
2408             }
2409 
2410             // Debounce the new sensor reading.
2411             debounceProximitySensor();
2412         }
2413     }
2414 
2415     private void debounceProximitySensor() {
2416         if (mProximitySensorEnabled
2417                 && mPendingProximity != PROXIMITY_UNKNOWN
2418                 && mPendingProximityDebounceTime >= 0) {
2419             final long now = SystemClock.uptimeMillis();
2420             if (mPendingProximityDebounceTime <= now) {
2421                 if (mProximity != mPendingProximity) {
2422                     // if the status of the sensor changed, stop ignoring.
2423                     mIgnoreProximityUntilChanged = false;
2424                     Slog.i(TAG, "No longer ignoring proximity [" + mPendingProximity + "]");
2425                 }
2426                 // Sensor reading accepted.  Apply the change then release the wake lock.
2427                 mProximity = mPendingProximity;
2428                 updatePowerState();
2429                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
2430             } else {
2431                 // Need to wait a little longer.
2432                 // Debounce again later.  We continue holding a wake lock while waiting.
2433                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
2434                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
2435             }
2436         }
2437     }
2438 
2439     private void clearPendingProximityDebounceTime() {
2440         if (mPendingProximityDebounceTime >= 0) {
2441             mPendingProximityDebounceTime = -1;
2442             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxDebounce);
2443         }
2444     }
2445 
2446     private void setPendingProximityDebounceTime(long debounceTime) {
2447         if (mPendingProximityDebounceTime < 0) {
2448             mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxDebounce);
2449         }
2450         mPendingProximityDebounceTime = debounceTime;
2451     }
2452 
2453     private void sendOnStateChangedWithWakelock() {
2454         if (!mOnStateChangedPending) {
2455             mOnStateChangedPending = true;
2456             mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdOnStateChanged);
2457             mHandler.post(mOnStateChangedRunnable);
2458         }
2459     }
2460 
2461     private void logDisplayPolicyChanged(int newPolicy) {
2462         LogMaker log = new LogMaker(MetricsEvent.DISPLAY_POLICY);
2463         log.setType(MetricsEvent.TYPE_UPDATE);
2464         log.setSubtype(newPolicy);
2465         MetricsLogger.action(log);
2466     }
2467 
2468     private void handleSettingsChange(boolean userSwitch) {
2469         mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
2470         mPendingAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
2471         if (userSwitch) {
2472             // Don't treat user switches as user initiated change.
2473             setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
2474             updateAutoBrightnessAdjustment();
2475             if (mAutomaticBrightnessController != null) {
2476                 mAutomaticBrightnessController.resetShortTermModel();
2477             }
2478         }
2479         // We don't bother with a pending variable for VR screen brightness since we just
2480         // immediately adapt to it.
2481         mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
2482         sendUpdatePowerState();
2483     }
2484 
2485     private void handleBrightnessModeChange() {
2486         final int screenBrightnessModeSetting = Settings.System.getIntForUser(
2487                 mContext.getContentResolver(),
2488                 Settings.System.SCREEN_BRIGHTNESS_MODE,
2489                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
2490         mHandler.post(() -> {
2491             mUseAutoBrightness = screenBrightnessModeSetting
2492                     == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
2493             updatePowerState();
2494         });
2495     }
2496 
2497     private float getAutoBrightnessAdjustmentSetting() {
2498         final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
2499                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
2500         return Float.isNaN(adj) ? 0.0f : clampAutoBrightnessAdjustment(adj);
2501     }
2502 
2503     float getScreenBrightnessSetting() {
2504         float brightness = mBrightnessSetting.getBrightness();
2505         if (Float.isNaN(brightness)) {
2506             brightness = mScreenBrightnessDefault;
2507         }
2508         return clampAbsoluteBrightness(brightness);
2509     }
2510 
2511     private float getScreenBrightnessForVrSetting() {
2512         final float brightnessFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
2513                 Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mScreenBrightnessForVrDefault,
2514                 UserHandle.USER_CURRENT);
2515         return clampScreenBrightnessForVr(brightnessFloat);
2516     }
2517 
2518     private void loadNitBasedBrightnessSetting() {
2519         if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
2520             float brightnessNitsForDefaultDisplay =
2521                     mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
2522             if (brightnessNitsForDefaultDisplay >= 0) {
2523                 float brightnessForDefaultDisplay = convertToFloatScale(
2524                         brightnessNitsForDefaultDisplay);
2525                 if (isValidBrightnessValue(brightnessForDefaultDisplay)) {
2526                     mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
2527                     mCurrentScreenBrightnessSetting = brightnessForDefaultDisplay;
2528                     return;
2529                 }
2530             }
2531         }
2532         mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
2533     }
2534 
2535     void setBrightness(float brightnessValue) {
2536         // Update the setting, which will eventually call back into DPC to have us actually update
2537         // the display with the new value.
2538         mBrightnessSetting.setBrightness(brightnessValue);
2539         if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
2540             float nits = convertToNits(brightnessValue);
2541             if (nits >= 0) {
2542                 mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits);
2543             }
2544         }
2545     }
2546 
2547     void onBootCompleted() {
2548         mHandler.obtainMessage(MSG_BOOT_COMPLETED).sendToTarget();
2549     }
2550 
2551     private void updateScreenBrightnessSetting(float brightnessValue) {
2552         if (!isValidBrightnessValue(brightnessValue)
2553                 || brightnessValue == mCurrentScreenBrightnessSetting) {
2554             return;
2555         }
2556         setCurrentScreenBrightness(brightnessValue);
2557         setBrightness(brightnessValue);
2558     }
2559 
2560     private void setCurrentScreenBrightness(float brightnessValue) {
2561         if (brightnessValue != mCurrentScreenBrightnessSetting) {
2562             mCurrentScreenBrightnessSetting = brightnessValue;
2563             postBrightnessChangeRunnable();
2564         }
2565     }
2566 
2567     private void putAutoBrightnessAdjustmentSetting(float adjustment) {
2568         if (mDisplayId == Display.DEFAULT_DISPLAY) {
2569             mAutoBrightnessAdjustment = adjustment;
2570             Settings.System.putFloatForUser(mContext.getContentResolver(),
2571                     Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment,
2572                     UserHandle.USER_CURRENT);
2573         }
2574     }
2575 
2576     private boolean updateAutoBrightnessAdjustment() {
2577         if (Float.isNaN(mPendingAutoBrightnessAdjustment)) {
2578             return false;
2579         }
2580         if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
2581             mPendingAutoBrightnessAdjustment = Float.NaN;
2582             return false;
2583         }
2584         mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
2585         mPendingAutoBrightnessAdjustment = Float.NaN;
2586         mTemporaryAutoBrightnessAdjustment = Float.NaN;
2587         return true;
2588     }
2589 
2590     // We want to return true if the user has set the screen brightness.
2591     // RBC on, off, and intensity changes will return false.
2592     // Slider interactions whilst in RBC will return true, just as when in non-rbc.
2593     private boolean updateUserSetScreenBrightness() {
2594         if ((Float.isNaN(mPendingScreenBrightnessSetting)
2595                 || mPendingScreenBrightnessSetting < 0.0f)) {
2596             return false;
2597         }
2598         if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
2599             mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
2600             mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
2601             return false;
2602         }
2603         setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
2604         mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
2605         mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
2606         mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
2607         return true;
2608     }
2609 
2610     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
2611             boolean hadUserDataPoint) {
2612         final float brightnessInNits = convertToNits(brightness);
2613         if (mUseAutoBrightness && brightnessInNits >= 0.0f
2614                 && mAutomaticBrightnessController != null && mBrightnessTracker != null) {
2615             // We only want to track changes on devices that can actually map the display backlight
2616             // values into a physical brightness unit since the value provided by the API is in
2617             // nits and not using the arbitrary backlight units.
2618             final float powerFactor = mPowerRequest.lowPowerMode
2619                     ? mPowerRequest.screenLowPowerBrightnessFactor
2620                     : 1.0f;
2621             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
2622                     powerFactor, hadUserDataPoint,
2623                     mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
2624                     mAutomaticBrightnessController.getLastSensorValues(),
2625                     mAutomaticBrightnessController.getLastSensorTimestamps());
2626         }
2627     }
2628 
2629     private float convertToNits(float brightness) {
2630         if (mAutomaticBrightnessController == null) {
2631             return -1f;
2632         }
2633         return mAutomaticBrightnessController.convertToNits(brightness);
2634     }
2635 
2636     private float convertToFloatScale(float nits) {
2637         if (mAutomaticBrightnessController == null) {
2638             return PowerManager.BRIGHTNESS_INVALID_FLOAT;
2639         }
2640         return mAutomaticBrightnessController.convertToFloatScale(nits);
2641     }
2642 
2643     @GuardedBy("mLock")
2644     private void updatePendingProximityRequestsLocked() {
2645         mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
2646         mPendingWaitForNegativeProximityLocked = false;
2647 
2648         if (mIgnoreProximityUntilChanged) {
2649             // Also, lets stop waiting for negative proximity if we're ignoring it.
2650             mWaitingForNegativeProximity = false;
2651         }
2652     }
2653 
2654     private void ignoreProximitySensorUntilChangedInternal() {
2655         if (!mIgnoreProximityUntilChanged
2656                 && mProximity == PROXIMITY_POSITIVE) {
2657             // Only ignore if it is still reporting positive (near)
2658             mIgnoreProximityUntilChanged = true;
2659             Slog.i(TAG, "Ignoring proximity");
2660             updatePowerState();
2661         }
2662     }
2663 
2664     private final Runnable mOnStateChangedRunnable = new Runnable() {
2665         @Override
2666         public void run() {
2667             mOnStateChangedPending = false;
2668             mCallbacks.onStateChanged();
2669             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdOnStateChanged);
2670         }
2671     };
2672 
2673     private void sendOnProximityPositiveWithWakelock() {
2674         mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxPositive);
2675         mHandler.post(mOnProximityPositiveRunnable);
2676         mOnProximityPositiveMessages++;
2677     }
2678 
2679     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
2680         @Override
2681         public void run() {
2682             mOnProximityPositiveMessages--;
2683             mCallbacks.onProximityPositive();
2684             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxPositive);
2685         }
2686     };
2687 
2688     private void sendOnProximityNegativeWithWakelock() {
2689         mOnProximityNegativeMessages++;
2690         mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxNegative);
2691         mHandler.post(mOnProximityNegativeRunnable);
2692     }
2693 
2694     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
2695         @Override
2696         public void run() {
2697             mOnProximityNegativeMessages--;
2698             mCallbacks.onProximityNegative();
2699             mCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxNegative);
2700         }
2701     };
2702 
2703     /**
2704      * Indicates whether the display state is ready to update. If this is the default display, we
2705      * want to update it right away so that we can draw the boot animation on it. If it is not
2706      * the default display, drawing the boot animation on it would look incorrect, so we need
2707      * to wait until boot is completed.
2708      * @return True if the display state is ready to update
2709      */
2710     private boolean readyToUpdateDisplayState() {
2711         return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
2712     }
2713 
2714     public void dump(final PrintWriter pw) {
2715         synchronized (mLock) {
2716             pw.println();
2717             pw.println("Display Power Controller:");
2718             pw.println("  mDisplayId=" + mDisplayId);
2719             pw.println("  mLightSensor=" + mLightSensor);
2720 
2721             pw.println();
2722             pw.println("Display Power Controller Locked State:");
2723             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
2724             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
2725             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
2726             pw.println("  mPendingWaitForNegativeProximityLocked="
2727                     + mPendingWaitForNegativeProximityLocked);
2728             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
2729         }
2730 
2731         pw.println();
2732         pw.println("Display Power Controller Configuration:");
2733         pw.println("  mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
2734         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
2735         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
2736         pw.println("  mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
2737         pw.println("  mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
2738         pw.println("  mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
2739         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
2740         pw.println("  mAllowAutoBrightnessWhileDozingConfig="
2741                 + mAllowAutoBrightnessWhileDozingConfig);
2742         pw.println("  mPersistBrightnessNitsForDefaultDisplay="
2743                 + mPersistBrightnessNitsForDefaultDisplay);
2744         pw.println("  mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
2745         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
2746         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
2747         synchronized (mCachedBrightnessInfo) {
2748             pw.println("  mCachedBrightnessInfo.brightness="
2749                     + mCachedBrightnessInfo.brightness.value);
2750             pw.println("  mCachedBrightnessInfo.adjustedBrightness="
2751                     + mCachedBrightnessInfo.adjustedBrightness.value);
2752             pw.println("  mCachedBrightnessInfo.brightnessMin="
2753                     + mCachedBrightnessInfo.brightnessMin.value);
2754             pw.println("  mCachedBrightnessInfo.brightnessMax="
2755                     + mCachedBrightnessInfo.brightnessMax.value);
2756             pw.println("  mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
2757             pw.println("  mCachedBrightnessInfo.hbmTransitionPoint="
2758                     + mCachedBrightnessInfo.hbmTransitionPoint.value);
2759             pw.println("  mCachedBrightnessInfo.brightnessMaxReason ="
2760                     + mCachedBrightnessInfo.brightnessMaxReason.value);
2761         }
2762         pw.println("  mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
2763         pw.println("  mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
2764 
2765         mHandler.runWithScissors(() -> dumpLocal(pw), 1000);
2766     }
2767 
2768     private void dumpLocal(PrintWriter pw) {
2769         pw.println();
2770         pw.println("Display Power Controller Thread State:");
2771         pw.println("  mPowerRequest=" + mPowerRequest);
2772         pw.println("  mUnfinishedBusiness=" + mUnfinishedBusiness);
2773         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
2774         pw.println("  mProximitySensor=" + mProximitySensor);
2775         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
2776         pw.println("  mProximityThreshold=" + mProximityThreshold);
2777         pw.println("  mProximity=" + proximityToString(mProximity));
2778         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
2779         pw.println("  mPendingProximityDebounceTime="
2780                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
2781         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
2782         pw.println("  mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness);
2783         pw.println("  mPendingScreenBrightnessSetting="
2784                 + mPendingScreenBrightnessSetting);
2785         pw.println("  mTemporaryScreenBrightness=" + mTemporaryScreenBrightness);
2786         pw.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
2787         pw.println("  mBrightnessReason=" + mBrightnessReason);
2788         pw.println("  mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
2789         pw.println("  mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
2790         pw.println("  mScreenBrightnessForVrFloat=" + mScreenBrightnessForVr);
2791         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
2792         pw.println("  mAppliedDimming=" + mAppliedDimming);
2793         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
2794         pw.println("  mAppliedThrottling=" + mAppliedThrottling);
2795         pw.println("  mAppliedScreenBrightnessOverride=" + mAppliedScreenBrightnessOverride);
2796         pw.println("  mAppliedTemporaryBrightness=" + mAppliedTemporaryBrightness);
2797         pw.println("  mAppliedTemporaryAutoBrightnessAdjustment="
2798                 + mAppliedTemporaryAutoBrightnessAdjustment);
2799         pw.println("  mAppliedBrightnessBoost=" + mAppliedBrightnessBoost);
2800         pw.println("  mDozing=" + mDozing);
2801         pw.println("  mSkipRampState=" + skipRampStateToString(mSkipRampState));
2802         pw.println("  mScreenOnBlockStartRealTime=" + mScreenOnBlockStartRealTime);
2803         pw.println("  mScreenOffBlockStartRealTime=" + mScreenOffBlockStartRealTime);
2804         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
2805         pw.println("  mPendingScreenOffUnblocker=" + mPendingScreenOffUnblocker);
2806         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
2807         pw.println("  mReportedToPolicy="
2808                 + reportedToPolicyToString(mReportedScreenStateToPolicy));
2809         pw.println("  mIsRbcActive=" + mIsRbcActive);
2810         pw.println("  mOnStateChangePending=" + mOnStateChangedPending);
2811         pw.println("  mOnProximityPositiveMessages=" + mOnProximityPositiveMessages);
2812         pw.println("  mOnProximityNegativeMessages=" + mOnProximityNegativeMessages);
2813 
2814         if (mScreenBrightnessRampAnimator != null) {
2815             pw.println("  mScreenBrightnessRampAnimator.isAnimating()="
2816                     + mScreenBrightnessRampAnimator.isAnimating());
2817         }
2818 
2819         if (mColorFadeOnAnimator != null) {
2820             pw.println("  mColorFadeOnAnimator.isStarted()="
2821                     + mColorFadeOnAnimator.isStarted());
2822         }
2823         if (mColorFadeOffAnimator != null) {
2824             pw.println("  mColorFadeOffAnimator.isStarted()="
2825                     + mColorFadeOffAnimator.isStarted());
2826         }
2827 
2828         if (mPowerState != null) {
2829             mPowerState.dump(pw);
2830         }
2831 
2832         if (mAutomaticBrightnessController != null) {
2833             mAutomaticBrightnessController.dump(pw);
2834             dumpBrightnessEvents(pw);
2835         }
2836 
2837         if (mScreenOffBrightnessSensorController != null) {
2838             mScreenOffBrightnessSensorController.dump(pw);
2839         }
2840 
2841         if (mHbmController != null) {
2842             mHbmController.dump(pw);
2843         }
2844 
2845         if (mBrightnessThrottler != null) {
2846             mBrightnessThrottler.dump(pw);
2847         }
2848 
2849         pw.println();
2850         if (mDisplayWhiteBalanceController != null) {
2851             mDisplayWhiteBalanceController.dump(pw);
2852             mDisplayWhiteBalanceSettings.dump(pw);
2853         }
2854     }
2855 
2856     private static String proximityToString(int state) {
2857         switch (state) {
2858             case PROXIMITY_UNKNOWN:
2859                 return "Unknown";
2860             case PROXIMITY_NEGATIVE:
2861                 return "Negative";
2862             case PROXIMITY_POSITIVE:
2863                 return "Positive";
2864             default:
2865                 return Integer.toString(state);
2866         }
2867     }
2868 
2869     private static String reportedToPolicyToString(int state) {
2870         switch (state) {
2871             case REPORTED_TO_POLICY_SCREEN_OFF:
2872                 return "REPORTED_TO_POLICY_SCREEN_OFF";
2873             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
2874                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
2875             case REPORTED_TO_POLICY_SCREEN_ON:
2876                 return "REPORTED_TO_POLICY_SCREEN_ON";
2877             default:
2878                 return Integer.toString(state);
2879         }
2880     }
2881 
2882     private static String skipRampStateToString(int state) {
2883         switch (state) {
2884             case RAMP_STATE_SKIP_NONE:
2885                 return "RAMP_STATE_SKIP_NONE";
2886             case RAMP_STATE_SKIP_INITIAL:
2887                 return "RAMP_STATE_SKIP_INITIAL";
2888             case RAMP_STATE_SKIP_AUTOBRIGHT:
2889                 return "RAMP_STATE_SKIP_AUTOBRIGHT";
2890             default:
2891                 return Integer.toString(state);
2892         }
2893     }
2894 
2895     private void dumpBrightnessEvents(PrintWriter pw) {
2896         int size = mBrightnessEventRingBuffer.size();
2897         if (size < 1) {
2898             pw.println("No Automatic Brightness Adjustments");
2899             return;
2900         }
2901 
2902         pw.println("Automatic Brightness Adjustments Last " + size + " Events: ");
2903         BrightnessEvent[] eventArray = mBrightnessEventRingBuffer.toArray();
2904         for (int i = 0; i < mBrightnessEventRingBuffer.size(); i++) {
2905             pw.println("  " + eventArray[i].toString());
2906         }
2907     }
2908 
2909     private static float clampAbsoluteBrightness(float value) {
2910         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
2911                 PowerManager.BRIGHTNESS_MAX);
2912     }
2913 
2914     private static float clampAutoBrightnessAdjustment(float value) {
2915         return MathUtils.constrain(value, -1.0f, 1.0f);
2916     }
2917 
2918     private void noteScreenState(int screenState) {
2919         if (mBatteryStats != null) {
2920             try {
2921                 // TODO(multi-display): make this multi-display
2922                 mBatteryStats.noteScreenState(screenState);
2923             } catch (RemoteException e) {
2924                 // same process
2925             }
2926         }
2927     }
2928 
2929     private void noteScreenBrightness(float brightness) {
2930         if (mBatteryStats != null) {
2931             try {
2932                 // TODO(brightnessfloat): change BatteryStats to use float
2933                 mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(
2934                         brightness));
2935             } catch (RemoteException e) {
2936                 // same process
2937             }
2938         }
2939     }
2940 
2941     private void reportStats(float brightness) {
2942         if (mLastStatsBrightness == brightness) {
2943             return;
2944         }
2945 
2946         float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
2947         synchronized(mCachedBrightnessInfo) {
2948             if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
2949                 return;
2950             }
2951             hbmTransitionPoint = mCachedBrightnessInfo.hbmTransitionPoint.value;
2952         }
2953 
2954         final boolean aboveTransition = brightness > hbmTransitionPoint;
2955         final boolean oldAboveTransition = mLastStatsBrightness > hbmTransitionPoint;
2956 
2957         if (aboveTransition || oldAboveTransition) {
2958             mLastStatsBrightness = brightness;
2959             mHandler.removeMessages(MSG_STATSD_HBM_BRIGHTNESS);
2960             if (aboveTransition != oldAboveTransition) {
2961                 // report immediately
2962                 logHbmBrightnessStats(brightness, mDisplayStatsId);
2963             } else {
2964                 // delay for rate limiting
2965                 Message msg = mHandler.obtainMessage();
2966                 msg.what = MSG_STATSD_HBM_BRIGHTNESS;
2967                 msg.arg1 = Float.floatToIntBits(brightness);
2968                 msg.arg2 = mDisplayStatsId;
2969                 mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
2970             }
2971         }
2972     }
2973 
2974     private void logHbmBrightnessStats(float brightness, int displayStatsId) {
2975         synchronized (mHandler) {
2976             FrameworkStatsLog.write(
2977                     FrameworkStatsLog.DISPLAY_HBM_BRIGHTNESS_CHANGED, displayStatsId, brightness);
2978         }
2979     }
2980 
2981     private void logManualBrightnessEvent(BrightnessEvent event) {
2982         float appliedHbmMaxNits =
2983                 event.hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
2984                         ? -1f : convertToNits(event.hbmMax);
2985 
2986         // thermalCapNits set to -1 if not currently capping max brightness
2987         float appliedThermalCapNits =
2988                 event.thermalMax == PowerManager.BRIGHTNESS_MAX
2989                         ? -1f : convertToNits(event.thermalMax);
2990 
2991         int appliedRbcStrength = event.isRbcEnabled() ? event.rbcStrength : -1;
2992 
2993         float appliedPowerFactor = event.isLowPowerModeSet() ? event.powerFactor : -1f;
2994 
2995         if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
2996                 && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
2997                     .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
2998             FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
2999                     convertToNits(event.initialBrightness),
3000                     convertToNits(event.brightness),
3001                     event.lux,
3002                     event.physicalDisplayId,
3003                     event.wasShortTermModelActive,
3004                     appliedPowerFactor,
3005                     appliedRbcStrength,
3006                     appliedHbmMaxNits,
3007                     appliedThermalCapNits,
3008                     event.automaticBrightnessEnabled,
3009                     FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
3010         }
3011     }
3012 
3013     class BrightnessEvent {
3014         static final int FLAG_RBC = 0x1;
3015         static final int FLAG_INVALID_LUX = 0x2;
3016         static final int FLAG_DOZE_SCALE = 0x4;
3017         static final int FLAG_USER_SET = 0x8;
3018         static final int FLAG_IDLE_CURVE = 0x10;
3019         static final int FLAG_LOW_POWER_MODE = 0x20;
3020 
3021         public final BrightnessReason reason = new BrightnessReason();
3022 
3023         public int displayId;
3024         public String physicalDisplayId;
3025         public float lux;
3026         public float preThresholdLux;
3027         public long time;
3028         public float brightness;
3029         public float initialBrightness;
3030         public float recommendedBrightness;
3031         public float preThresholdBrightness;
3032         public float hbmMax;
3033         public int rbcStrength;
3034         public float thermalMax;
3035         public float powerFactor;
3036         public int hbmMode;
3037         public boolean wasShortTermModelActive;
3038         public int flags;
3039         public int adjustmentFlags;
3040         public boolean automaticBrightnessEnabled;
3041 
3042         BrightnessEvent(BrightnessEvent that) {
3043             copyFrom(that);
3044         }
3045 
3046         BrightnessEvent(int displayId) {
3047             this.displayId = displayId;
3048             reset();
3049         }
3050 
3051         void copyFrom(BrightnessEvent that) {
3052             displayId = that.displayId;
3053             physicalDisplayId = that.physicalDisplayId;
3054             time = that.time;
3055             lux = that.lux;
3056             preThresholdLux = that.preThresholdLux;
3057             brightness = that.brightness;
3058             initialBrightness = that.initialBrightness;
3059             recommendedBrightness = that.recommendedBrightness;
3060             preThresholdBrightness = that.preThresholdBrightness;
3061             hbmMax = that.hbmMax;
3062             rbcStrength = that.rbcStrength;
3063             thermalMax = that.thermalMax;
3064             powerFactor = that.powerFactor;
3065             flags = that.flags;
3066             hbmMode = that.hbmMode;
3067             wasShortTermModelActive = that.wasShortTermModelActive;
3068             reason.set(that.reason);
3069             adjustmentFlags = that.adjustmentFlags;
3070             automaticBrightnessEnabled = that.automaticBrightnessEnabled;
3071         }
3072 
3073         void reset() {
3074             time = SystemClock.uptimeMillis();
3075             physicalDisplayId = "";
3076             brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
3077             initialBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
3078             recommendedBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
3079             lux = 0f;
3080             preThresholdLux = 0f;
3081             preThresholdBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
3082             hbmMax = PowerManager.BRIGHTNESS_MAX;
3083             rbcStrength = 0;
3084             powerFactor = 1f;
3085             wasShortTermModelActive = false;
3086             thermalMax = PowerManager.BRIGHTNESS_MAX;
3087             flags = 0;
3088             hbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
3089             reason.set(null);
3090             adjustmentFlags = 0;
3091             automaticBrightnessEnabled = true;
3092         }
3093 
3094         boolean isRbcEnabled() {
3095             return (flags & FLAG_RBC) != 0;
3096         }
3097 
3098         public boolean isShortTermModelActive() {
3099             return (flags & FLAG_USER_SET) != 0;
3100         }
3101 
3102         public boolean isLowPowerModeSet() {
3103             return (flags & FLAG_LOW_POWER_MODE) != 0;
3104         }
3105 
3106         boolean equalsMainData(BrightnessEvent that) {
3107             // This equals comparison purposefully ignores time since it is regularly changing and
3108             // we don't want to log a brightness event just because the time changed.
3109             return displayId == that.displayId
3110                     && physicalDisplayId.equals(that.physicalDisplayId)
3111                     && Float.floatToRawIntBits(brightness)
3112                         == Float.floatToRawIntBits(that.brightness)
3113                     && Float.floatToRawIntBits(initialBrightness)
3114                         == Float.floatToRawIntBits(that.initialBrightness)
3115                     && Float.floatToRawIntBits(recommendedBrightness)
3116                         == Float.floatToRawIntBits(that.recommendedBrightness)
3117                     && Float.floatToRawIntBits(preThresholdBrightness)
3118                         == Float.floatToRawIntBits(that.preThresholdBrightness)
3119                     && Float.floatToRawIntBits(lux) == Float.floatToRawIntBits(that.lux)
3120                     && Float.floatToRawIntBits(preThresholdLux)
3121                         == Float.floatToRawIntBits(that.preThresholdLux)
3122                     && rbcStrength == that.rbcStrength
3123                     && Float.floatToRawIntBits(hbmMax) == Float.floatToRawIntBits(that.hbmMax)
3124                     && hbmMode == that.hbmMode
3125                     && Float.floatToRawIntBits(thermalMax)
3126                         == Float.floatToRawIntBits(that.thermalMax)
3127                     && Float.floatToRawIntBits(powerFactor)
3128                         == Float.floatToRawIntBits(that.powerFactor)
3129                     && wasShortTermModelActive == that.wasShortTermModelActive
3130                     && flags == that.flags
3131                     && adjustmentFlags == that.adjustmentFlags
3132                     && reason.equals(that.reason)
3133                     && automaticBrightnessEnabled == that.automaticBrightnessEnabled;
3134         }
3135 
3136         public String toString(boolean includeTime) {
3137             return (includeTime ? TimeUtils.formatForLogging(time) + " - " : "")
3138                     + "BrightnessEvent: "
3139                     + "disp=" + displayId
3140                     + ", physDisp=" + physicalDisplayId
3141                     + ", brt=" + brightness + ((flags & FLAG_USER_SET) != 0 ? "(user_set)" : "")
3142                     + ", initBrt=" + initialBrightness
3143                     + ", rcmdBrt=" + recommendedBrightness
3144                     + ", preBrt=" + preThresholdBrightness
3145                     + ", lux=" + lux
3146                     + ", preLux=" + preThresholdLux
3147                     + ", hbmMax=" + hbmMax
3148                     + ", hbmMode=" + BrightnessInfo.hbmToString(hbmMode)
3149                     + ", rbcStrength=" + rbcStrength
3150                     + ", powerFactor=" + powerFactor
3151                     + ", thrmMax=" + thermalMax
3152                     + ", wasShortTermModelActive=" + wasShortTermModelActive
3153                     + ", flags=" + flagsToString()
3154                     + ", reason=" + reason.toString(adjustmentFlags)
3155                     + ", autoBrightness=" + automaticBrightnessEnabled;
3156         }
3157 
3158         @Override
3159         public String toString() {
3160             return toString(/* includeTime */ true);
3161         }
3162 
3163         private String flagsToString() {
3164             return ((flags & FLAG_USER_SET) != 0 ? "user_set " : "")
3165                     + ((flags & FLAG_RBC) != 0 ? "rbc " : "")
3166                     + ((flags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "")
3167                     + ((flags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "")
3168                     + ((flags & FLAG_IDLE_CURVE) != 0 ? "idle_curve " : "")
3169                     + ((flags & FLAG_LOW_POWER_MODE) != 0 ? "low_power_mode " : "");
3170         }
3171     }
3172 
3173     private final class DisplayControllerHandler extends Handler {
3174         public DisplayControllerHandler(Looper looper) {
3175             super(looper, null, true /*async*/);
3176         }
3177 
3178         @Override
3179         public void handleMessage(Message msg) {
3180             switch (msg.what) {
3181                 case MSG_UPDATE_POWER_STATE:
3182                     updatePowerState();
3183                     break;
3184 
3185                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
3186                     debounceProximitySensor();
3187                     break;
3188 
3189                 case MSG_SCREEN_ON_UNBLOCKED:
3190                     if (mPendingScreenOnUnblocker == msg.obj) {
3191                         unblockScreenOn();
3192                         updatePowerState();
3193                     }
3194                     break;
3195                 case MSG_SCREEN_OFF_UNBLOCKED:
3196                     if (mPendingScreenOffUnblocker == msg.obj) {
3197                         unblockScreenOff();
3198                         updatePowerState();
3199                     }
3200                     break;
3201                 case MSG_CONFIGURE_BRIGHTNESS:
3202                     mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
3203                     mShouldResetShortTermModel = msg.arg1 == 1;
3204                     updatePowerState();
3205                     break;
3206 
3207                 case MSG_SET_TEMPORARY_BRIGHTNESS:
3208                     // TODO: Should we have a a timeout for the temporary brightness?
3209                     mTemporaryScreenBrightness = Float.intBitsToFloat(msg.arg1);
3210                     updatePowerState();
3211                     break;
3212 
3213                 case MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT:
3214                     mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1);
3215                     updatePowerState();
3216                     break;
3217 
3218                 case MSG_IGNORE_PROXIMITY:
3219                     ignoreProximitySensorUntilChangedInternal();
3220                     break;
3221 
3222                 case MSG_STOP:
3223                     cleanupHandlerThreadAfterStop();
3224                     break;
3225 
3226                 case MSG_UPDATE_BRIGHTNESS:
3227                     if (mStopped) {
3228                         return;
3229                     }
3230                     handleSettingsChange(false /*userSwitch*/);
3231                     break;
3232 
3233                 case MSG_UPDATE_RBC:
3234                     handleRbcChanged();
3235                     break;
3236 
3237                 case MSG_BRIGHTNESS_RAMP_DONE:
3238                     if (mPowerState != null)  {
3239                         final float brightness = mPowerState.getScreenBrightness();
3240                         reportStats(brightness);
3241                     }
3242                     break;
3243 
3244                 case MSG_STATSD_HBM_BRIGHTNESS:
3245                     logHbmBrightnessStats(Float.intBitsToFloat(msg.arg1), msg.arg2);
3246                     break;
3247 
3248                 case MSG_SWITCH_USER:
3249                     handleOnSwitchUser(msg.arg1);
3250                     break;
3251 
3252                 case MSG_BOOT_COMPLETED:
3253                     mBootCompleted = true;
3254                     updatePowerState();
3255                     break;
3256             }
3257         }
3258     }
3259 
3260     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
3261         @Override
3262         public void onSensorChanged(SensorEvent event) {
3263             if (mProximitySensorEnabled) {
3264                 final long time = SystemClock.uptimeMillis();
3265                 final float distance = event.values[0];
3266                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
3267                 handleProximitySensorEvent(time, positive);
3268             }
3269         }
3270 
3271         @Override
3272         public void onAccuracyChanged(Sensor sensor, int accuracy) {
3273             // Not used.
3274         }
3275     };
3276 
3277 
3278     private final class SettingsObserver extends ContentObserver {
3279         public SettingsObserver(Handler handler) {
3280             super(handler);
3281         }
3282 
3283         @Override
3284         public void onChange(boolean selfChange, Uri uri) {
3285             if (uri.equals(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE))) {
3286                 handleBrightnessModeChange();
3287             } else {
3288                 handleSettingsChange(false /* userSwitch */);
3289             }
3290         }
3291     }
3292 
3293     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
3294         @Override
3295         public void onScreenOn() {
3296             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
3297             mHandler.sendMessage(msg);
3298         }
3299     }
3300 
3301     private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener {
3302         @Override
3303         public void onScreenOff() {
3304             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
3305             mHandler.sendMessage(msg);
3306         }
3307     }
3308 
3309     void setAutoBrightnessLoggingEnabled(boolean enabled) {
3310         if (mAutomaticBrightnessController != null) {
3311             mAutomaticBrightnessController.setLoggingEnabled(enabled);
3312         }
3313     }
3314 
3315     @Override // DisplayWhiteBalanceController.Callbacks
3316     public void updateWhiteBalance() {
3317         sendUpdatePowerState();
3318     }
3319 
3320     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
3321         if (mDisplayWhiteBalanceController != null) {
3322             mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
3323             mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
3324         }
3325     }
3326 
3327     void setAmbientColorTemperatureOverride(float cct) {
3328         if (mDisplayWhiteBalanceController != null) {
3329             mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
3330             // The ambient color temperature override is only applied when the ambient color
3331             // temperature changes or is updated, so it doesn't necessarily change the screen color
3332             // temperature immediately. So, let's make it!
3333             sendUpdatePowerState();
3334         }
3335     }
3336 
3337     /**
3338      * Stores data about why the brightness was changed.  Made up of one main
3339      * {@code BrightnessReason.REASON_*} reason and various {@code BrightnessReason.MODIFIER_*}
3340      * modifiers.
3341      */
3342     private final class BrightnessReason {
3343         static final int REASON_UNKNOWN = 0;
3344         static final int REASON_MANUAL = 1;
3345         static final int REASON_DOZE = 2;
3346         static final int REASON_DOZE_DEFAULT = 3;
3347         static final int REASON_AUTOMATIC = 4;
3348         static final int REASON_SCREEN_OFF = 5;
3349         static final int REASON_VR = 6;
3350         static final int REASON_OVERRIDE = 7;
3351         static final int REASON_TEMPORARY = 8;
3352         static final int REASON_BOOST = 9;
3353         static final int REASON_SCREEN_OFF_BRIGHTNESS_SENSOR = 10;
3354         static final int REASON_MAX = REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
3355 
3356         static final int MODIFIER_DIMMED = 0x1;
3357         static final int MODIFIER_LOW_POWER = 0x2;
3358         static final int MODIFIER_HDR = 0x4;
3359         static final int MODIFIER_THROTTLED = 0x8;
3360         static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR
3361             | MODIFIER_THROTTLED;
3362 
3363         // ADJUSTMENT_*
3364         // These things can happen at any point, even if the main brightness reason doesn't
3365         // fundamentally change, so they're not stored.
3366 
3367         // Auto-brightness adjustment factor changed
3368         static final int ADJUSTMENT_AUTO_TEMP = 0x1;
3369         // Temporary adjustment to the auto-brightness adjustment factor.
3370         static final int ADJUSTMENT_AUTO = 0x2;
3371 
3372         // One of REASON_*
3373         public int reason;
3374         // Any number of MODIFIER_*
3375         public int modifier;
3376 
3377         public void set(BrightnessReason other) {
3378             setReason(other == null ? REASON_UNKNOWN : other.reason);
3379             setModifier(other == null ? 0 : other.modifier);
3380         }
3381 
3382         public void setReason(int reason) {
3383             if (reason < REASON_UNKNOWN || reason > REASON_MAX) {
3384                 Slog.w(TAG, "brightness reason out of bounds: " + reason);
3385             } else {
3386                 this.reason = reason;
3387             }
3388         }
3389 
3390         public void setModifier(int modifier) {
3391             if ((modifier & ~MODIFIER_MASK) != 0) {
3392                 Slog.w(TAG, "brightness modifier out of bounds: 0x"
3393                         + Integer.toHexString(modifier));
3394             } else {
3395                 this.modifier = modifier;
3396             }
3397         }
3398 
3399         public void addModifier(int modifier) {
3400             setModifier(modifier | this.modifier);
3401         }
3402 
3403         @Override
3404         public boolean equals(Object obj) {
3405             if (!(obj instanceof BrightnessReason)) {
3406                 return false;
3407             }
3408             BrightnessReason other = (BrightnessReason) obj;
3409             return other.reason == reason && other.modifier == modifier;
3410         }
3411 
3412         @Override
3413         public int hashCode() {
3414             return Objects.hash(reason, modifier);
3415         }
3416 
3417         @Override
3418         public String toString() {
3419             return toString(0);
3420         }
3421 
3422         public String toString(int adjustments) {
3423             final StringBuilder sb = new StringBuilder();
3424             sb.append(reasonToString(reason));
3425             sb.append(" [");
3426             if ((adjustments & ADJUSTMENT_AUTO_TEMP) != 0) {
3427                 sb.append(" temp_adj");
3428             }
3429             if ((adjustments & ADJUSTMENT_AUTO) != 0) {
3430                 sb.append(" auto_adj");
3431             }
3432             if ((modifier & MODIFIER_LOW_POWER) != 0) {
3433                 sb.append(" low_pwr");
3434             }
3435             if ((modifier & MODIFIER_DIMMED) != 0) {
3436                 sb.append(" dim");
3437             }
3438             if ((modifier & MODIFIER_HDR) != 0) {
3439                 sb.append(" hdr");
3440             }
3441             if ((modifier & MODIFIER_THROTTLED) != 0) {
3442                 sb.append(" throttled");
3443             }
3444             int strlen = sb.length();
3445             if (sb.charAt(strlen - 1) == '[') {
3446                 sb.setLength(strlen - 2);
3447             } else {
3448                 sb.append(" ]");
3449             }
3450             return sb.toString();
3451         }
3452 
3453         private String reasonToString(int reason) {
3454             switch (reason) {
3455                 case REASON_MANUAL: return "manual";
3456                 case REASON_DOZE: return "doze";
3457                 case REASON_DOZE_DEFAULT: return "doze_default";
3458                 case REASON_AUTOMATIC: return "automatic";
3459                 case REASON_SCREEN_OFF: return "screen_off";
3460                 case REASON_VR: return "vr";
3461                 case REASON_OVERRIDE: return "override";
3462                 case REASON_TEMPORARY: return "temporary";
3463                 case REASON_BOOST: return "boost";
3464                 case REASON_SCREEN_OFF_BRIGHTNESS_SENSOR: return "screen_off_brightness_sensor";
3465                 default: return Integer.toString(reason);
3466             }
3467         }
3468     }
3469 
3470     static class CachedBrightnessInfo {
3471         public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3472         public MutableFloat adjustedBrightness =
3473             new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3474         public MutableFloat brightnessMin =
3475             new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3476         public MutableFloat brightnessMax =
3477             new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3478         public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
3479         public MutableFloat hbmTransitionPoint =
3480             new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
3481         public MutableInt brightnessMaxReason =
3482             new MutableInt(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
3483 
3484         public boolean checkAndSetFloat(MutableFloat mf, float f) {
3485             if (mf.value != f) {
3486                 mf.value = f;
3487                 return true;
3488             }
3489             return false;
3490         }
3491 
3492         public boolean checkAndSetInt(MutableInt mi, int i) {
3493             if (mi.value != i) {
3494                 mi.value = i;
3495                 return true;
3496             }
3497             return false;
3498         }
3499     }
3500 }
3501