1 /*
2  * Copyright (C) 2022 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 static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
20 
21 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
22 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
23 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
24 import static com.android.server.display.config.DisplayBrightnessMappingConfig.autoBrightnessPresetToString;
25 
26 import android.animation.Animator;
27 import android.animation.ObjectAnimator;
28 import android.annotation.Nullable;
29 import android.annotation.SuppressLint;
30 import android.annotation.UserIdInt;
31 import android.app.ActivityManager;
32 import android.content.Context;
33 import android.content.pm.ParceledListSlice;
34 import android.content.res.Resources;
35 import android.database.ContentObserver;
36 import android.hardware.Sensor;
37 import android.hardware.SensorManager;
38 import android.hardware.display.AmbientBrightnessDayStats;
39 import android.hardware.display.BrightnessChangeEvent;
40 import android.hardware.display.BrightnessConfiguration;
41 import android.hardware.display.BrightnessInfo;
42 import android.hardware.display.DisplayManagerInternal.DisplayOffloadSession;
43 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
44 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
45 import android.metrics.LogMaker;
46 import android.net.Uri;
47 import android.os.Handler;
48 import android.os.HandlerExecutor;
49 import android.os.IBinder;
50 import android.os.Looper;
51 import android.os.Message;
52 import android.os.PowerManager;
53 import android.os.RemoteException;
54 import android.os.SystemClock;
55 import android.os.SystemProperties;
56 import android.os.Trace;
57 import android.os.UserHandle;
58 import android.provider.Settings;
59 import android.util.FloatProperty;
60 import android.util.IndentingPrintWriter;
61 import android.util.MathUtils;
62 import android.util.MutableFloat;
63 import android.util.MutableInt;
64 import android.util.Pair;
65 import android.util.Slog;
66 import android.util.SparseArray;
67 import android.view.Display;
68 
69 import com.android.internal.R;
70 import com.android.internal.annotations.GuardedBy;
71 import com.android.internal.annotations.VisibleForTesting;
72 import com.android.internal.app.IBatteryStats;
73 import com.android.internal.display.BrightnessSynchronizer;
74 import com.android.internal.logging.MetricsLogger;
75 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
76 import com.android.internal.util.FrameworkStatsLog;
77 import com.android.internal.util.RingBuffer;
78 import com.android.server.LocalServices;
79 import com.android.server.am.BatteryStatsService;
80 import com.android.server.display.RampAnimator.DualRampAnimator;
81 import com.android.server.display.brightness.BrightnessEvent;
82 import com.android.server.display.brightness.BrightnessReason;
83 import com.android.server.display.brightness.BrightnessUtils;
84 import com.android.server.display.brightness.DisplayBrightnessController;
85 import com.android.server.display.brightness.clamper.BrightnessClamperController;
86 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
87 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategyConstants;
88 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
89 import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
90 import com.android.server.display.config.HysteresisLevels;
91 import com.android.server.display.feature.DisplayManagerFlags;
92 import com.android.server.display.layout.Layout;
93 import com.android.server.display.state.DisplayStateController;
94 import com.android.server.display.utils.DebugUtils;
95 import com.android.server.display.utils.SensorUtils;
96 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
97 import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
98 import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
99 import com.android.server.policy.WindowManagerPolicy;
100 
101 import java.io.PrintWriter;
102 import java.util.Objects;
103 
104 /**
105  * Controls the power state of the display.
106  *
107  * Handles the proximity sensor, light sensor, and animations between states
108  * including the screen off animation.
109  *
110  * This component acts independently of the rest of the power manager service.
111  * In particular, it does not share any state and it only communicates
112  * via asynchronous callbacks to inform the power manager that something has
113  * changed.
114  *
115  * Everything this class does internally is serialized on its handler although
116  * it may be accessed by other threads from the outside.
117  *
118  * Note that the power manager service guarantees that it will hold a suspend
119  * blocker as long as the display is not ready.  So most of the work done here
120  * does not need to worry about holding a suspend blocker unless it happens
121  * independently of the display ready signal.
122  *
123  * For debugging, you can make the color fade and brightness animations run
124  * slower by changing the "animator duration scale" option in Development Settings.
125  */
126 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
127         DisplayWhiteBalanceController.Callbacks, DisplayPowerControllerInterface {
128     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
129     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
130 
131     private static final String TAG = "DisplayPowerController2";
132     // To enable these logs, run:
133     // 'adb shell setprop persist.log.tag.DisplayPowerController2 DEBUG && adb reboot'
134     private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
135     private static final String SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME =
136             "Screen on blocked by displayoffload";
137 
138     // If true, uses the color fade on animation.
139     // We might want to turn this off if we cannot get a guarantee that the screen
140     // actually turns on and starts showing new content after the call to set the
141     // screen state returns.  Playing the animation can also be somewhat slow.
142     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
143 
144     private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
145 
146     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
147     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
148 
149     private static final int MSG_UPDATE_POWER_STATE = 1;
150     private static final int MSG_SCREEN_ON_UNBLOCKED = 2;
151     private static final int MSG_SCREEN_OFF_UNBLOCKED = 3;
152     private static final int MSG_CONFIGURE_BRIGHTNESS = 4;
153     private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 5;
154     private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 6;
155     private static final int MSG_STOP = 7;
156     private static final int MSG_UPDATE_BRIGHTNESS = 8;
157     private static final int MSG_UPDATE_RBC = 9;
158     private static final int MSG_BRIGHTNESS_RAMP_DONE = 10;
159     private static final int MSG_STATSD_HBM_BRIGHTNESS = 11;
160     private static final int MSG_SWITCH_USER = 12;
161     private static final int MSG_BOOT_COMPLETED = 13;
162     private static final int MSG_SWITCH_AUTOBRIGHTNESS_MODE = 14;
163     private static final int MSG_SET_DWBC_COLOR_OVERRIDE = 15;
164     private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16;
165     private static final int MSG_SET_BRIGHTNESS_FROM_OFFLOAD = 17;
166     private static final int MSG_OFFLOADING_SCREEN_ON_UNBLOCKED = 18;
167 
168 
169 
170     private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
171 
172 
173     // State machine constants for tracking initial brightness ramp skipping when enabled.
174     private static final int RAMP_STATE_SKIP_NONE = 0;
175     private static final int RAMP_STATE_SKIP_INITIAL = 1;
176     private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
177 
178     private static final int REPORTED_TO_POLICY_UNREPORTED = -1;
179     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
180     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
181     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
182     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
183 
184     private static final int RINGBUFFER_MAX = 100;
185     private static final int RINGBUFFER_RBC_MAX = 20;
186 
187     private static final float[] BRIGHTNESS_RANGE_BOUNDARIES = {
188         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
189         90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
190         1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
191     private static final int[] BRIGHTNESS_RANGE_INDEX = {
192         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN,
193         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1,
194         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1_2,
195         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2_3,
196         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3_4,
197         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_4_5,
198         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_5_6,
199         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_6_7,
200         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_7_8,
201         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_8_9,
202         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_9_10,
203         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_10_20,
204         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_20_30,
205         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_30_40,
206         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_40_50,
207         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_50_60,
208         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_60_70,
209         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_70_80,
210         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_80_90,
211         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_90_100,
212         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_100_200,
213         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_200_300,
214         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_300_400,
215         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_400_500,
216         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_500_600,
217         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_600_700,
218         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_700_800,
219         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_800_900,
220         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_900_1000,
221         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1000_1200,
222         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1200_1400,
223         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1400_1600,
224         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1600_1800,
225         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1800_2000,
226         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2000_2250,
227         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2250_2500,
228         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2500_2750,
229         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2750_3000,
230     };
231 
232     private final String mTag;
233 
234     private final Object mLock = new Object();
235 
236     private final Context mContext;
237 
238     // Our handler.
239     private final DisplayControllerHandler mHandler;
240 
241     // Battery stats.
242     @Nullable
243     private final IBatteryStats mBatteryStats;
244 
245     // The sensor manager.
246     private final SensorManager mSensorManager;
247 
248     // The window manager policy.
249     private final WindowManagerPolicy mWindowManagerPolicy;
250 
251     // The display blanker.
252     private final DisplayBlanker mBlanker;
253 
254     // The LogicalDisplay tied to this DisplayPowerController2.
255     private final LogicalDisplay mLogicalDisplay;
256 
257     // The ID of the LogicalDisplay tied to this DisplayPowerController2.
258     private final int mDisplayId;
259 
260     // The ID of the display which this display follows for brightness purposes.
261     private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY;
262 
263     // The unique ID of the primary display device currently tied to this logical display
264     private String mUniqueDisplayId;
265 
266     // Tracker for brightness changes.
267     @Nullable
268     private final BrightnessTracker mBrightnessTracker;
269 
270     // Tracker for brightness settings changes.
271     private final SettingsObserver mSettingsObserver;
272 
273     // The doze screen brightness.
274     private final float mScreenBrightnessDozeConfig;
275 
276     // True if auto-brightness should be used.
277     private boolean mUseSoftwareAutoBrightnessConfig;
278 
279     // Whether or not the color fade on screen on / off is enabled.
280     private final boolean mColorFadeEnabled;
281 
282     @GuardedBy("mCachedBrightnessInfo")
283     private final CachedBrightnessInfo mCachedBrightnessInfo = new CachedBrightnessInfo();
284 
285     private DisplayDevice mDisplayDevice;
286 
287     // True if we should fade the screen while turning it off, false if we should play
288     // a stylish color fade animation instead.
289     private final boolean mColorFadeFadesConfig;
290 
291     // True if we need to fake a transition to off when coming out of a doze state.
292     // Some display hardware will blank itself when coming out of doze in order to hide
293     // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
294     // blank itself and begin an appropriate power on animation.
295     private final boolean mDisplayBlanksAfterDozeConfig;
296 
297     // True if there are only buckets of brightness values when the display is in the doze state,
298     // rather than a full range of values. If this is true, then we'll avoid animating the screen
299     // brightness since it'd likely be multiple jarring brightness transitions instead of just one
300     // to reach the final state.
301     private final boolean mBrightnessBucketsInDozeConfig;
302 
303     private final Clock mClock;
304     private final Injector mInjector;
305 
306     // Maximum time a ramp animation can take.
307     private long mBrightnessRampIncreaseMaxTimeMillis;
308     private long mBrightnessRampDecreaseMaxTimeMillis;
309 
310     // Maximum time a ramp animation can take in idle mode.
311     private long mBrightnessRampIncreaseMaxTimeIdleMillis;
312     private long mBrightnessRampDecreaseMaxTimeIdleMillis;
313 
314     // The pending power request.
315     // Initially null until the first call to requestPowerState.
316     @GuardedBy("mLock")
317     private DisplayPowerRequest mPendingRequestLocked;
318 
319     // True if the pending power request or wait for negative proximity flag
320     // has been changed since the last update occurred.
321     @GuardedBy("mLock")
322     private boolean mPendingRequestChangedLocked;
323 
324     // Set to true when the important parts of the pending power request have been applied.
325     // The important parts are mainly the screen state.  Brightness changes may occur
326     // concurrently.
327     @GuardedBy("mLock")
328     private boolean mDisplayReadyLocked;
329 
330     // Set to true if a power state update is required.
331     @GuardedBy("mLock")
332     private boolean mPendingUpdatePowerStateLocked;
333 
334     /* The following state must only be accessed by the handler thread. */
335 
336     // The currently requested power state.
337     // The power controller will progressively update its internal state to match
338     // the requested power state.  Initially null until the first update.
339     private DisplayPowerRequest mPowerRequest;
340 
341     // The current power state.
342     // Must only be accessed on the handler thread.
343     private DisplayPowerState mPowerState;
344 
345 
346 
347     // The currently active screen on unblocker.  This field is non-null whenever
348     // we are waiting for a callback to release it and unblock the screen.
349     private ScreenOnUnblocker mPendingScreenOnUnblocker;
350     private ScreenOffUnblocker mPendingScreenOffUnblocker;
351     private Runnable mPendingScreenOnUnblockerByDisplayOffload;
352 
353     // True if we were in the process of turning off the screen.
354     // This allows us to recover more gracefully from situations where we abort
355     // turning off the screen.
356     private boolean mPendingScreenOff;
357 
358     // The elapsed real time when the screen on was blocked.
359     private long mScreenOnBlockStartRealTime;
360     private long mScreenOffBlockStartRealTime;
361     private long mScreenOnBlockByDisplayOffloadStartRealTime;
362 
363     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_* fields.
364     private int mReportedScreenStateToPolicy = REPORTED_TO_POLICY_UNREPORTED;
365 
366     // Used to deduplicate the displayoffload blocking screen on logic. One block per turning on.
367     // This value is reset when screen on is reported or the blocking is cancelled.
368     private boolean mScreenTurningOnWasBlockedByDisplayOffload;
369 
370     // If the last recorded screen state was dozing or not.
371     private boolean mDozing;
372 
373     private boolean mAppliedDimming;
374 
375     private boolean mAppliedThrottling;
376 
377     // Reason for which the brightness was last changed. See {@link BrightnessReason} for more
378     // information.
379     // At the time of this writing, this value is changed within updatePowerState() only, which is
380     // limited to the thread used by DisplayControllerHandler.
381     @VisibleForTesting
382     final BrightnessReason mBrightnessReason = new BrightnessReason();
383     private final BrightnessReason mBrightnessReasonTemp = new BrightnessReason();
384 
385     // Brightness animation ramp rates in brightness units per second
386     private float mBrightnessRampRateFastDecrease;
387     private float mBrightnessRampRateFastIncrease;
388     private float mBrightnessRampRateSlowDecrease;
389     private float mBrightnessRampRateSlowIncrease;
390     private float mBrightnessRampRateSlowDecreaseIdle;
391     private float mBrightnessRampRateSlowIncreaseIdle;
392 
393     // Report HBM brightness change to StatsD
394     private int mDisplayStatsId;
395     private float mLastStatsBrightness = PowerManager.BRIGHTNESS_MIN;
396 
397     // Whether or not to skip the initial brightness ramps into STATE_ON.
398     private final boolean mSkipScreenOnBrightnessRamp;
399 
400     // Display white balance components.
401     // Critical methods must be called on DPC2 handler thread.
402     @Nullable
403     private final DisplayWhiteBalanceSettings mDisplayWhiteBalanceSettings;
404     @Nullable
405     private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
406 
407     @Nullable
408     private final ColorDisplayServiceInternal mCdsi;
409     private float[] mNitsRange;
410 
411     private final BrightnessRangeController mBrightnessRangeController;
412 
413     private final BrightnessThrottler mBrightnessThrottler;
414 
415     private final BrightnessClamperController mBrightnessClamperController;
416 
417     private final Runnable mOnBrightnessChangeRunnable;
418 
419     private final BrightnessEvent mLastBrightnessEvent;
420     private final BrightnessEvent mTempBrightnessEvent;
421 
422     private final DisplayBrightnessController mDisplayBrightnessController;
423 
424     // Keeps a record of brightness changes for dumpsys.
425     private RingBuffer<BrightnessEvent> mBrightnessEventRingBuffer;
426 
427     // Keeps a record of rbc changes for dumpsys.
428     private final RingBuffer<BrightnessEvent> mRbcEventRingBuffer =
429             new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_RBC_MAX);
430 
431     // Controls and tracks all the wakelocks that are acquired/released by the system. Also acts as
432     // a medium of communication between this class and the PowerManagerService.
433     private final WakelockController mWakelockController;
434 
435     // Tracks and manages the proximity state of the associated display.
436     private final DisplayPowerProximityStateController mDisplayPowerProximityStateController;
437 
438     // Tracks and manages the display state of the associated display.
439     private final DisplayStateController mDisplayStateController;
440 
441 
442     // Responsible for evaluating and tracking the automatic brightness relevant states.
443     // Todo: This is a temporary workaround. Ideally DPC2 should never talk to the strategies
444     private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy;
445 
446     // A record of state for skipping brightness ramps.
447     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
448 
449     // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
450     private float mInitialAutoBrightness;
451 
452     // The controller for the automatic brightness level.
453     @Nullable
454     private AutomaticBrightnessController mAutomaticBrightnessController;
455 
456     // The controller for the sensor used to estimate ambient lux while the display is off.
457     @Nullable
458     private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
459 
460     private Sensor mLightSensor;
461     private Sensor mScreenOffBrightnessSensor;
462 
463     private boolean mIsRbcActive;
464 
465     // Animators.
466     private ObjectAnimator mColorFadeOnAnimator;
467     private ObjectAnimator mColorFadeOffAnimator;
468     private DualRampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
469 
470     // True if this DisplayPowerController2 has been stopped and should no longer be running.
471     private boolean mStopped;
472 
473     private DisplayDeviceConfig mDisplayDeviceConfig;
474 
475     private boolean mIsEnabled;
476     private boolean mIsInTransition;
477     private boolean mIsDisplayInternal;
478 
479     // The id of the thermal brightness throttling policy that should be used.
480     private String mThermalBrightnessThrottlingDataId;
481 
482     // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
483     // is one lead display, the additional displays follow the brightness value of the lead display.
484     @GuardedBy("mLock")
485     private SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
486             new SparseArray();
487 
488     private boolean mBootCompleted;
489     private final DisplayManagerFlags mFlags;
490 
491     private DisplayOffloadSession mDisplayOffloadSession;
492 
493     // Used to scale the brightness in doze mode
494     private float mDozeScaleFactor;
495 
496     /**
497      * Creates the display power controller.
498      */
DisplayPowerController(Context context, Injector injector, DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay, BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting, Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata, boolean bootCompleted, DisplayManagerFlags flags)499     DisplayPowerController(Context context, Injector injector,
500             DisplayPowerCallbacks callbacks, Handler handler,
501             SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
502             BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
503             Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
504             boolean bootCompleted, DisplayManagerFlags flags) {
505         mFlags = flags;
506         mInjector = injector != null ? injector : new Injector();
507         mClock = mInjector.getClock();
508         mLogicalDisplay = logicalDisplay;
509         mDisplayId = mLogicalDisplay.getDisplayIdLocked();
510         mSensorManager = sensorManager;
511         mHandler = new DisplayControllerHandler(handler.getLooper());
512         mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
513                 .getDisplayDeviceConfig();
514         mIsEnabled = logicalDisplay.isEnabledLocked();
515         mIsInTransition = logicalDisplay.isInTransitionLocked();
516         mIsDisplayInternal = logicalDisplay.getPrimaryDisplayDeviceLocked()
517                 .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL;
518         mWakelockController = mInjector.getWakelockController(mDisplayId, callbacks);
519         mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
520                 mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
521                 () -> updatePowerState(), mDisplayId, mSensorManager);
522         mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
523         mTag = TAG + "[" + mDisplayId + "]";
524         mThermalBrightnessThrottlingDataId =
525                 logicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
526         mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
527         mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
528         mDisplayStatsId = mUniqueDisplayId.hashCode();
529 
530         mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
531         mTempBrightnessEvent = new BrightnessEvent(mDisplayId);
532 
533         if (mDisplayId == Display.DEFAULT_DISPLAY) {
534             mBatteryStats = BatteryStatsService.getService();
535         } else {
536             mBatteryStats = null;
537         }
538 
539         mSettingsObserver = new SettingsObserver(mHandler);
540         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
541         mBlanker = blanker;
542         mContext = context;
543         mBrightnessTracker = brightnessTracker;
544         mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
545 
546         PowerManager pm = context.getSystemService(PowerManager.class);
547 
548         final Resources resources = context.getResources();
549 
550         // DOZE AND DIM SETTINGS
551         mScreenBrightnessDozeConfig = BrightnessUtils.clampAbsoluteBrightness(
552                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
553         loadBrightnessRampRates();
554         mSkipScreenOnBrightnessRamp = resources.getBoolean(
555                 R.bool.config_skipScreenOnBrightnessRamp);
556         mDozeScaleFactor = context.getResources().getFraction(
557                 R.fraction.config_screenAutoBrightnessDozeScaleFactor,
558                 1, 1);
559 
560         Runnable modeChangeCallback = () -> {
561             sendUpdatePowerState();
562             postBrightnessChangeRunnable();
563             // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
564             if (mAutomaticBrightnessController != null) {
565                 mAutomaticBrightnessController.update();
566             }
567         };
568 
569         HighBrightnessModeController hbmController = createHbmControllerLocked(hbmMetadata,
570                 modeChangeCallback);
571         mBrightnessThrottler = createBrightnessThrottlerLocked();
572 
573         mBrightnessRangeController = mInjector.getBrightnessRangeController(hbmController,
574                 modeChangeCallback, mDisplayDeviceConfig, mHandler, flags,
575                 mDisplayDevice.getDisplayTokenLocked(),
576                 mDisplayDevice.getDisplayDeviceInfoLocked());
577 
578         mDisplayBrightnessController =
579                 new DisplayBrightnessController(context, null,
580                         mDisplayId, mLogicalDisplay.getDisplayInfoLocked().brightnessDefault,
581                         brightnessSetting, () -> postBrightnessChangeRunnable(),
582                         new HandlerExecutor(mHandler), flags);
583 
584         mBrightnessClamperController = mInjector.getBrightnessClamperController(
585                 mHandler, modeChangeCallback::run,
586                 new BrightnessClamperController.DisplayDeviceData(
587                         mUniqueDisplayId,
588                         mThermalBrightnessThrottlingDataId,
589                         logicalDisplay.getPowerThrottlingDataIdLocked(),
590                         mDisplayDeviceConfig), mContext, flags, mSensorManager);
591         // Seed the cached brightness
592         saveBrightnessInfo(getScreenBrightnessSetting());
593         mAutomaticBrightnessStrategy =
594                 mDisplayBrightnessController.getAutomaticBrightnessStrategy();
595 
596         DisplayWhiteBalanceSettings displayWhiteBalanceSettings = null;
597         DisplayWhiteBalanceController displayWhiteBalanceController = null;
598         if (mDisplayId == Display.DEFAULT_DISPLAY) {
599             try {
600                 displayWhiteBalanceController = mInjector.getDisplayWhiteBalanceController(
601                         mHandler, mSensorManager, resources);
602                 displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
603                 displayWhiteBalanceSettings.setCallbacks(this);
604                 displayWhiteBalanceController.setCallbacks(this);
605             } catch (Exception e) {
606                 Slog.e(mTag, "failed to set up display white-balance: " + e);
607             }
608         }
609         mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
610         mDisplayWhiteBalanceController = displayWhiteBalanceController;
611 
612         loadNitsRange(resources);
613 
614         if (mDisplayId == Display.DEFAULT_DISPLAY) {
615             mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
616             if (mCdsi != null) {
617                 boolean active = mCdsi.setReduceBrightColorsListener(
618                         new ReduceBrightColorsListener() {
619                             @Override
620                             public void onReduceBrightColorsActivationChanged(boolean activated,
621                                     boolean userInitiated) {
622                                 applyReduceBrightColorsSplineAdjustment();
623 
624                             }
625 
626                             @Override
627                             public void onReduceBrightColorsStrengthChanged(int strength) {
628                                 applyReduceBrightColorsSplineAdjustment();
629                             }
630                         });
631                 if (active) {
632                     applyReduceBrightColorsSplineAdjustment();
633                 }
634             }
635         } else {
636             mCdsi = null;
637         }
638 
639         setUpAutoBrightness(context, handler);
640 
641         mColorFadeEnabled = mInjector.isColorFadeEnabled()
642                 && !resources.getBoolean(
643                   com.android.internal.R.bool.config_displayColorFadeDisabled);
644         mColorFadeFadesConfig = resources.getBoolean(
645                 R.bool.config_animateScreenLights);
646 
647         mDisplayBlanksAfterDozeConfig = resources.getBoolean(
648                 R.bool.config_displayBlanksAfterDoze);
649 
650         mBrightnessBucketsInDozeConfig = resources.getBoolean(
651                 R.bool.config_displayBrightnessBucketsInDoze);
652 
653         mBootCompleted = bootCompleted;
654     }
655 
applyReduceBrightColorsSplineAdjustment()656     private void applyReduceBrightColorsSplineAdjustment() {
657         mHandler.obtainMessage(MSG_UPDATE_RBC).sendToTarget();
658         sendUpdatePowerState();
659     }
660 
handleRbcChanged()661     private void handleRbcChanged() {
662         if (mAutomaticBrightnessController == null) {
663             return;
664         }
665 
666         float[] adjustedNits = new float[mNitsRange.length];
667         for (int i = 0; i < mNitsRange.length; i++) {
668             adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
669         }
670         mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
671         mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
672     }
673 
674     /**
675      * Returns true if the proximity sensor screen-off function is available.
676      */
677     @Override
isProximitySensorAvailable()678     public boolean isProximitySensorAvailable() {
679         return mDisplayPowerProximityStateController.isProximitySensorAvailable();
680     }
681 
682     /**
683      * Get the {@link BrightnessChangeEvent}s for the specified user.
684      *
685      * @param userId         userId to fetch data for
686      * @param includePackage if false will null out the package name in events
687      */
688     @Nullable
689     @Override
getBrightnessEvents( @serIdInt int userId, boolean includePackage)690     public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
691             @UserIdInt int userId, boolean includePackage) {
692         if (mBrightnessTracker == null) {
693             return null;
694         }
695         return mBrightnessTracker.getEvents(userId, includePackage);
696     }
697 
698     @Override
onSwitchUser(@serIdInt int newUserId, int userSerial, float newBrightness)699     public void onSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
700         Message msg = mHandler.obtainMessage(MSG_SWITCH_USER, newUserId, userSerial, newBrightness);
701         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
702     }
703 
handleOnSwitchUser(@serIdInt int newUserId, int userSerial, float newBrightness)704     private void handleOnSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
705         Slog.i(mTag, "Switching user newUserId=" + newUserId + " userSerial=" + userSerial
706                 + " newBrightness=" + newBrightness);
707         handleBrightnessModeChange();
708         if (mBrightnessTracker != null) {
709             mBrightnessTracker.onSwitchUser(newUserId);
710         }
711         setBrightness(newBrightness, userSerial);
712 
713         // Don't treat user switches as user initiated change.
714         mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(newBrightness);
715 
716         if (mAutomaticBrightnessController != null) {
717             mAutomaticBrightnessController.resetShortTermModel();
718         }
719         sendUpdatePowerState();
720     }
721 
722     @Nullable
723     @Override
getAmbientBrightnessStats( @serIdInt int userId)724     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
725             @UserIdInt int userId) {
726         if (mBrightnessTracker == null) {
727             return null;
728         }
729         return mBrightnessTracker.getAmbientBrightnessStats(userId);
730     }
731 
732     /**
733      * Persist the brightness slider events and ambient brightness stats to disk.
734      */
735     @Override
persistBrightnessTrackerState()736     public void persistBrightnessTrackerState() {
737         if (mBrightnessTracker != null) {
738             mBrightnessTracker.persistBrightnessTrackerState();
739         }
740     }
741 
742     /**
743      * Requests a new power state.
744      * The controller makes a copy of the provided object and then
745      * begins adjusting the power state to match what was requested.
746      *
747      * @param request                  The requested power state.
748      * @param waitForNegativeProximity If true, issues a request to wait for
749      *                                 negative proximity before turning the screen back on,
750      *                                 assuming the screen
751      *                                 was turned off by the proximity sensor.
752      * @return True if display is ready, false if there are important changes that must
753      * be made asynchronously (such as turning the screen on), in which case the caller
754      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
755      * then try the request again later until the state converges.
756      */
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)757     public boolean requestPowerState(DisplayPowerRequest request,
758             boolean waitForNegativeProximity) {
759         if (DEBUG) {
760             Slog.d(mTag, "requestPowerState: "
761                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
762         }
763 
764         synchronized (mLock) {
765             if (mStopped) {
766                 return true;
767             }
768 
769             boolean changed = mDisplayPowerProximityStateController
770                     .setPendingWaitForNegativeProximityLocked(waitForNegativeProximity);
771 
772             if (mPendingRequestLocked == null) {
773                 mPendingRequestLocked = new DisplayPowerRequest(request);
774                 changed = true;
775             } else if (!mPendingRequestLocked.equals(request)) {
776                 mPendingRequestLocked.copyFrom(request);
777                 changed = true;
778             }
779 
780             if (changed) {
781                 mDisplayReadyLocked = false;
782                 if (!mPendingRequestChangedLocked) {
783                     mPendingRequestChangedLocked = true;
784                     sendUpdatePowerStateLocked();
785                 }
786             }
787 
788             return mDisplayReadyLocked;
789         }
790     }
791 
792     @Override
overrideDozeScreenState(int displayState, @Display.StateReason int reason)793     public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
794         Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
795         mHandler.postAtTime(() -> {
796             if (mDisplayOffloadSession == null
797                     || !(DisplayOffloadSession.isSupportedOffloadState(displayState)
798                             || displayState == Display.STATE_UNKNOWN)) {
799                 return;
800             }
801             mDisplayStateController.overrideDozeScreenState(displayState, reason);
802             updatePowerState();
803         }, mClock.uptimeMillis());
804     }
805 
806     @Override
setDisplayOffloadSession(DisplayOffloadSession session)807     public void setDisplayOffloadSession(DisplayOffloadSession session) {
808         if (session == mDisplayOffloadSession) {
809             return;
810         }
811         unblockScreenOnByDisplayOffload();
812         mDisplayOffloadSession = session;
813     }
814 
815     @Override
getDefaultBrightnessConfiguration()816     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
817         if (mAutomaticBrightnessController == null) {
818             return null;
819         }
820         return mAutomaticBrightnessController.getDefaultConfig();
821     }
822 
823     /**
824      * Notified when the display is changed. We use this to apply any changes that might be needed
825      * when displays get swapped on foldable devices.  For example, different brightness properties
826      * of each display need to be properly reflected in AutomaticBrightnessController.
827      *
828      * Make sure DisplayManagerService.mSyncRoot lock is held when this is called
829      */
830     @Override
onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId)831     public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
832         mLeadDisplayId = leadDisplayId;
833         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
834         if (device == null) {
835             Slog.wtf(mTag, "Display Device is null in DisplayPowerController2 for display: "
836                     + mLogicalDisplay.getDisplayIdLocked());
837             return;
838         }
839 
840         final String uniqueId = device.getUniqueId();
841         final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
842         final IBinder token = device.getDisplayTokenLocked();
843         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
844         final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
845         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
846         final boolean isDisplayInternal = mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
847                 && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
848                 .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL;
849         final String thermalBrightnessThrottlingDataId =
850                 mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
851         final String powerThrottlingDataId =
852                 mLogicalDisplay.getPowerThrottlingDataIdLocked();
853 
854         mHandler.postAtTime(() -> {
855             boolean changed = false;
856 
857             if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
858                 changed = true;
859                 mIsEnabled = isEnabled;
860                 mIsInTransition = isInTransition;
861             }
862 
863             if (mDisplayDevice != device) {
864                 changed = true;
865                 mDisplayDevice = device;
866                 mUniqueDisplayId = uniqueId;
867                 mDisplayStatsId = mUniqueDisplayId.hashCode();
868                 mDisplayDeviceConfig = config;
869                 mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
870                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
871                 mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
872 
873                 // Since the underlying display-device changed, we really don't know the
874                 // last command that was sent to change it's state. Let's assume it is unknown so
875                 // that we trigger a change immediately.
876                 mPowerState.resetScreenState();
877             } else if (!Objects.equals(mThermalBrightnessThrottlingDataId,
878                     thermalBrightnessThrottlingDataId)) {
879                 changed = true;
880                 mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
881                 mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
882                         config.getThermalBrightnessThrottlingDataMapByThrottlingId(),
883                         config.getTempSensor(),
884                         mThermalBrightnessThrottlingDataId,
885                         mUniqueDisplayId);
886             }
887 
888             mIsDisplayInternal = isDisplayInternal;
889             // using local variables here, when mBrightnessThrottler is removed,
890             // mThermalBrightnessThrottlingDataId could be removed as well
891             // changed = true will be not needed - clampers are maintaining their state and
892             // will call updatePowerState if needed.
893             mBrightnessClamperController.onDisplayChanged(
894                     new BrightnessClamperController.DisplayDeviceData(uniqueId,
895                         thermalBrightnessThrottlingDataId, powerThrottlingDataId, config));
896 
897             if (changed) {
898                 updatePowerState();
899             }
900         }, mClock.uptimeMillis());
901     }
902 
903     /**
904      * Unregisters all listeners and interrupts all running threads; halting future work.
905      *
906      * This method should be called when the DisplayPowerController2 is no longer in use; i.e. when
907      * the {@link #mDisplayId display} has been removed.
908      */
909     @Override
stop()910     public void stop() {
911         synchronized (mLock) {
912             clearDisplayBrightnessFollowersLocked();
913 
914             mStopped = true;
915             Message msg = mHandler.obtainMessage(MSG_STOP);
916             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
917 
918             if (mAutomaticBrightnessController != null) {
919                 mAutomaticBrightnessController.stop();
920             }
921 
922             mDisplayBrightnessController.stop();
923 
924             mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
925         }
926     }
927 
loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info, HighBrightnessModeMetadata hbmMetadata)928     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
929             HighBrightnessModeMetadata hbmMetadata) {
930         // All properties that depend on the associated DisplayDevice and the DDC must be
931         // updated here.
932         loadBrightnessRampRates();
933         loadNitsRange(mContext.getResources());
934         setUpAutoBrightness(mContext, mHandler);
935         reloadReduceBrightColours();
936         setAnimatorRampSpeeds(/* isIdleMode= */ false);
937 
938         mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig);
939         mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
940                 mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(),
941                 mDisplayDeviceConfig.getTempSensor(),
942                 mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
943     }
944 
sendUpdatePowerState()945     private void sendUpdatePowerState() {
946         synchronized (mLock) {
947             sendUpdatePowerStateLocked();
948         }
949     }
950 
951     @GuardedBy("mLock")
sendUpdatePowerStateLocked()952     private void sendUpdatePowerStateLocked() {
953         if (!mStopped && !mPendingUpdatePowerStateLocked) {
954             mPendingUpdatePowerStateLocked = true;
955             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
956             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
957         }
958     }
959 
initialize(int displayState)960     private void initialize(int displayState) {
961         mPowerState = mInjector.getDisplayPowerState(mBlanker,
962                 mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId, displayState);
963 
964         if (mColorFadeEnabled) {
965             mColorFadeOnAnimator = ObjectAnimator.ofFloat(
966                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
967             mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
968             mColorFadeOnAnimator.addListener(mAnimatorListener);
969 
970             mColorFadeOffAnimator = ObjectAnimator.ofFloat(
971                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
972             mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
973             mColorFadeOffAnimator.addListener(mAnimatorListener);
974         }
975 
976         mScreenBrightnessRampAnimator = mInjector.getDualRampAnimator(mPowerState,
977                 DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
978                 DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
979         setAnimatorRampSpeeds(mAutomaticBrightnessController != null
980                 && mAutomaticBrightnessController.isInIdleMode());
981         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
982 
983         noteScreenState(mPowerState.getScreenState(), Display.STATE_REASON_DEFAULT_POLICY);
984         noteScreenBrightness(mPowerState.getScreenBrightness());
985 
986         // Initialize all of the brightness tracking state
987         final float brightness = mDisplayBrightnessController.convertToAdjustedNits(
988                 mPowerState.getScreenBrightness());
989         if (mBrightnessTracker != null && brightness >= PowerManager.BRIGHTNESS_MIN) {
990             mBrightnessTracker.start(brightness);
991         }
992 
993         BrightnessSetting.BrightnessSettingListener brightnessSettingListener = brightnessValue -> {
994             Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
995             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
996         };
997         mDisplayBrightnessController
998                 .registerBrightnessSettingChangeListener(brightnessSettingListener);
999 
1000         mContext.getContentResolver().registerContentObserver(
1001                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
1002                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
1003         mContext.getContentResolver().registerContentObserver(
1004                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
1005                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
1006         if (mFlags.areAutoBrightnessModesEnabled()) {
1007             mContext.getContentResolver().registerContentObserver(
1008                     Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_ALS),
1009                     /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_CURRENT);
1010         }
1011         handleBrightnessModeChange();
1012     }
1013 
setUpAutoBrightness(Context context, Handler handler)1014     private void setUpAutoBrightness(Context context, Handler handler) {
1015         mUseSoftwareAutoBrightnessConfig = mDisplayDeviceConfig.isAutoBrightnessAvailable();
1016 
1017         if (!mUseSoftwareAutoBrightnessConfig) {
1018             return;
1019         }
1020 
1021         SparseArray<BrightnessMappingStrategy> brightnessMappers = new SparseArray<>();
1022 
1023         BrightnessMappingStrategy defaultModeBrightnessMapper =
1024                 mInjector.getDefaultModeBrightnessMapper(context, mDisplayDeviceConfig,
1025                         mDisplayWhiteBalanceController);
1026         brightnessMappers.append(AUTO_BRIGHTNESS_MODE_DEFAULT,
1027                 defaultModeBrightnessMapper);
1028 
1029         final boolean isIdleScreenBrightnessEnabled = context.getResources().getBoolean(
1030                 R.bool.config_enableIdleScreenBrightnessMode);
1031         if (isIdleScreenBrightnessEnabled) {
1032             BrightnessMappingStrategy idleModeBrightnessMapper =
1033                     BrightnessMappingStrategy.create(context, mDisplayDeviceConfig,
1034                             AUTO_BRIGHTNESS_MODE_IDLE,
1035                             mDisplayWhiteBalanceController);
1036             if (idleModeBrightnessMapper != null) {
1037                 brightnessMappers.append(AUTO_BRIGHTNESS_MODE_IDLE,
1038                         idleModeBrightnessMapper);
1039             }
1040         }
1041 
1042         BrightnessMappingStrategy dozeModeBrightnessMapper =
1043                 BrightnessMappingStrategy.create(context, mDisplayDeviceConfig,
1044                         AUTO_BRIGHTNESS_MODE_DOZE, mDisplayWhiteBalanceController);
1045         if (mFlags.areAutoBrightnessModesEnabled() && dozeModeBrightnessMapper != null) {
1046             brightnessMappers.put(AUTO_BRIGHTNESS_MODE_DOZE, dozeModeBrightnessMapper);
1047         }
1048 
1049         float userLux = BrightnessMappingStrategy.INVALID_LUX;
1050         float userNits = BrightnessMappingStrategy.INVALID_NITS;
1051         if (mAutomaticBrightnessController != null) {
1052             userLux = mAutomaticBrightnessController.getUserLux();
1053             userNits = mAutomaticBrightnessController.getUserNits();
1054         }
1055 
1056         if (defaultModeBrightnessMapper != null) {
1057             // Ambient Lux - Active Mode Brightness Thresholds
1058             HysteresisLevels ambientBrightnessThresholds =
1059                     mDisplayDeviceConfig.getAmbientBrightnessHysteresis();
1060 
1061             // Display - Active Mode Brightness Thresholds
1062             HysteresisLevels screenBrightnessThresholds =
1063                     mDisplayDeviceConfig.getScreenBrightnessHysteresis();
1064 
1065             // Ambient Lux - Idle Screen Brightness Thresholds
1066             HysteresisLevels ambientBrightnessThresholdsIdle =
1067                     mDisplayDeviceConfig.getAmbientBrightnessIdleHysteresis();
1068 
1069             // Display - Idle Screen Brightness Thresholds
1070             HysteresisLevels screenBrightnessThresholdsIdle =
1071                     mDisplayDeviceConfig.getScreenBrightnessIdleHysteresis();
1072 
1073             long brighteningLightDebounce = mDisplayDeviceConfig
1074                     .getAutoBrightnessBrighteningLightDebounce();
1075             long darkeningLightDebounce = mDisplayDeviceConfig
1076                     .getAutoBrightnessDarkeningLightDebounce();
1077             long brighteningLightDebounceIdle = mDisplayDeviceConfig
1078                     .getAutoBrightnessBrighteningLightDebounceIdle();
1079             long darkeningLightDebounceIdle = mDisplayDeviceConfig
1080                     .getAutoBrightnessDarkeningLightDebounceIdle();
1081             boolean autoBrightnessResetAmbientLuxAfterWarmUp = context.getResources().getBoolean(
1082                     R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
1083 
1084             int lightSensorWarmUpTimeConfig = context.getResources().getInteger(
1085                     R.integer.config_lightSensorWarmupTime);
1086             int lightSensorRate = context.getResources().getInteger(
1087                     R.integer.config_autoBrightnessLightSensorRate);
1088             int initialLightSensorRate = context.getResources().getInteger(
1089                     R.integer.config_autoBrightnessInitialLightSensorRate);
1090             if (initialLightSensorRate == -1) {
1091                 initialLightSensorRate = lightSensorRate;
1092             } else if (initialLightSensorRate > lightSensorRate) {
1093                 Slog.w(mTag, "Expected config_autoBrightnessInitialLightSensorRate ("
1094                         + initialLightSensorRate + ") to be less than or equal to "
1095                         + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
1096             }
1097 
1098             loadAmbientLightSensor();
1099             // BrightnessTracker should only use one light sensor, we want to use the light sensor
1100             // from the default display and not e.g. temporary displays when switching layouts.
1101             if (mBrightnessTracker != null && mDisplayId == Display.DEFAULT_DISPLAY) {
1102                 mBrightnessTracker.setLightSensor(mLightSensor);
1103             }
1104 
1105             if (mAutomaticBrightnessController != null) {
1106                 mAutomaticBrightnessController.stop();
1107             }
1108             mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
1109                     this, handler.getLooper(), mSensorManager, mLightSensor,
1110                     brightnessMappers, lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
1111                     PowerManager.BRIGHTNESS_MAX, mDozeScaleFactor, lightSensorRate,
1112                     initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
1113                     brighteningLightDebounceIdle, darkeningLightDebounceIdle,
1114                     autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
1115                     screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
1116                     screenBrightnessThresholdsIdle, mContext, mBrightnessRangeController,
1117                     mBrightnessThrottler, mDisplayDeviceConfig.getAmbientHorizonShort(),
1118                     mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits,
1119                     mBrightnessClamperController, mFlags);
1120             mDisplayBrightnessController.setUpAutoBrightness(
1121                     mAutomaticBrightnessController, mSensorManager, mDisplayDeviceConfig, mHandler,
1122                     defaultModeBrightnessMapper, mIsEnabled, mLeadDisplayId);
1123             mBrightnessEventRingBuffer =
1124                     new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
1125             if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
1126                 if (mScreenOffBrightnessSensorController != null) {
1127                     mScreenOffBrightnessSensorController.stop();
1128                     mScreenOffBrightnessSensorController = null;
1129                 }
1130                 loadScreenOffBrightnessSensor();
1131                 int[] sensorValueToLux =
1132                         mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
1133                 if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
1134                     mScreenOffBrightnessSensorController =
1135                             mInjector.getScreenOffBrightnessSensorController(
1136                                     mSensorManager,
1137                                     mScreenOffBrightnessSensor,
1138                                     mHandler,
1139                                     SystemClock::uptimeMillis,
1140                                     sensorValueToLux,
1141                                     defaultModeBrightnessMapper);
1142                 }
1143             }
1144         } else {
1145             mUseSoftwareAutoBrightnessConfig = false;
1146         }
1147     }
1148 
loadBrightnessRampRates()1149     private void loadBrightnessRampRates() {
1150         mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease();
1151         mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
1152         mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
1153         mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
1154         mBrightnessRampRateSlowDecreaseIdle =
1155                 mDisplayDeviceConfig.getBrightnessRampSlowDecreaseIdle();
1156         mBrightnessRampRateSlowIncreaseIdle =
1157                 mDisplayDeviceConfig.getBrightnessRampSlowIncreaseIdle();
1158         mBrightnessRampDecreaseMaxTimeMillis =
1159                 mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis();
1160         mBrightnessRampIncreaseMaxTimeMillis =
1161                 mDisplayDeviceConfig.getBrightnessRampIncreaseMaxMillis();
1162         mBrightnessRampDecreaseMaxTimeIdleMillis =
1163                 mDisplayDeviceConfig.getBrightnessRampDecreaseMaxIdleMillis();
1164         mBrightnessRampIncreaseMaxTimeIdleMillis =
1165                 mDisplayDeviceConfig.getBrightnessRampIncreaseMaxIdleMillis();
1166     }
1167 
loadNitsRange(Resources resources)1168     private void loadNitsRange(Resources resources) {
1169         if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) {
1170             mNitsRange = mDisplayDeviceConfig.getNits();
1171         } else {
1172             Slog.w(mTag, "Screen brightness nits configuration is unavailable; falling back");
1173             mNitsRange = BrightnessMappingStrategy.getFloatArray(resources
1174                     .obtainTypedArray(R.array.config_screenBrightnessNits));
1175         }
1176     }
1177 
reloadReduceBrightColours()1178     private void reloadReduceBrightColours() {
1179         if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) {
1180             applyReduceBrightColorsSplineAdjustment();
1181         }
1182     }
1183 
1184     @Override
setAutomaticScreenBrightnessMode( @utomaticBrightnessController.AutomaticBrightnessMode int mode)1185     public void setAutomaticScreenBrightnessMode(
1186             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
1187         Message msg = mHandler.obtainMessage();
1188         msg.what = MSG_SWITCH_AUTOBRIGHTNESS_MODE;
1189         msg.arg1 = mode;
1190         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
1191     }
1192 
setAnimatorRampSpeeds(boolean isIdle)1193     private void setAnimatorRampSpeeds(boolean isIdle) {
1194         if (mScreenBrightnessRampAnimator == null) {
1195             return;
1196         }
1197         if (mFlags.isAdaptiveTone1Enabled() && isIdle) {
1198             mScreenBrightnessRampAnimator.setAnimationTimeLimits(
1199                     mBrightnessRampIncreaseMaxTimeIdleMillis,
1200                     mBrightnessRampDecreaseMaxTimeIdleMillis);
1201         } else {
1202             mScreenBrightnessRampAnimator.setAnimationTimeLimits(
1203                     mBrightnessRampIncreaseMaxTimeMillis,
1204                     mBrightnessRampDecreaseMaxTimeMillis);
1205         }
1206     }
1207 
1208     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
1209         @Override
1210         public void onAnimationStart(Animator animation) {
1211         }
1212 
1213         @Override
1214         public void onAnimationEnd(Animator animation) {
1215             sendUpdatePowerState();
1216         }
1217 
1218         @Override
1219         public void onAnimationRepeat(Animator animation) {
1220         }
1221 
1222         @Override
1223         public void onAnimationCancel(Animator animation) {
1224         }
1225     };
1226 
1227     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
1228         @Override
1229         public void onAnimationEnd() {
1230             sendUpdatePowerState();
1231             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
1232             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
1233         }
1234     };
1235 
1236     /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
cleanupHandlerThreadAfterStop()1237     private void cleanupHandlerThreadAfterStop() {
1238         mDisplayPowerProximityStateController.cleanup();
1239         mBrightnessRangeController.stop();
1240         mBrightnessThrottler.stop();
1241         mBrightnessClamperController.stop();
1242         mHandler.removeCallbacksAndMessages(null);
1243 
1244         // Release any outstanding wakelocks we're still holding because of pending messages.
1245         mWakelockController.releaseAll();
1246 
1247         final float brightness = mPowerState != null
1248                 ? mPowerState.getScreenBrightness()
1249                 : PowerManager.BRIGHTNESS_MIN;
1250         reportStats(brightness);
1251 
1252         if (mPowerState != null) {
1253             mPowerState.stop();
1254             mPowerState = null;
1255         }
1256 
1257         if (!mFlags.isRefactorDisplayPowerControllerEnabled()
1258                 && mScreenOffBrightnessSensorController != null) {
1259             mScreenOffBrightnessSensorController.stop();
1260         }
1261 
1262         if (mDisplayWhiteBalanceController != null) {
1263             mDisplayWhiteBalanceController.setEnabled(false);
1264         }
1265     }
1266 
1267     // Call from handler thread
updatePowerState()1268     private void updatePowerState() {
1269         Trace.traceBegin(Trace.TRACE_TAG_POWER,
1270                 "DisplayPowerController#updatePowerState");
1271         updatePowerStateInternal();
1272         Trace.traceEnd(Trace.TRACE_TAG_POWER);
1273     }
1274 
updatePowerStateInternal()1275     private void updatePowerStateInternal() {
1276         // Update the power state request.
1277         boolean mustNotify = false;
1278         final int previousPolicy;
1279         boolean mustInitialize = false;
1280         mBrightnessReasonTemp.set(null);
1281         mTempBrightnessEvent.reset();
1282         SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers;
1283         synchronized (mLock) {
1284             if (mStopped) {
1285                 return;
1286             }
1287             mPendingUpdatePowerStateLocked = false;
1288             if (mPendingRequestLocked == null) {
1289                 return; // wait until first actual power request
1290             }
1291 
1292             if (mPowerRequest == null) {
1293                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
1294                 mDisplayPowerProximityStateController.updatePendingProximityRequestsLocked();
1295                 mPendingRequestChangedLocked = false;
1296                 mustInitialize = true;
1297                 // Assume we're on and bright until told otherwise, since that's the state we turn
1298                 // on in.
1299                 previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
1300             } else if (mPendingRequestChangedLocked) {
1301                 previousPolicy = mPowerRequest.policy;
1302                 mPowerRequest.copyFrom(mPendingRequestLocked);
1303                 mDisplayPowerProximityStateController.updatePendingProximityRequestsLocked();
1304                 mPendingRequestChangedLocked = false;
1305                 mDisplayReadyLocked = false;
1306             } else {
1307                 previousPolicy = mPowerRequest.policy;
1308             }
1309 
1310             mustNotify = !mDisplayReadyLocked;
1311 
1312             displayBrightnessFollowers = mDisplayBrightnessFollowers.clone();
1313         }
1314 
1315         final Pair<Integer, Integer> stateAndReason =
1316                 mDisplayStateController
1317                         .updateDisplayState(mPowerRequest, mIsEnabled, mIsInTransition);
1318         int state = stateAndReason.first;
1319 
1320         // Initialize things the first time the power state is changed.
1321         if (mustInitialize) {
1322             initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
1323         }
1324 
1325         if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) {
1326             // Sometimes, a display-state change can come without an associated PowerRequest,
1327             // as with DisplayOffload.  For those cases, we have to make sure to also mark the
1328             // display as "not ready" so that we can inform power-manager when the state-change is
1329             // complete.
1330             if (mPowerState.getScreenState() != state) {
1331                 final boolean wasReady;
1332                 synchronized (mLock) {
1333                     wasReady = mDisplayReadyLocked;
1334                     mDisplayReadyLocked = false;
1335                     mustNotify = true;
1336                 }
1337 
1338                 if (wasReady) {
1339                     // If we went from ready to not-ready from the state-change (instead of a
1340                     // PowerRequest) there's a good chance that nothing is keeping PowerManager
1341                     // from suspending. Grab the unfinished business suspend blocker to keep the
1342                     // device awake until the display-state change goes into effect.
1343                     mWakelockController.acquireWakelock(
1344                             WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
1345                 }
1346             }
1347         }
1348 
1349         // Animate the screen state change unless already animating.
1350         // The transition may be deferred, so after this point we will use the
1351         // actual state instead of the desired one.
1352         animateScreenStateChange(
1353                 state, /* reason= */ stateAndReason.second,
1354                 mDisplayStateController.shouldPerformScreenOffTransition());
1355         state = mPowerState.getScreenState();
1356 
1357         DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController
1358                 .updateBrightness(mPowerRequest, state, mDisplayOffloadSession);
1359         float brightnessState = displayBrightnessState.getBrightness();
1360         float rawBrightnessState = displayBrightnessState.getBrightness();
1361         mBrightnessReasonTemp.set(displayBrightnessState.getBrightnessReason());
1362         boolean slowChange = displayBrightnessState.isSlowChange();
1363         // custom transition duration
1364         float customAnimationRate = displayBrightnessState.getCustomAnimationRate();
1365         int brightnessAdjustmentFlags = displayBrightnessState.getBrightnessAdjustmentFlag();
1366         final boolean userSetBrightnessChanged =
1367                 mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated();
1368         if (displayBrightnessState.getBrightnessEvent() != null) {
1369             mTempBrightnessEvent.copyFrom(displayBrightnessState.getBrightnessEvent());
1370         }
1371 
1372         boolean allowAutoBrightnessWhileDozing =
1373                 mDisplayBrightnessController.isAllowAutoBrightnessWhileDozing();
1374 
1375         if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
1376             // Set up the ScreenOff controller used when coming out of SCREEN_OFF and the ALS sensor
1377             // doesn't yet have a valid lux value to use with auto-brightness.
1378             if (mScreenOffBrightnessSensorController != null) {
1379                 mScreenOffBrightnessSensorController
1380                         .setLightSensorEnabled(displayBrightnessState.getShouldUseAutoBrightness()
1381                         && mIsEnabled && (state == Display.STATE_OFF
1382                         || (state == Display.STATE_DOZE && !allowAutoBrightnessWhileDozing))
1383                         && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
1384             }
1385         }
1386 
1387         // Take note if the short term model was already active before applying the current
1388         // request changes.
1389         final boolean wasShortTermModelActive =
1390                 mAutomaticBrightnessStrategy.isShortTermModelActive();
1391         boolean userInitiatedChange = displayBrightnessState.isUserInitiatedChange();
1392 
1393         if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
1394             // Switch to doze auto-brightness mode if needed
1395             if (mFlags.areAutoBrightnessModesEnabled() && mAutomaticBrightnessController != null
1396                     && !mAutomaticBrightnessController.isInIdleMode()) {
1397                 // Set sendUpdate to false, we're already in updatePowerState() so there's no need
1398                 // to trigger it again
1399                 mAutomaticBrightnessController.switchMode(Display.isDozeState(state)
1400                         ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT,
1401                         /* sendUpdate= */ false);
1402             }
1403 
1404             mAutomaticBrightnessStrategy.setAutoBrightnessState(state,
1405                     allowAutoBrightnessWhileDozing, mBrightnessReasonTemp.getReason(),
1406                     mPowerRequest.policy,
1407                     mDisplayBrightnessController.getLastUserSetScreenBrightness(),
1408                     userSetBrightnessChanged);
1409 
1410             // If the brightness is already set then it's been overridden by something other than
1411             // the user, or is a temporary adjustment.
1412             userInitiatedChange = (Float.isNaN(brightnessState))
1413                     && (mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged()
1414                     || userSetBrightnessChanged);
1415         }
1416 
1417 
1418         final int autoBrightnessState = mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()
1419                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
1420                 : mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()
1421                         ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
1422                         : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
1423 
1424         mBrightnessRangeController.setAutoBrightnessEnabled(autoBrightnessState);
1425 
1426         boolean updateScreenBrightnessSetting =
1427                 displayBrightnessState.shouldUpdateScreenBrightnessSetting();
1428         float currentBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness();
1429 
1430         if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
1431             // AutomaticBrightnessStrategy has higher priority than OffloadBrightnessStrategy
1432             if (Float.isNaN(brightnessState)
1433                     || mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_OFFLOAD) {
1434                 if (mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()) {
1435                     brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
1436                             mTempBrightnessEvent);
1437                     if (BrightnessUtils.isValidBrightnessValue(brightnessState)
1438                             || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
1439                         rawBrightnessState = mAutomaticBrightnessController
1440                                 .getRawAutomaticScreenBrightness();
1441                         // slowly adapt to auto-brightness
1442                         // TODO(b/253226419): slowChange should be decided by
1443                         // strategy.updateBrightness
1444                         slowChange = mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()
1445                                 && !mAutomaticBrightnessStrategy
1446                                 .getAutoBrightnessAdjustmentChanged();
1447                         brightnessAdjustmentFlags =
1448                                 mAutomaticBrightnessStrategy
1449                                         .getAutoBrightnessAdjustmentReasonsFlags();
1450                         updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState;
1451                         mAutomaticBrightnessStrategy.setAutoBrightnessApplied(true);
1452                         mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
1453                         if (mScreenOffBrightnessSensorController != null) {
1454                             mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
1455                         }
1456                         setBrightnessFromOffload(PowerManager.BRIGHTNESS_INVALID_FLOAT);
1457                     } else {
1458                         mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
1459                         // Restore the lower-priority brightness strategy
1460                         brightnessState = displayBrightnessState.getBrightness();
1461                     }
1462                 }
1463             } else {
1464                 mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
1465             }
1466         }
1467 
1468         if (!Float.isNaN(brightnessState)) {
1469             brightnessState = clampScreenBrightness(brightnessState);
1470         }
1471 
1472         if (Display.isDozeState(state)) {
1473             // TODO(b/329676661): Introduce a config property to choose between this brightness
1474             //  strategy and DOZE_DEFAULT
1475             // On some devices, when auto-brightness is disabled and the device is dozing, we use
1476             // the current brightness setting scaled by the doze scale factor
1477             if ((Float.isNaN(brightnessState)
1478                     || displayBrightnessState.getDisplayBrightnessStrategyName()
1479                     .equals(DisplayBrightnessStrategyConstants.FALLBACK_BRIGHTNESS_STRATEGY_NAME))
1480                     && mFlags.isDisplayOffloadEnabled()
1481                     && mDisplayOffloadSession != null
1482                     && (mAutomaticBrightnessController == null
1483                     || !mAutomaticBrightnessStrategy.shouldUseAutoBrightness())) {
1484                 rawBrightnessState = getDozeBrightnessForOffload();
1485                 brightnessState = clampScreenBrightness(rawBrightnessState);
1486                 mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_MANUAL);
1487                 mTempBrightnessEvent.setFlags(
1488                         mTempBrightnessEvent.getFlags() | BrightnessEvent.FLAG_DOZE_SCALE);
1489             }
1490 
1491             // Use default brightness when dozing unless overridden.
1492             if (Float.isNaN(brightnessState) && Display.isDozeState(state)
1493                     && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()) {
1494                 rawBrightnessState = mScreenBrightnessDozeConfig;
1495                 brightnessState = clampScreenBrightness(rawBrightnessState);
1496                 mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
1497             }
1498         }
1499 
1500         if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
1501             // The ALS is not available yet - use the screen off sensor to determine the initial
1502             // brightness
1503             if (Float.isNaN(brightnessState)
1504                     && mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()
1505                     && mScreenOffBrightnessSensorController != null) {
1506                 rawBrightnessState =
1507                         mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
1508                 brightnessState = rawBrightnessState;
1509                 if (BrightnessUtils.isValidBrightnessValue(brightnessState)) {
1510                     brightnessState = clampScreenBrightness(brightnessState);
1511                     updateScreenBrightnessSetting =
1512                             mDisplayBrightnessController.getCurrentBrightness()
1513                                     != brightnessState;
1514                     mBrightnessReasonTemp.setReason(
1515                             BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
1516                 }
1517             }
1518         }
1519 
1520         // Apply manual brightness.
1521         if (Float.isNaN(brightnessState) && !mFlags.isRefactorDisplayPowerControllerEnabled()) {
1522             rawBrightnessState = currentBrightnessSetting;
1523             brightnessState = clampScreenBrightness(rawBrightnessState);
1524             if (brightnessState != currentBrightnessSetting) {
1525                 // The manually chosen screen brightness is outside of the currently allowed
1526                 // range (i.e., high-brightness-mode), make sure we tell the rest of the system
1527                 // by updating the setting.
1528                 updateScreenBrightnessSetting = true;
1529             }
1530             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
1531         }
1532 
1533         float ambientLux = mAutomaticBrightnessController == null ? 0
1534                 : mAutomaticBrightnessController.getAmbientLux();
1535         for (int i = 0; i < displayBrightnessFollowers.size(); i++) {
1536             DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i);
1537             follower.setBrightnessToFollow(rawBrightnessState,
1538                     mDisplayBrightnessController.convertToNits(rawBrightnessState),
1539                     ambientLux, slowChange);
1540         }
1541 
1542         // Now that a desired brightness has been calculated, apply brightness throttling. The
1543         // dimming and low power transformations that follow can only dim brightness further.
1544         //
1545         // We didn't do this earlier through brightness clamping because we need to know both
1546         // unthrottled (unclamped/ideal) and throttled brightness levels for subsequent operations.
1547         // Note throttling effectively changes the allowed brightness range, so, similarly to HBM,
1548         // we broadcast this change through setting.
1549         final float unthrottledBrightnessState = brightnessState;
1550         DisplayBrightnessState clampedState = mBrightnessClamperController.clamp(mPowerRequest,
1551                 brightnessState, slowChange, /* displayState= */ state);
1552 
1553         brightnessState = clampedState.getBrightness();
1554         slowChange = clampedState.isSlowChange();
1555         // faster rate wins, at this point customAnimationRate == -1, strategy does not control
1556         // customAnimationRate. Should be revisited if strategy start setting this value
1557         customAnimationRate = Math.max(customAnimationRate, clampedState.getCustomAnimationRate());
1558         mBrightnessReasonTemp.addModifier(clampedState.getBrightnessReason().getModifier());
1559 
1560         if (updateScreenBrightnessSetting) {
1561             // Tell the rest of the system about the new brightness in case we had to change it
1562             // for things like auto-brightness or high-brightness-mode. Note that we do this
1563             // only considering maxBrightness (ignoring brightness modifiers like low power or dim)
1564             // so that the slider accurately represents the full possible range,
1565             // even if they range changes what it means in absolute terms.
1566             mDisplayBrightnessController.updateScreenBrightnessSetting(
1567                     MathUtils.constrain(unthrottledBrightnessState,
1568                             clampedState.getMinBrightness(), clampedState.getMaxBrightness()),
1569                     Math.min(mBrightnessRangeController.getCurrentBrightnessMax(),
1570                             clampedState.getMaxBrightness()));
1571         }
1572 
1573         // The current brightness to use has been calculated at this point, and HbmController should
1574         // be notified so that it can accurately calculate HDR or HBM levels. We specifically do it
1575         // here instead of having HbmController listen to the brightness setting because certain
1576         // brightness sources (such as an app override) are not saved to the setting, but should be
1577         // reflected in HBM calculations.
1578         mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
1579                 mBrightnessClamperController.getBrightnessMaxReason());
1580 
1581         // Animate the screen brightness when the screen is on or dozing.
1582         // Skip the animation when the screen is off or suspended.
1583         boolean brightnessAdjusted = false;
1584         final boolean brightnessIsTemporary =
1585                 (mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_TEMPORARY)
1586                         || mAutomaticBrightnessStrategy
1587                         .isTemporaryAutoBrightnessAdjustmentApplied();
1588         if (!mPendingScreenOff) {
1589             if (mSkipScreenOnBrightnessRamp) {
1590                 if (state == Display.STATE_ON) {
1591                     if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
1592                         mInitialAutoBrightness = brightnessState;
1593                         mSkipRampState = RAMP_STATE_SKIP_INITIAL;
1594                     } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
1595                             && mUseSoftwareAutoBrightnessConfig
1596                             && !BrightnessSynchronizer.floatEquals(brightnessState,
1597                             mInitialAutoBrightness)) {
1598                         mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
1599                     } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
1600                         mSkipRampState = RAMP_STATE_SKIP_NONE;
1601                     }
1602                 } else {
1603                     mSkipRampState = RAMP_STATE_SKIP_NONE;
1604                 }
1605             }
1606 
1607             final boolean initialRampSkip = (state == Display.STATE_ON && mSkipRampState
1608                     != RAMP_STATE_SKIP_NONE) || mDisplayPowerProximityStateController
1609                     .shouldSkipRampBecauseOfProximityChangeToNegative();
1610             // While dozing, sometimes the brightness is split into buckets. Rather than animating
1611             // through the buckets, which is unlikely to be smooth in the first place, just jump
1612             // right to the suggested brightness.
1613             final boolean hasBrightnessBuckets =
1614                     Display.isDozeState(state) && mBrightnessBucketsInDozeConfig;
1615             // If the color fade is totally covering the screen then we can change the backlight
1616             // level without it being a noticeable jump since any actual content isn't yet visible.
1617             final boolean isDisplayContentVisible =
1618                     mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
1619             // We only want to animate the brightness if it is between 0.0f and 1.0f.
1620             // brightnessState can contain the values -1.0f and NaN, which we do not want to
1621             // animate to. To avoid this, we check the value first.
1622             // If the brightnessState is off (-1.0f) we still want to animate to the minimum
1623             // brightness (0.0f) to accommodate for LED displays, which can appear bright to the
1624             // user even when the display is all black. We also clamp here in case some
1625             // transformations to the brightness have pushed it outside of the currently
1626             // allowed range.
1627             float animateValue = clampScreenBrightness(brightnessState);
1628 
1629             // If there are any HDR layers on the screen, we have a special brightness value that we
1630             // use instead. We still preserve the calculated brightness for Standard Dynamic Range
1631             // (SDR) layers, but the main brightness value will be the one for HDR.
1632             float sdrAnimateValue = animateValue;
1633             // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
1634             // done in HighBrightnessModeController.
1635             if (mBrightnessRangeController.getHighBrightnessMode()
1636                     == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
1637                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
1638                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
1639                     == 0) {
1640                 // We want to scale HDR brightness level with the SDR level, we also need to restore
1641                 // SDR brightness immediately when entering dim or low power mode.
1642                 animateValue = mBrightnessRangeController.getHdrBrightnessValue();
1643                 customAnimationRate = Math.max(customAnimationRate,
1644                         mBrightnessRangeController.getHdrTransitionRate());
1645                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_HDR);
1646             }
1647 
1648             // if doze or suspend state is requested, we want to finish brightnes animation fast
1649             // to allow state animation to start
1650             if (mPowerRequest.policy == POLICY_DOZE
1651                     && (mPowerRequest.dozeScreenState == Display.STATE_UNKNOWN  // dozing
1652                     || mPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
1653                     || mPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND)) {
1654                 customAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET;
1655                 slowChange = false;
1656             }
1657 
1658             final float currentBrightness = mPowerState.getScreenBrightness();
1659             final float currentSdrBrightness = mPowerState.getSdrScreenBrightness();
1660 
1661             if (BrightnessUtils.isValidBrightnessValue(animateValue)
1662                     && (animateValue != currentBrightness
1663                     || sdrAnimateValue != currentSdrBrightness)) {
1664                 boolean skipAnimation = initialRampSkip || hasBrightnessBuckets
1665                         || !isDisplayContentVisible || brightnessIsTemporary;
1666                 final boolean isHdrOnlyChange = BrightnessSynchronizer.floatEquals(
1667                         sdrAnimateValue, currentSdrBrightness);
1668                 if (mFlags.isFastHdrTransitionsEnabled() && !skipAnimation && isHdrOnlyChange) {
1669                     // SDR brightness is unchanged, so animate quickly as this is only impacting
1670                     // a likely minority amount of display content
1671                     // ie, the highlights of an HDR video or UltraHDR image
1672                     // Ideally we'd do this as fast as possible (ie, skip the animation entirely),
1673                     // but this requires display support and would need an entry in the
1674                     // display configuration. For now just do the fast animation
1675                     slowChange = false;
1676                 }
1677                 if (skipAnimation) {
1678                     animateScreenBrightness(animateValue, sdrAnimateValue,
1679                             SCREEN_ANIMATION_RATE_MINIMUM);
1680                 } else if (customAnimationRate > 0) {
1681                     animateScreenBrightness(animateValue, sdrAnimateValue,
1682                             customAnimationRate, /* ignoreAnimationLimits = */true);
1683                 } else {
1684                     boolean isIncreasing = animateValue > currentBrightness;
1685                     final float rampSpeed;
1686                     final boolean idle = mAutomaticBrightnessController != null
1687                             && mAutomaticBrightnessController.isInIdleMode();
1688                     if (isIncreasing && slowChange) {
1689                         rampSpeed = idle ? mBrightnessRampRateSlowIncreaseIdle
1690                                 : mBrightnessRampRateSlowIncrease;
1691                     } else if (isIncreasing && !slowChange) {
1692                         rampSpeed = mBrightnessRampRateFastIncrease;
1693                     } else if (!isIncreasing && slowChange) {
1694                         rampSpeed = idle ? mBrightnessRampRateSlowDecreaseIdle
1695                                 : mBrightnessRampRateSlowDecrease;
1696                     } else {
1697                         rampSpeed = mBrightnessRampRateFastDecrease;
1698                     }
1699                     animateScreenBrightness(animateValue, sdrAnimateValue, rampSpeed);
1700                 }
1701             }
1702 
1703             notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
1704                     wasShortTermModelActive, mAutomaticBrightnessStrategy.isAutoBrightnessEnabled(),
1705                     brightnessIsTemporary, displayBrightnessState.getShouldUseAutoBrightness());
1706 
1707             // We save the brightness info *after* the brightness setting has been changed and
1708             // adjustments made so that the brightness info reflects the latest value.
1709             brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(),
1710                     animateValue, clampedState);
1711         } else {
1712             brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(), clampedState);
1713         }
1714 
1715         // Only notify if the brightness adjustment is not temporary (i.e. slider has been released)
1716         if (brightnessAdjusted && !brightnessIsTemporary) {
1717             postBrightnessChangeRunnable();
1718         }
1719 
1720         // Log any changes to what is currently driving the brightness setting.
1721         if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
1722             Slog.v(mTag, "Brightness [" + brightnessState + "] reason changing to: '"
1723                     + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
1724                     + "', previous reason: '" + mBrightnessReason + "'.");
1725             mBrightnessReason.set(mBrightnessReasonTemp);
1726         } else if (mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_MANUAL
1727                 && userSetBrightnessChanged) {
1728             Slog.v(mTag, "Brightness [" + brightnessState + "] manual adjustment.");
1729         }
1730 
1731 
1732         // Log brightness events when a detail of significance has changed. Generally this is the
1733         // brightness itself changing, but also includes data like HBM cap, thermal throttling
1734         // brightness cap, RBC state, etc.
1735         mTempBrightnessEvent.setTime(System.currentTimeMillis());
1736         mTempBrightnessEvent.setBrightness(brightnessState);
1737         mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId);
1738         mTempBrightnessEvent.setDisplayState(state);
1739         mTempBrightnessEvent.setDisplayPolicy(mPowerRequest.policy);
1740         mTempBrightnessEvent.setReason(mBrightnessReason);
1741         mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax());
1742         mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode());
1743         mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
1744                 | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
1745                 | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
1746         mTempBrightnessEvent.setRbcStrength(mCdsi != null
1747                 ? mCdsi.getReduceBrightColorsStrength() : -1);
1748         mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
1749         mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
1750         mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState
1751                 .getDisplayBrightnessStrategyName());
1752         mTempBrightnessEvent.setAutomaticBrightnessEnabled(
1753                 displayBrightnessState.getShouldUseAutoBrightness());
1754         // Temporary is what we use during slider interactions. We avoid logging those so that
1755         // we don't spam logcat when the slider is being used.
1756         boolean tempToTempTransition =
1757                 mTempBrightnessEvent.getReason().getReason() == BrightnessReason.REASON_TEMPORARY
1758                         && mLastBrightnessEvent.getReason().getReason()
1759                         == BrightnessReason.REASON_TEMPORARY;
1760         // Purely for dumpsys;
1761         final boolean isRbcEvent =
1762                 mLastBrightnessEvent.isRbcEnabled() != mTempBrightnessEvent.isRbcEnabled();
1763 
1764         if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
1765                 || brightnessAdjustmentFlags != 0) {
1766             mTempBrightnessEvent.setInitialBrightness(mLastBrightnessEvent.getBrightness());
1767             mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
1768             BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
1769             // Adjustment flags (and user-set flag) only get added after the equality checks since
1770             // they are transient.
1771             newEvent.setAdjustmentFlags(brightnessAdjustmentFlags);
1772             newEvent.setFlags(newEvent.getFlags() | (userSetBrightnessChanged
1773                     ? BrightnessEvent.FLAG_USER_SET : 0));
1774             Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
1775 
1776             if (userSetBrightnessChanged
1777                     || newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
1778                 logBrightnessEvent(newEvent, unthrottledBrightnessState);
1779             }
1780             if (mBrightnessEventRingBuffer != null) {
1781                 mBrightnessEventRingBuffer.append(newEvent);
1782             }
1783             if (isRbcEvent) {
1784                 mRbcEventRingBuffer.append(newEvent);
1785             }
1786 
1787         }
1788 
1789         // Update display white-balance.
1790         if (mDisplayWhiteBalanceController != null) {
1791             if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
1792                 mDisplayWhiteBalanceController.setEnabled(true);
1793                 mDisplayWhiteBalanceController.updateDisplayColorTemperature();
1794             } else {
1795                 mDisplayWhiteBalanceController.setEnabled(false);
1796             }
1797         }
1798 
1799         // Determine whether the display is ready for use in the newly requested state.
1800         // Note that we do not wait for the brightness ramp animation to complete before
1801         // reporting the display is ready because we only need to ensure the screen is in the
1802         // right power state even as it continues to converge on the desired brightness.
1803         final boolean ready = mPendingScreenOnUnblocker == null
1804                 && mPendingScreenOnUnblockerByDisplayOffload == null
1805                 && (!mColorFadeEnabled || (!mColorFadeOnAnimator.isStarted()
1806                         && !mColorFadeOffAnimator.isStarted()))
1807                 && mPowerState.waitUntilClean(mCleanListener);
1808         final boolean finished = ready
1809                 && !mScreenBrightnessRampAnimator.isAnimating();
1810 
1811         // Notify policy about screen turned on.
1812         if (ready && state != Display.STATE_OFF
1813                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
1814             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
1815             mWindowManagerPolicy.screenTurnedOn(mDisplayId);
1816         }
1817 
1818         // Grab a wake lock if we have unfinished business.
1819         if (!finished) {
1820             mWakelockController.acquireWakelock(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
1821         }
1822 
1823         // Notify the power manager when ready.
1824         if (ready && mustNotify) {
1825             // Send state change.
1826             synchronized (mLock) {
1827                 if (!mPendingRequestChangedLocked) {
1828                     mDisplayReadyLocked = true;
1829 
1830                     if (DEBUG) {
1831                         Slog.d(mTag, "Display ready!");
1832                     }
1833                 }
1834             }
1835             sendOnStateChangedWithWakelock();
1836         }
1837 
1838         // Release the wake lock when we have no unfinished business.
1839         if (finished) {
1840             mWakelockController.releaseWakelock(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
1841         }
1842 
1843         // Record if dozing for future comparison.
1844         mDozing = state != Display.STATE_ON;
1845 
1846         if (previousPolicy != mPowerRequest.policy) {
1847             logDisplayPolicyChanged(mPowerRequest.policy);
1848         }
1849     }
1850 
setDwbcOverride(float cct)1851     private void setDwbcOverride(float cct) {
1852         if (mDisplayWhiteBalanceController != null) {
1853             mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
1854             // The ambient color temperature override is only applied when the ambient color
1855             // temperature changes or is updated, so it doesn't necessarily change the screen color
1856             // temperature immediately. So, let's make it!
1857             // We can call this directly, since we're already on the handler thread.
1858             updatePowerState();
1859         }
1860     }
1861 
setDwbcStrongMode(int arg)1862     private void setDwbcStrongMode(int arg) {
1863         if (mDisplayWhiteBalanceController != null) {
1864             final boolean isIdle = (arg == AUTO_BRIGHTNESS_MODE_IDLE);
1865             mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
1866         }
1867     }
1868 
setDwbcLoggingEnabled(int arg)1869     private void setDwbcLoggingEnabled(int arg) {
1870         if (mDisplayWhiteBalanceController != null) {
1871             final boolean enabled = (arg == 1);
1872             mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
1873             mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
1874         }
1875     }
1876 
1877     @Override
updateBrightness()1878     public void updateBrightness() {
1879         sendUpdatePowerState();
1880     }
1881 
1882     /**
1883      * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
1884      * currently enabled and forcing the screen to be dark.
1885      */
1886     @Override
ignoreProximitySensorUntilChanged()1887     public void ignoreProximitySensorUntilChanged() {
1888         mDisplayPowerProximityStateController.ignoreProximitySensorUntilChanged();
1889     }
1890 
1891     @Override
setBrightnessConfiguration(BrightnessConfiguration c, boolean shouldResetShortTermModel)1892     public void setBrightnessConfiguration(BrightnessConfiguration c,
1893             boolean shouldResetShortTermModel) {
1894         Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS,
1895                 shouldResetShortTermModel ? 1 : 0, /* unused */ 0, c);
1896         msg.sendToTarget();
1897     }
1898 
1899     @Override
setTemporaryBrightness(float brightness)1900     public void setTemporaryBrightness(float brightness) {
1901         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
1902                 Float.floatToIntBits(brightness), 0 /*unused*/);
1903         msg.sendToTarget();
1904     }
1905 
1906     @Override
setTemporaryAutoBrightnessAdjustment(float adjustment)1907     public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
1908         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
1909                 Float.floatToIntBits(adjustment), 0 /*unused*/);
1910         msg.sendToTarget();
1911     }
1912 
1913     @Override
setBrightnessFromOffload(float brightness)1914     public void setBrightnessFromOffload(float brightness) {
1915         Message msg = mHandler.obtainMessage(MSG_SET_BRIGHTNESS_FROM_OFFLOAD,
1916                 Float.floatToIntBits(brightness), 0 /*unused*/);
1917         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
1918     }
1919 
1920     @Override
getAutoBrightnessLevels( @utomaticBrightnessController.AutomaticBrightnessMode int mode)1921     public float[] getAutoBrightnessLevels(
1922             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
1923         int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
1924                 Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
1925                 Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL, UserHandle.USER_CURRENT);
1926         return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(mode, preset);
1927     }
1928 
1929     @Override
getAutoBrightnessLuxLevels( @utomaticBrightnessController.AutomaticBrightnessMode int mode)1930     public float[] getAutoBrightnessLuxLevels(
1931             @AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
1932         int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
1933                 Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
1934                 Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL, UserHandle.USER_CURRENT);
1935         return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(mode, preset);
1936     }
1937 
1938     @Override
getBrightnessInfo()1939     public BrightnessInfo getBrightnessInfo() {
1940         synchronized (mCachedBrightnessInfo) {
1941             return new BrightnessInfo(
1942                     mCachedBrightnessInfo.brightness.value,
1943                     mCachedBrightnessInfo.adjustedBrightness.value,
1944                     mCachedBrightnessInfo.brightnessMin.value,
1945                     mCachedBrightnessInfo.brightnessMax.value,
1946                     mCachedBrightnessInfo.hbmMode.value,
1947                     mCachedBrightnessInfo.hbmTransitionPoint.value,
1948                     mCachedBrightnessInfo.brightnessMaxReason.value);
1949         }
1950     }
1951 
1952     @Override
onBootCompleted()1953     public void onBootCompleted() {
1954         Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
1955         mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
1956     }
1957 
saveBrightnessInfo(float brightness)1958     private boolean saveBrightnessInfo(float brightness) {
1959         return saveBrightnessInfo(brightness, /* state= */ null);
1960     }
1961 
saveBrightnessInfo(float brightness, @Nullable DisplayBrightnessState state)1962     private boolean saveBrightnessInfo(float brightness, @Nullable DisplayBrightnessState state) {
1963         return saveBrightnessInfo(brightness, brightness, state);
1964     }
1965 
saveBrightnessInfo(float brightness, float adjustedBrightness, @Nullable DisplayBrightnessState state)1966     private boolean saveBrightnessInfo(float brightness, float adjustedBrightness,
1967             @Nullable DisplayBrightnessState state) {
1968         synchronized (mCachedBrightnessInfo) {
1969             float stateMax = state != null ? state.getMaxBrightness() : PowerManager.BRIGHTNESS_MAX;
1970             float stateMin = state != null ? state.getMinBrightness() : PowerManager.BRIGHTNESS_MAX;
1971             final float minBrightness = Math.max(stateMin, Math.min(
1972                     mBrightnessRangeController.getCurrentBrightnessMin(), stateMax));
1973             final float maxBrightness = Math.min(
1974                     mBrightnessRangeController.getCurrentBrightnessMax(), stateMax);
1975             boolean changed = false;
1976 
1977             changed |=
1978                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
1979                             brightness);
1980             changed |=
1981                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
1982                             adjustedBrightness);
1983             changed |=
1984                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
1985                             minBrightness);
1986             changed |=
1987                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
1988                             maxBrightness);
1989             changed |=
1990                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
1991                             mBrightnessRangeController.getHighBrightnessMode());
1992             changed |=
1993                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
1994                             mBrightnessRangeController.getTransitionPoint());
1995             changed |=
1996                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
1997                             mBrightnessClamperController.getBrightnessMaxReason());
1998             return changed;
1999         }
2000     }
2001 
postBrightnessChangeRunnable()2002     void postBrightnessChangeRunnable() {
2003         if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
2004             mHandler.post(mOnBrightnessChangeRunnable);
2005         }
2006     }
2007 
createHbmControllerLocked( HighBrightnessModeMetadata hbmMetadata, Runnable modeChangeCallback)2008     private HighBrightnessModeController createHbmControllerLocked(
2009             HighBrightnessModeMetadata hbmMetadata, Runnable modeChangeCallback) {
2010         final DisplayDeviceConfig ddConfig = mDisplayDevice.getDisplayDeviceConfig();
2011         final IBinder displayToken = mDisplayDevice.getDisplayTokenLocked();
2012         final String displayUniqueId = mDisplayDevice.getUniqueId();
2013         final DisplayDeviceConfig.HighBrightnessModeData hbmData =
2014                 ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
2015         final DisplayDeviceInfo info = mDisplayDevice.getDisplayDeviceInfoLocked();
2016         return mInjector.getHighBrightnessModeController(mHandler, info.width, info.height,
2017                 displayToken, displayUniqueId, PowerManager.BRIGHTNESS_MIN,
2018                 PowerManager.BRIGHTNESS_MAX, hbmData, (sdrBrightness, maxDesiredHdrSdrRatio) ->
2019                         mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness,
2020                                 maxDesiredHdrSdrRatio), modeChangeCallback, hbmMetadata, mContext);
2021     }
2022 
createBrightnessThrottlerLocked()2023     private BrightnessThrottler createBrightnessThrottlerLocked() {
2024         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
2025         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
2026         return new BrightnessThrottler(mHandler,
2027                 () -> {
2028                     sendUpdatePowerState();
2029                     postBrightnessChangeRunnable();
2030                 }, mUniqueDisplayId,
2031                 mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId,
2032                 ddConfig);
2033     }
2034 
blockScreenOn()2035     private void blockScreenOn() {
2036         if (mPendingScreenOnUnblocker == null) {
2037             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
2038             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
2039             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
2040             Slog.i(mTag, "Blocking screen on until initial contents have been drawn.");
2041         }
2042     }
2043 
unblockScreenOn()2044     private void unblockScreenOn() {
2045         if (mPendingScreenOnUnblocker != null) {
2046             mPendingScreenOnUnblocker = null;
2047             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
2048             Slog.i(mTag, "Unblocked screen on after " + delay + " ms");
2049             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
2050         }
2051     }
2052 
blockScreenOff()2053     private void blockScreenOff() {
2054         if (mPendingScreenOffUnblocker == null) {
2055             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
2056             mPendingScreenOffUnblocker = new ScreenOffUnblocker();
2057             mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
2058             Slog.i(mTag, "Blocking screen off");
2059         }
2060     }
2061 
unblockScreenOff()2062     private void unblockScreenOff() {
2063         if (mPendingScreenOffUnblocker != null) {
2064             mPendingScreenOffUnblocker = null;
2065             long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
2066             Slog.i(mTag, "Unblocked screen off after " + delay + " ms");
2067             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
2068         }
2069     }
2070 
blockScreenOnByDisplayOffload(DisplayOffloadSession displayOffloadSession)2071     private void blockScreenOnByDisplayOffload(DisplayOffloadSession displayOffloadSession) {
2072         if (mPendingScreenOnUnblockerByDisplayOffload != null || displayOffloadSession == null) {
2073             return;
2074         }
2075         mScreenTurningOnWasBlockedByDisplayOffload = true;
2076 
2077         Trace.asyncTraceBegin(
2078                 Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
2079         mScreenOnBlockByDisplayOffloadStartRealTime = SystemClock.elapsedRealtime();
2080 
2081         mPendingScreenOnUnblockerByDisplayOffload =
2082                 () -> onDisplayOffloadUnblockScreenOn(displayOffloadSession);
2083         if (!displayOffloadSession.blockScreenOn(mPendingScreenOnUnblockerByDisplayOffload)) {
2084             mPendingScreenOnUnblockerByDisplayOffload = null;
2085             long delay =
2086                     SystemClock.elapsedRealtime() - mScreenOnBlockByDisplayOffloadStartRealTime;
2087             Slog.w(mTag, "Tried blocking screen on for offloading but failed. So, end trace after "
2088                     + delay + " ms.");
2089             Trace.asyncTraceEnd(
2090                     Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
2091             return;
2092         }
2093         Slog.i(mTag, "Blocking screen on for offloading.");
2094     }
2095 
onDisplayOffloadUnblockScreenOn(DisplayOffloadSession displayOffloadSession)2096     private void onDisplayOffloadUnblockScreenOn(DisplayOffloadSession displayOffloadSession) {
2097         Message msg = mHandler.obtainMessage(MSG_OFFLOADING_SCREEN_ON_UNBLOCKED,
2098                 displayOffloadSession);
2099         mHandler.sendMessage(msg);
2100     }
2101 
unblockScreenOnByDisplayOffload()2102     private void unblockScreenOnByDisplayOffload() {
2103         if (mPendingScreenOnUnblockerByDisplayOffload == null) {
2104             return;
2105         }
2106         mPendingScreenOnUnblockerByDisplayOffload = null;
2107         long delay = SystemClock.elapsedRealtime() - mScreenOnBlockByDisplayOffloadStartRealTime;
2108         Slog.i(mTag, "Unblocked screen on for offloading after " + delay + " ms");
2109         Trace.asyncTraceEnd(
2110                 Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
2111     }
2112 
setScreenState(int state, @Display.StateReason int reason)2113     private boolean setScreenState(int state, @Display.StateReason int reason) {
2114         return setScreenState(state, reason, false /*reportOnly*/);
2115     }
2116 
setScreenState(int state, @Display.StateReason int reason, boolean reportOnly)2117     private boolean setScreenState(int state, @Display.StateReason int reason, boolean reportOnly) {
2118         final boolean isOff = (state == Display.STATE_OFF);
2119         final boolean isOn = (state == Display.STATE_ON);
2120         final boolean changed = mPowerState.getScreenState() != state;
2121 
2122         // If the screen is turning on, give displayoffload a chance to do something before the
2123         // screen actually turns on.
2124         // TODO(b/316941732): add tests for this displayoffload screen-on blocker.
2125         if (isOn && changed && !mScreenTurningOnWasBlockedByDisplayOffload) {
2126             blockScreenOnByDisplayOffload(mDisplayOffloadSession);
2127         } else if (!isOn && mScreenTurningOnWasBlockedByDisplayOffload) {
2128             // No longer turning screen on, so unblock previous screen on blocking immediately.
2129             unblockScreenOnByDisplayOffload();
2130             mScreenTurningOnWasBlockedByDisplayOffload = false;
2131         }
2132 
2133         if (changed || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
2134             // If we are trying to turn screen off, give policy a chance to do something before we
2135             // actually turn the screen off.
2136             if (isOff && !mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
2137                 if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON
2138                         || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
2139                     setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
2140                     blockScreenOff();
2141                     mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
2142                     unblockScreenOff();
2143                 } else if (mPendingScreenOffUnblocker != null) {
2144                     // Abort doing the state change until screen off is unblocked.
2145                     return false;
2146                 }
2147             }
2148 
2149             if (!reportOnly && changed && readyToUpdateDisplayState()
2150                     && mPendingScreenOffUnblocker == null
2151                     && mPendingScreenOnUnblockerByDisplayOffload == null) {
2152                 Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
2153 
2154                 String propertyKey = "debug.tracing.screen_state";
2155                 String propertyValue = String.valueOf(state);
2156                 try {
2157                     // TODO(b/153319140) remove when we can get this from the above trace invocation
2158                     SystemProperties.set(propertyKey, propertyValue);
2159                 } catch (RuntimeException e) {
2160                     Slog.e(mTag, "Failed to set a system property: key=" + propertyKey
2161                             + " value=" + propertyValue + " " + e.getMessage());
2162                 }
2163 
2164                 mPowerState.setScreenState(state, reason);
2165                 // Tell battery stats about the transition.
2166                 noteScreenState(state, reason);
2167             }
2168         }
2169 
2170         // Tell the window manager policy when the screen is turned off or on unless it's due
2171         // to the proximity sensor.  We temporarily block turning the screen on until the
2172         // window manager is ready by leaving a black surface covering the screen.
2173         // This surface is essentially the final state of the color fade animation and
2174         // it is only removed once the window manager tells us that the activity has
2175         // finished drawing underneath.
2176         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
2177                 && !mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
2178             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
2179             unblockScreenOn();
2180             mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition);
2181         } else if (!isOff
2182                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
2183 
2184             // We told policy already that screen was turning off, but now we changed our minds.
2185             // Complete the full state transition on -> turningOff -> off.
2186             unblockScreenOff();
2187             mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition);
2188             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
2189         }
2190         if (!isOff
2191                 && (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
2192                 || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
2193             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
2194             if (mPowerState.getColorFadeLevel() == 0.0f) {
2195                 blockScreenOn();
2196             } else {
2197                 unblockScreenOn();
2198             }
2199             mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
2200         }
2201 
2202         // Return true if the screen isn't blocked.
2203         return mPendingScreenOnUnblocker == null
2204                 && mPendingScreenOnUnblockerByDisplayOffload == null;
2205     }
2206 
setReportedScreenState(int state)2207     private void setReportedScreenState(int state) {
2208         Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
2209         mReportedScreenStateToPolicy = state;
2210         if (state == REPORTED_TO_POLICY_SCREEN_ON) {
2211             mScreenTurningOnWasBlockedByDisplayOffload = false;
2212         }
2213     }
2214 
loadAmbientLightSensor()2215     private void loadAmbientLightSensor() {
2216         final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
2217                 ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK;
2218         mLightSensor = SensorUtils.findSensor(mSensorManager,
2219                 mDisplayDeviceConfig.getAmbientLightSensor(), fallbackType);
2220     }
2221 
loadScreenOffBrightnessSensor()2222     private void loadScreenOffBrightnessSensor() {
2223         mScreenOffBrightnessSensor = SensorUtils.findSensor(mSensorManager,
2224                 mDisplayDeviceConfig.getScreenOffBrightnessSensor(), SensorUtils.NO_FALLBACK);
2225     }
2226 
clampScreenBrightness(float value)2227     private float clampScreenBrightness(float value) {
2228         if (Float.isNaN(value)) {
2229             value = PowerManager.BRIGHTNESS_MIN;
2230         }
2231         return MathUtils.constrain(value, mBrightnessRangeController.getCurrentBrightnessMin(),
2232                 mBrightnessRangeController.getCurrentBrightnessMax());
2233     }
2234 
animateScreenBrightness(float target, float sdrTarget, float rate)2235     private void animateScreenBrightness(float target, float sdrTarget, float rate) {
2236         animateScreenBrightness(target, sdrTarget, rate, /* ignoreAnimationLimits = */false);
2237     }
2238 
animateScreenBrightness(float target, float sdrTarget, float rate, boolean ignoreAnimationLimits)2239     private void animateScreenBrightness(float target, float sdrTarget, float rate,
2240             boolean ignoreAnimationLimits) {
2241         if (DEBUG) {
2242             Slog.d(mTag, "Animating brightness: target=" + target + ", sdrTarget=" + sdrTarget
2243                     + ", rate=" + rate);
2244         }
2245         if (mScreenBrightnessRampAnimator.animateTo(target, sdrTarget, rate,
2246                 ignoreAnimationLimits)) {
2247             Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
2248 
2249             String propertyKey = "debug.tracing.screen_brightness";
2250             String propertyValue = String.valueOf(target);
2251             try {
2252                 // TODO(b/153319140) remove when we can get this from the above trace invocation
2253                 SystemProperties.set(propertyKey, propertyValue);
2254             } catch (RuntimeException e) {
2255                 Slog.e(mTag, "Failed to set a system property: key=" + propertyKey
2256                         + " value=" + propertyValue + " " + e.getMessage());
2257             }
2258 
2259             noteScreenBrightness(target);
2260         }
2261     }
2262 
animateScreenStateChange( int target, @Display.StateReason int reason, boolean performScreenOffTransition)2263     private void animateScreenStateChange(
2264             int target, @Display.StateReason int reason, boolean performScreenOffTransition) {
2265         // If there is already an animation in progress, don't interfere with it.
2266         if (mColorFadeEnabled
2267                 && (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
2268             if (target != Display.STATE_ON) {
2269                 return;
2270             }
2271             // If display state changed to on, proceed and stop the color fade and turn screen on.
2272             mPendingScreenOff = false;
2273         }
2274 
2275         if (mDisplayBlanksAfterDozeConfig
2276                 && Display.isDozeState(mPowerState.getScreenState())
2277                 && !Display.isDozeState(target)) {
2278             // Skip the screen off animation and add a black surface to hide the
2279             // contents of the screen.
2280             mPowerState.prepareColorFade(mContext,
2281                     mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
2282             if (mColorFadeOffAnimator != null) {
2283                 mColorFadeOffAnimator.end();
2284             }
2285             // Some display hardware will blank itself on the transition between doze and non-doze
2286             // but still on display states. In this case we want to report to policy that the
2287             // display has turned off so it can prepare the appropriate power on animation, but we
2288             // don't want to actually transition to the fully off state since that takes
2289             // significantly longer to transition from.
2290             setScreenState(Display.STATE_OFF, reason, target != Display.STATE_OFF /*reportOnly*/);
2291         }
2292 
2293         // If we were in the process of turning off the screen but didn't quite
2294         // finish.  Then finish up now to prevent a jarring transition back
2295         // to screen on if we skipped blocking screen on as usual.
2296         if (mPendingScreenOff && target != Display.STATE_OFF) {
2297             setScreenState(Display.STATE_OFF, reason);
2298             mPendingScreenOff = false;
2299             mPowerState.dismissColorFadeResources();
2300         }
2301 
2302         if (target == Display.STATE_ON) {
2303             // Want screen on.  The contents of the screen may not yet
2304             // be visible if the color fade has not been dismissed because
2305             // its last frame of animation is solid black.
2306             if (!setScreenState(Display.STATE_ON, reason)) {
2307                 return; // screen on blocked
2308             }
2309             if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
2310                 // Perform screen on animation.
2311                 if (mPowerState.getColorFadeLevel() == 1.0f) {
2312                     mPowerState.dismissColorFade();
2313                 } else if (mPowerState.prepareColorFade(mContext,
2314                         mColorFadeFadesConfig
2315                                 ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP)) {
2316                     mColorFadeOnAnimator.start();
2317                 } else {
2318                     mColorFadeOnAnimator.end();
2319                 }
2320             } else {
2321                 // Skip screen on animation.
2322                 mPowerState.setColorFadeLevel(1.0f);
2323                 mPowerState.dismissColorFade();
2324             }
2325         } else if (target == Display.STATE_DOZE) {
2326             // Want screen dozing.
2327             // Wait for brightness animation to complete beforehand when entering doze
2328             // from screen on to prevent a perceptible jump because brightness may operate
2329             // differently when the display is configured for dozing.
2330             if (mScreenBrightnessRampAnimator.isAnimating()
2331                     && mPowerState.getScreenState() == Display.STATE_ON) {
2332                 return;
2333             }
2334 
2335             // Set screen state.
2336             if (!setScreenState(Display.STATE_DOZE, reason)) {
2337                 return; // screen on blocked
2338             }
2339 
2340             // Dismiss the black surface without fanfare.
2341             mPowerState.setColorFadeLevel(1.0f);
2342             mPowerState.dismissColorFade();
2343         } else if (target == Display.STATE_DOZE_SUSPEND) {
2344             // Want screen dozing and suspended.
2345             // Wait for brightness animation to complete beforehand unless already
2346             // suspended because we may not be able to change it after suspension.
2347             if (mScreenBrightnessRampAnimator.isAnimating()
2348                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
2349                 return;
2350             }
2351 
2352             // If not already suspending, temporarily set the state to doze until the
2353             // screen on is unblocked, then suspend.
2354             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
2355                 if (!setScreenState(Display.STATE_DOZE, reason)) {
2356                     return; // screen on blocked
2357                 }
2358                 setScreenState(Display.STATE_DOZE_SUSPEND, reason); // already on so can't block
2359             }
2360 
2361             // Dismiss the black surface without fanfare.
2362             mPowerState.setColorFadeLevel(1.0f);
2363             mPowerState.dismissColorFade();
2364         } else if (target == Display.STATE_ON_SUSPEND) {
2365             // Want screen full-power and suspended.
2366             // Wait for brightness animation to complete beforehand unless already
2367             // suspended because we may not be able to change it after suspension.
2368             if (mScreenBrightnessRampAnimator.isAnimating()
2369                     && mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
2370                 return;
2371             }
2372 
2373             // If not already suspending, temporarily set the state to on until the
2374             // screen on is unblocked, then suspend.
2375             if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
2376                 if (!setScreenState(Display.STATE_ON, reason)) {
2377                     return;
2378                 }
2379                 setScreenState(Display.STATE_ON_SUSPEND, reason);
2380             }
2381 
2382             // Dismiss the black surface without fanfare.
2383             mPowerState.setColorFadeLevel(1.0f);
2384             mPowerState.dismissColorFade();
2385         } else {
2386             // Want screen off.
2387             mPendingScreenOff = true;
2388             if (!mColorFadeEnabled) {
2389                 mPowerState.setColorFadeLevel(0.0f);
2390             }
2391 
2392             if (mPowerState.getColorFadeLevel() == 0.0f) {
2393                 // Turn the screen off.
2394                 // A black surface is already hiding the contents of the screen.
2395                 setScreenState(Display.STATE_OFF, reason);
2396                 mPendingScreenOff = false;
2397                 mPowerState.dismissColorFadeResources();
2398             } else if (performScreenOffTransition
2399                     && mPowerState.prepareColorFade(mContext,
2400                     mColorFadeFadesConfig
2401                             ? ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
2402                     && mPowerState.getScreenState() != Display.STATE_OFF) {
2403                 // Perform the screen off animation.
2404                 mColorFadeOffAnimator.start();
2405             } else {
2406                 // Skip the screen off animation and add a black surface to hide the
2407                 // contents of the screen.
2408                 mColorFadeOffAnimator.end();
2409             }
2410         }
2411     }
2412 
2413     private final Runnable mCleanListener = this::sendUpdatePowerState;
2414 
sendOnStateChangedWithWakelock()2415     private void sendOnStateChangedWithWakelock() {
2416         boolean wakeLockAcquired = mWakelockController.acquireWakelock(
2417                 WakelockController.WAKE_LOCK_STATE_CHANGED);
2418         if (wakeLockAcquired) {
2419             mHandler.post(mWakelockController.getOnStateChangedRunnable());
2420         }
2421     }
2422 
logDisplayPolicyChanged(int newPolicy)2423     private void logDisplayPolicyChanged(int newPolicy) {
2424         LogMaker log = new LogMaker(MetricsEvent.DISPLAY_POLICY);
2425         log.setType(MetricsEvent.TYPE_UPDATE);
2426         log.setSubtype(newPolicy);
2427         MetricsLogger.action(log);
2428     }
2429 
handleSettingsChange()2430     private void handleSettingsChange() {
2431         mDisplayBrightnessController
2432                 .setPendingScreenBrightness(mDisplayBrightnessController
2433                         .getScreenBrightnessSetting());
2434         mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
2435         sendUpdatePowerState();
2436     }
2437 
handleBrightnessModeChange()2438     private void handleBrightnessModeChange() {
2439         final int screenBrightnessModeSetting = Settings.System.getIntForUser(
2440                 mContext.getContentResolver(),
2441                 Settings.System.SCREEN_BRIGHTNESS_MODE,
2442                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
2443         mAutomaticBrightnessStrategy.setUseAutoBrightness(screenBrightnessModeSetting
2444                 == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
2445     }
2446 
2447 
2448     @Override
getScreenBrightnessSetting()2449     public float getScreenBrightnessSetting() {
2450         return mDisplayBrightnessController.getScreenBrightnessSetting();
2451     }
2452 
2453     @Override
getDozeBrightnessForOffload()2454     public float getDozeBrightnessForOffload() {
2455         return mDisplayBrightnessController.getCurrentBrightness() * mDozeScaleFactor;
2456     }
2457 
2458     @Override
setBrightness(float brightness)2459     public void setBrightness(float brightness) {
2460         // After HBMController and NBMController migration to Clampers framework
2461         // currentBrightnessMax should be taken from clampers controller
2462         // TODO(b/263362199)
2463         mDisplayBrightnessController.setBrightness(clampScreenBrightness(brightness),
2464                 mBrightnessRangeController.getCurrentBrightnessMax());
2465     }
2466 
2467     @Override
setBrightness(float brightness, int userSerial)2468     public void setBrightness(float brightness, int userSerial) {
2469         // After HBMController and NBMController migration to Clampers framework
2470         // currentBrightnessMax should be taken from clampers controller
2471         // TODO(b/263362199)
2472         mDisplayBrightnessController.setBrightness(clampScreenBrightness(brightness), userSerial,
2473                 mBrightnessRangeController.getCurrentBrightnessMax());
2474     }
2475 
2476     @Override
getDisplayId()2477     public int getDisplayId() {
2478         return mDisplayId;
2479     }
2480 
2481     @Override
getLeadDisplayId()2482     public int getLeadDisplayId() {
2483         return mLeadDisplayId;
2484     }
2485 
2486     @Override
setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux, boolean slowChange)2487     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
2488             boolean slowChange) {
2489         mBrightnessRangeController.onAmbientLuxChange(ambientLux);
2490         if (nits == BrightnessMappingStrategy.INVALID_NITS) {
2491             mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness, slowChange);
2492         } else {
2493             float brightness = mDisplayBrightnessController.getBrightnessFromNits(nits);
2494             if (BrightnessUtils.isValidBrightnessValue(brightness)) {
2495                 mDisplayBrightnessController.setBrightnessToFollow(brightness, slowChange);
2496             } else {
2497                 // The device does not support nits
2498                 mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness,
2499                         slowChange);
2500             }
2501         }
2502         sendUpdatePowerState();
2503     }
2504 
notifyBrightnessTrackerChanged(float brightness, boolean userInitiated, boolean wasShortTermModelActive, boolean autobrightnessEnabled, boolean brightnessIsTemporary, boolean shouldUseAutoBrightness)2505     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
2506             boolean wasShortTermModelActive, boolean autobrightnessEnabled,
2507             boolean brightnessIsTemporary, boolean shouldUseAutoBrightness) {
2508 
2509         final float brightnessInNits =
2510                 mDisplayBrightnessController.convertToAdjustedNits(brightness);
2511         // Don't report brightness to brightnessTracker:
2512         // If brightness is temporary (ie the slider has not been released)
2513         // or if we are in idle screen brightness mode.
2514         // or display is not on
2515         // or we shouldn't be using autobrightness
2516         // or the nits is invalid.
2517         if (brightnessIsTemporary
2518                 || mAutomaticBrightnessController == null
2519                 || mAutomaticBrightnessController.isInIdleMode()
2520                 || !autobrightnessEnabled
2521                 || mBrightnessTracker == null
2522                 || !shouldUseAutoBrightness
2523                 || brightnessInNits < 0.0f) {
2524             return;
2525         }
2526 
2527         if (userInitiated && (mAutomaticBrightnessController == null
2528                 || !mAutomaticBrightnessController.hasValidAmbientLux())) {
2529             // If we don't have a valid lux reading we can't report a valid
2530             // slider event so notify as if the system changed the brightness.
2531             userInitiated = false;
2532         }
2533 
2534         // We only want to track changes on devices that can actually map the display backlight
2535         // values into a physical brightness unit since the value provided by the API is in
2536         // nits and not using the arbitrary backlight units.
2537         final float powerFactor = mPowerRequest.lowPowerMode
2538                 ? mPowerRequest.screenLowPowerBrightnessFactor
2539                 : 1.0f;
2540         mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
2541                 powerFactor, wasShortTermModelActive,
2542                 mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
2543                 mAutomaticBrightnessController.getLastSensorValues(),
2544                 mAutomaticBrightnessController.getLastSensorTimestamps());
2545     }
2546 
2547     @Override
addDisplayBrightnessFollower(DisplayPowerControllerInterface follower)2548     public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
2549         synchronized (mLock) {
2550             mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
2551             sendUpdatePowerStateLocked();
2552         }
2553     }
2554 
2555     @Override
removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower)2556     public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
2557         synchronized (mLock) {
2558             mDisplayBrightnessFollowers.remove(follower.getDisplayId());
2559             mHandler.postAtTime(() -> follower.setBrightnessToFollow(
2560                     PowerManager.BRIGHTNESS_INVALID_FLOAT, BrightnessMappingStrategy.INVALID_NITS,
2561                     /* ambientLux= */ 0, /* slowChange= */ false), mClock.uptimeMillis());
2562         }
2563     }
2564 
2565     @GuardedBy("mLock")
clearDisplayBrightnessFollowersLocked()2566     private void clearDisplayBrightnessFollowersLocked() {
2567         for (int i = 0; i < mDisplayBrightnessFollowers.size(); i++) {
2568             DisplayPowerControllerInterface follower = mDisplayBrightnessFollowers.valueAt(i);
2569             mHandler.postAtTime(() -> follower.setBrightnessToFollow(
2570                     PowerManager.BRIGHTNESS_INVALID_FLOAT, BrightnessMappingStrategy.INVALID_NITS,
2571                     /* ambientLux= */ 0, /* slowChange= */ false), mClock.uptimeMillis());
2572         }
2573         mDisplayBrightnessFollowers.clear();
2574     }
2575 
2576     @Override
dump(final PrintWriter pw)2577     public void dump(final PrintWriter pw) {
2578         synchronized (mLock) {
2579             pw.println();
2580             pw.println("Display Power Controller:");
2581             pw.println("  mDisplayId=" + mDisplayId);
2582             pw.println("  mLeadDisplayId=" + mLeadDisplayId);
2583             pw.println("  mLightSensor=" + mLightSensor);
2584             pw.println("  mDisplayBrightnessFollowers=" + mDisplayBrightnessFollowers);
2585 
2586             pw.println();
2587             pw.println("Display Power Controller Locked State:");
2588             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
2589             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
2590             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
2591             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
2592         }
2593 
2594         pw.println();
2595         pw.println("Display Power Controller Configuration:");
2596         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
2597         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
2598         pw.println("  mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
2599         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
2600         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
2601         pw.println("  mIsDisplayInternal=" + mIsDisplayInternal);
2602         synchronized (mCachedBrightnessInfo) {
2603             pw.println("  mCachedBrightnessInfo.brightness="
2604                     + mCachedBrightnessInfo.brightness.value);
2605             pw.println("  mCachedBrightnessInfo.adjustedBrightness="
2606                     + mCachedBrightnessInfo.adjustedBrightness.value);
2607             pw.println("  mCachedBrightnessInfo.brightnessMin="
2608                     + mCachedBrightnessInfo.brightnessMin.value);
2609             pw.println("  mCachedBrightnessInfo.brightnessMax="
2610                     + mCachedBrightnessInfo.brightnessMax.value);
2611             pw.println("  mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
2612             pw.println("  mCachedBrightnessInfo.hbmTransitionPoint="
2613                     + mCachedBrightnessInfo.hbmTransitionPoint.value);
2614             pw.println("  mCachedBrightnessInfo.brightnessMaxReason ="
2615                     + mCachedBrightnessInfo.brightnessMaxReason.value);
2616         }
2617         pw.println("  mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
2618         pw.println("  mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
2619         pw.println("  mDozeScaleFactor=" + mDozeScaleFactor);
2620         mHandler.runWithScissors(() -> dumpLocal(pw), 1000);
2621     }
2622 
dumpLocal(PrintWriter pw)2623     private void dumpLocal(PrintWriter pw) {
2624         pw.println();
2625         pw.println("Display Power Controller Thread State:");
2626         pw.println("  mPowerRequest=" + mPowerRequest);
2627         pw.println("  mBrightnessReason=" + mBrightnessReason);
2628         pw.println("  mAppliedDimming=" + mAppliedDimming);
2629         pw.println("  mAppliedThrottling=" + mAppliedThrottling);
2630         pw.println("  mDozing=" + mDozing);
2631         pw.println("  mSkipRampState=" + skipRampStateToString(mSkipRampState));
2632         pw.println("  mScreenOnBlockStartRealTime=" + mScreenOnBlockStartRealTime);
2633         pw.println("  mScreenOffBlockStartRealTime=" + mScreenOffBlockStartRealTime);
2634         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
2635         pw.println("  mPendingScreenOffUnblocker=" + mPendingScreenOffUnblocker);
2636         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
2637         pw.println("  mReportedToPolicy="
2638                 + reportedToPolicyToString(mReportedScreenStateToPolicy));
2639         pw.println("  mIsRbcActive=" + mIsRbcActive);
2640         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
2641         mAutomaticBrightnessStrategy.dump(ipw);
2642 
2643         if (mScreenBrightnessRampAnimator != null) {
2644             pw.println("  mScreenBrightnessRampAnimator.isAnimating()="
2645                     + mScreenBrightnessRampAnimator.isAnimating());
2646         }
2647 
2648         if (mColorFadeOnAnimator != null) {
2649             pw.println("  mColorFadeOnAnimator.isStarted()="
2650                     + mColorFadeOnAnimator.isStarted());
2651         }
2652         if (mColorFadeOffAnimator != null) {
2653             pw.println("  mColorFadeOffAnimator.isStarted()="
2654                     + mColorFadeOffAnimator.isStarted());
2655         }
2656 
2657         if (mPowerState != null) {
2658             mPowerState.dump(pw);
2659         }
2660 
2661         if (mAutomaticBrightnessController != null) {
2662             mAutomaticBrightnessController.dump(pw);
2663             dumpBrightnessEvents(pw);
2664         }
2665 
2666         dumpRbcEvents(pw);
2667 
2668         if (mScreenOffBrightnessSensorController != null) {
2669             mScreenOffBrightnessSensorController.dump(pw);
2670         }
2671 
2672         if (mBrightnessRangeController != null) {
2673             mBrightnessRangeController.dump(pw);
2674         }
2675 
2676         if (mBrightnessThrottler != null) {
2677             mBrightnessThrottler.dump(pw);
2678         }
2679 
2680         pw.println();
2681         if (mDisplayWhiteBalanceController != null) {
2682             mDisplayWhiteBalanceController.dump(pw);
2683             mDisplayWhiteBalanceSettings.dump(pw);
2684         }
2685 
2686         pw.println();
2687 
2688         if (mWakelockController != null) {
2689             mWakelockController.dumpLocal(pw);
2690         }
2691 
2692         pw.println();
2693         if (mDisplayBrightnessController != null) {
2694             mDisplayBrightnessController.dump(pw);
2695         }
2696 
2697         pw.println();
2698         if (mDisplayStateController != null) {
2699             mDisplayStateController.dumpsys(pw);
2700         }
2701 
2702         pw.println();
2703         if (mBrightnessClamperController != null) {
2704             mBrightnessClamperController.dump(ipw);
2705         }
2706     }
2707 
2708 
reportedToPolicyToString(int state)2709     private static String reportedToPolicyToString(int state) {
2710         switch (state) {
2711             case REPORTED_TO_POLICY_SCREEN_OFF:
2712                 return "REPORTED_TO_POLICY_SCREEN_OFF";
2713             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
2714                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
2715             case REPORTED_TO_POLICY_SCREEN_ON:
2716                 return "REPORTED_TO_POLICY_SCREEN_ON";
2717             default:
2718                 return Integer.toString(state);
2719         }
2720     }
2721 
skipRampStateToString(int state)2722     private static String skipRampStateToString(int state) {
2723         switch (state) {
2724             case RAMP_STATE_SKIP_NONE:
2725                 return "RAMP_STATE_SKIP_NONE";
2726             case RAMP_STATE_SKIP_INITIAL:
2727                 return "RAMP_STATE_SKIP_INITIAL";
2728             case RAMP_STATE_SKIP_AUTOBRIGHT:
2729                 return "RAMP_STATE_SKIP_AUTOBRIGHT";
2730             default:
2731                 return Integer.toString(state);
2732         }
2733     }
2734 
dumpBrightnessEvents(PrintWriter pw)2735     private void dumpBrightnessEvents(PrintWriter pw) {
2736         int size = mBrightnessEventRingBuffer.size();
2737         if (size < 1) {
2738             pw.println("No Automatic Brightness Adjustments");
2739             return;
2740         }
2741 
2742         pw.println("Automatic Brightness Adjustments Last " + size + " Events: ");
2743         BrightnessEvent[] eventArray = mBrightnessEventRingBuffer.toArray();
2744         for (int i = 0; i < mBrightnessEventRingBuffer.size(); i++) {
2745             pw.println("  " + eventArray[i].toString());
2746         }
2747     }
2748 
dumpRbcEvents(PrintWriter pw)2749     private void dumpRbcEvents(PrintWriter pw) {
2750         int size = mRbcEventRingBuffer.size();
2751         if (size < 1) {
2752             pw.println("No Reduce Bright Colors Adjustments");
2753             return;
2754         }
2755 
2756         pw.println("Reduce Bright Colors Adjustments Last " + size + " Events: ");
2757         BrightnessEvent[] eventArray = mRbcEventRingBuffer.toArray();
2758         for (int i = 0; i < mRbcEventRingBuffer.size(); i++) {
2759             pw.println("  " + eventArray[i]);
2760         }
2761     }
2762 
2763 
noteScreenState(int screenState, @Display.StateReason int reason)2764     private void noteScreenState(int screenState, @Display.StateReason int reason) {
2765         // Log screen state change with display id
2766         FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED_V2,
2767                 screenState, mDisplayStatsId, reason);
2768         if (mBatteryStats != null) {
2769             try {
2770                 // TODO(multi-display): make this multi-display
2771                 mBatteryStats.noteScreenState(screenState);
2772             } catch (RemoteException e) {
2773                 // same process
2774             }
2775         }
2776     }
2777 
2778     @SuppressLint("AndroidFrameworkRequiresPermission")
noteScreenBrightness(float brightness)2779     private void noteScreenBrightness(float brightness) {
2780         if (mBatteryStats != null) {
2781             try {
2782                 // TODO(brightnessfloat): change BatteryStats to use float
2783                 int brightnessInt = mFlags.isBrightnessIntRangeUserPerceptionEnabled()
2784                         ? BrightnessSynchronizer.brightnessFloatToIntSetting(mContext, brightness)
2785                         : BrightnessSynchronizer.brightnessFloatToInt(brightness);
2786                 mBatteryStats.noteScreenBrightness(brightnessInt);
2787             } catch (RemoteException e) {
2788                 // same process
2789             }
2790         }
2791     }
2792 
reportStats(float brightness)2793     private void reportStats(float brightness) {
2794         if (mLastStatsBrightness == brightness) {
2795             return;
2796         }
2797 
2798         float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
2799         synchronized (mCachedBrightnessInfo) {
2800             if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
2801                 return;
2802             }
2803             hbmTransitionPoint = mCachedBrightnessInfo.hbmTransitionPoint.value;
2804         }
2805 
2806         final boolean aboveTransition = brightness > hbmTransitionPoint;
2807         final boolean oldAboveTransition = mLastStatsBrightness > hbmTransitionPoint;
2808 
2809         if (aboveTransition || oldAboveTransition) {
2810             mLastStatsBrightness = brightness;
2811             mHandler.removeMessages(MSG_STATSD_HBM_BRIGHTNESS);
2812             if (aboveTransition != oldAboveTransition) {
2813                 // report immediately
2814                 logHbmBrightnessStats(brightness, mDisplayStatsId);
2815             } else {
2816                 // delay for rate limiting
2817                 Message msg = mHandler.obtainMessage();
2818                 msg.what = MSG_STATSD_HBM_BRIGHTNESS;
2819                 msg.arg1 = Float.floatToIntBits(brightness);
2820                 msg.arg2 = mDisplayStatsId;
2821                 mHandler.sendMessageAtTime(msg, mClock.uptimeMillis()
2822                         + BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
2823             }
2824         }
2825     }
2826 
logHbmBrightnessStats(float brightness, int displayStatsId)2827     private void logHbmBrightnessStats(float brightness, int displayStatsId) {
2828         synchronized (mHandler) {
2829             FrameworkStatsLog.write(
2830                     FrameworkStatsLog.DISPLAY_HBM_BRIGHTNESS_CHANGED, displayStatsId, brightness);
2831         }
2832     }
2833 
2834     // Return bucket index of range_[left]_[right] where
2835     // left <= nits < right
nitsToRangeIndex(float nits)2836     private int nitsToRangeIndex(float nits) {
2837         for (int i = 0; i < BRIGHTNESS_RANGE_BOUNDARIES.length; i++) {
2838             if (nits < BRIGHTNESS_RANGE_BOUNDARIES[i]) {
2839                 return BRIGHTNESS_RANGE_INDEX[i];
2840             }
2841         }
2842         return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3000_INF;
2843     }
2844 
convertBrightnessReasonToStatsEnum(int brightnessReason)2845     private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
2846         switch(brightnessReason) {
2847             case BrightnessReason.REASON_UNKNOWN:
2848                 return FrameworkStatsLog
2849                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
2850             case BrightnessReason.REASON_MANUAL:
2851                 return FrameworkStatsLog
2852                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_MANUAL;
2853             case BrightnessReason.REASON_DOZE:
2854                 return FrameworkStatsLog
2855                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE;
2856             case BrightnessReason.REASON_DOZE_DEFAULT:
2857                 return FrameworkStatsLog
2858                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE_DEFAULT;
2859             case BrightnessReason.REASON_AUTOMATIC:
2860                 return FrameworkStatsLog
2861                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_AUTOMATIC;
2862             case BrightnessReason.REASON_SCREEN_OFF:
2863                 return FrameworkStatsLog
2864                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF;
2865             case BrightnessReason.REASON_OVERRIDE:
2866                 return FrameworkStatsLog
2867                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_OVERRIDE;
2868             case BrightnessReason.REASON_TEMPORARY:
2869                 return FrameworkStatsLog
2870                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_TEMPORARY;
2871             case BrightnessReason.REASON_BOOST:
2872                 return FrameworkStatsLog
2873                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_BOOST;
2874             case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
2875                 return FrameworkStatsLog
2876                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
2877             case BrightnessReason.REASON_FOLLOWER:
2878                 return FrameworkStatsLog
2879                     .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_FOLLOWER;
2880         }
2881         return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
2882     }
2883 
logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness)2884     private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
2885         int modifier = event.getReason().getModifier();
2886         int flags = event.getFlags();
2887         // It's easier to check if the brightness is at maximum level using the brightness
2888         // value untouched by any modifiers
2889         boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
2890         float brightnessInNits =
2891                 mDisplayBrightnessController.convertToAdjustedNits(event.getBrightness());
2892         float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f;
2893         int appliedRbcStrength  = event.isRbcEnabled() ? event.getRbcStrength() : -1;
2894         float appliedHbmMaxNits =
2895                 event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
2896                 ? -1f : mDisplayBrightnessController.convertToAdjustedNits(event.getHbmMax());
2897         // thermalCapNits set to -1 if not currently capping max brightness
2898         float appliedThermalCapNits =
2899                 event.getThermalMax() == PowerManager.BRIGHTNESS_MAX
2900                 ? -1f : mDisplayBrightnessController.convertToAdjustedNits(event.getThermalMax());
2901         if (mIsDisplayInternal) {
2902             FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
2903                     mDisplayBrightnessController
2904                             .convertToAdjustedNits(event.getInitialBrightness()),
2905                     brightnessInNits,
2906                     event.getLux(),
2907                     event.getPhysicalDisplayId(),
2908                     event.wasShortTermModelActive(),
2909                     appliedLowPowerMode,
2910                     appliedRbcStrength,
2911                     appliedHbmMaxNits,
2912                     appliedThermalCapNits,
2913                     event.isAutomaticBrightnessEnabled(),
2914                     FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL,
2915                     convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
2916                     nitsToRangeIndex(brightnessInNits),
2917                     brightnessIsMax,
2918                     event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
2919                     event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR,
2920                     (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
2921                     mBrightnessClamperController.getBrightnessMaxReason(),
2922                     // TODO: (flc) add brightnessMinReason here too.
2923                     (modifier & BrightnessReason.MODIFIER_DIMMED) > 0,
2924                     event.isRbcEnabled(),
2925                     (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0,
2926                     (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0,
2927                     (flags & BrightnessEvent.FLAG_USER_SET) > 0,
2928                     event.getAutoBrightnessMode() == AUTO_BRIGHTNESS_MODE_IDLE,
2929                     (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0);
2930         }
2931     }
2932 
2933     /**
2934      * Indicates whether the display state is ready to update. If this is the default display, we
2935      * want to update it right away so that we can draw the boot animation on it. If it is not
2936      * the default display, drawing the boot animation on it would look incorrect, so we need
2937      * to wait until boot is completed.
2938      * @return True if the display state is ready to update
2939      */
readyToUpdateDisplayState()2940     private boolean readyToUpdateDisplayState() {
2941         return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
2942     }
2943 
2944     private final class DisplayControllerHandler extends Handler {
DisplayControllerHandler(Looper looper)2945         DisplayControllerHandler(Looper looper) {
2946             super(looper, null, true /*async*/);
2947         }
2948 
2949         @Override
handleMessage(Message msg)2950         public void handleMessage(Message msg) {
2951             switch (msg.what) {
2952                 case MSG_UPDATE_POWER_STATE:
2953                     updatePowerState();
2954                     break;
2955 
2956                 case MSG_SCREEN_ON_UNBLOCKED:
2957                     if (mPendingScreenOnUnblocker == msg.obj) {
2958                         unblockScreenOn();
2959                         updatePowerState();
2960                     }
2961                     break;
2962                 case MSG_SCREEN_OFF_UNBLOCKED:
2963                     if (mPendingScreenOffUnblocker == msg.obj) {
2964                         unblockScreenOff();
2965                         updatePowerState();
2966                     }
2967                     break;
2968                 case MSG_OFFLOADING_SCREEN_ON_UNBLOCKED:
2969                     if (mDisplayOffloadSession == msg.obj) {
2970                         unblockScreenOnByDisplayOffload();
2971                         updatePowerState();
2972                     }
2973                     break;
2974                 case MSG_CONFIGURE_BRIGHTNESS:
2975                     BrightnessConfiguration brightnessConfiguration =
2976                             (BrightnessConfiguration) msg.obj;
2977                     mAutomaticBrightnessStrategy.setBrightnessConfiguration(brightnessConfiguration,
2978                             msg.arg1 == 1);
2979                     if (mBrightnessTracker != null) {
2980                         mBrightnessTracker
2981                                 .setShouldCollectColorSample(brightnessConfiguration != null
2982                                         && brightnessConfiguration.shouldCollectColorSamples());
2983                     }
2984                     updatePowerState();
2985                     break;
2986 
2987                 case MSG_SET_TEMPORARY_BRIGHTNESS:
2988                     // TODO: Should we have a a timeout for the temporary brightness?
2989                     mDisplayBrightnessController
2990                             .setTemporaryBrightness(Float.intBitsToFloat(msg.arg1));
2991                     updatePowerState();
2992                     break;
2993 
2994                 case MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT:
2995                     mAutomaticBrightnessStrategy
2996                             .setTemporaryAutoBrightnessAdjustment(Float.intBitsToFloat(msg.arg1));
2997                     updatePowerState();
2998                     break;
2999 
3000                 case MSG_STOP:
3001                     cleanupHandlerThreadAfterStop();
3002                     break;
3003 
3004                 case MSG_UPDATE_BRIGHTNESS:
3005                     if (mStopped) {
3006                         return;
3007                     }
3008                     handleSettingsChange();
3009                     break;
3010 
3011                 case MSG_UPDATE_RBC:
3012                     handleRbcChanged();
3013                     break;
3014 
3015                 case MSG_BRIGHTNESS_RAMP_DONE:
3016                     if (mPowerState != null) {
3017                         final float brightness = mPowerState.getScreenBrightness();
3018                         reportStats(brightness);
3019                     }
3020                     break;
3021 
3022                 case MSG_STATSD_HBM_BRIGHTNESS:
3023                     logHbmBrightnessStats(Float.intBitsToFloat(msg.arg1), msg.arg2);
3024                     break;
3025 
3026                 case MSG_SWITCH_USER:
3027                     float newBrightness = msg.obj instanceof Float ? (float) msg.obj
3028                             : PowerManager.BRIGHTNESS_INVALID_FLOAT;
3029                     handleOnSwitchUser(msg.arg1, msg.arg2, newBrightness);
3030                     break;
3031 
3032                 case MSG_BOOT_COMPLETED:
3033                     mBootCompleted = true;
3034                     updatePowerState();
3035                     break;
3036 
3037                 case MSG_SWITCH_AUTOBRIGHTNESS_MODE:
3038                     boolean isIdle = msg.arg1 == AUTO_BRIGHTNESS_MODE_IDLE;
3039                     if (mAutomaticBrightnessController != null) {
3040                         mAutomaticBrightnessController.switchMode(msg.arg1, /* sendUpdate= */ true);
3041                         setAnimatorRampSpeeds(isIdle);
3042                     }
3043                     setDwbcStrongMode(msg.arg1);
3044                     break;
3045 
3046                 case MSG_SET_DWBC_COLOR_OVERRIDE:
3047                     final float cct = Float.intBitsToFloat(msg.arg1);
3048                     setDwbcOverride(cct);
3049                     break;
3050 
3051                 case MSG_SET_DWBC_LOGGING_ENABLED:
3052                     setDwbcLoggingEnabled(msg.arg1);
3053                     break;
3054                 case MSG_SET_BRIGHTNESS_FROM_OFFLOAD:
3055                     if (mDisplayBrightnessController.setBrightnessFromOffload(
3056                             Float.intBitsToFloat(msg.arg1))) {
3057                         updatePowerState();
3058                     }
3059                     break;
3060             }
3061         }
3062     }
3063 
3064 
3065     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)3066         SettingsObserver(Handler handler) {
3067             super(handler);
3068         }
3069 
3070         @Override
onChange(boolean selfChange, Uri uri)3071         public void onChange(boolean selfChange, Uri uri) {
3072             if (uri.equals(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE))) {
3073                 mHandler.postAtTime(() -> {
3074                     handleBrightnessModeChange();
3075                     updatePowerState();
3076                 }, mClock.uptimeMillis());
3077             } else if (uri.equals(Settings.System.getUriFor(
3078                     Settings.System.SCREEN_BRIGHTNESS_FOR_ALS))) {
3079                 int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
3080                         Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
3081                         Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL,
3082                         UserHandle.USER_CURRENT);
3083                 Slog.i(mTag, "Setting up auto-brightness for preset "
3084                         + autoBrightnessPresetToString(preset));
3085                 setUpAutoBrightness(mContext, mHandler);
3086                 sendUpdatePowerState();
3087             } else {
3088                 handleSettingsChange();
3089             }
3090         }
3091     }
3092 
3093     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
3094         @Override
onScreenOn()3095         public void onScreenOn() {
3096             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
3097             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
3098         }
3099     }
3100 
3101     private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener {
3102         @Override
onScreenOff()3103         public void onScreenOff() {
3104             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
3105             mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
3106         }
3107     }
3108 
3109     @Override
setAutoBrightnessLoggingEnabled(boolean enabled)3110     public void setAutoBrightnessLoggingEnabled(boolean enabled) {
3111         if (mAutomaticBrightnessController != null) {
3112             mAutomaticBrightnessController.setLoggingEnabled(enabled);
3113         }
3114     }
3115 
3116     @Override // DisplayWhiteBalanceController.Callbacks
updateWhiteBalance()3117     public void updateWhiteBalance() {
3118         sendUpdatePowerState();
3119     }
3120 
3121     @Override
setDisplayWhiteBalanceLoggingEnabled(boolean enabled)3122     public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
3123         Message msg = mHandler.obtainMessage();
3124         msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
3125         msg.arg1 = enabled ? 1 : 0;
3126         msg.sendToTarget();
3127     }
3128 
3129     @Override
setAmbientColorTemperatureOverride(float cct)3130     public void setAmbientColorTemperatureOverride(float cct) {
3131         Message msg = mHandler.obtainMessage();
3132         msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
3133         msg.arg1 = Float.floatToIntBits(cct);
3134         msg.sendToTarget();
3135     }
3136 
3137     /** Functional interface for providing time. */
3138     @VisibleForTesting
3139     interface Clock {
3140         /**
3141          * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
3142          */
uptimeMillis()3143         long uptimeMillis();
3144     }
3145 
3146     @VisibleForTesting
3147     static class Injector {
getClock()3148         Clock getClock() {
3149             return SystemClock::uptimeMillis;
3150         }
3151 
getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState)3152         DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
3153                 int displayId, int displayState) {
3154             return new DisplayPowerState(blanker, colorFade, displayId, displayState);
3155         }
3156 
getDualRampAnimator(DisplayPowerState dps, FloatProperty<DisplayPowerState> firstProperty, FloatProperty<DisplayPowerState> secondProperty)3157         DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
3158                 FloatProperty<DisplayPowerState> firstProperty,
3159                 FloatProperty<DisplayPowerState> secondProperty) {
3160             return new DualRampAnimator(dps, firstProperty, secondProperty);
3161         }
3162 
getWakelockController(int displayId, DisplayPowerCallbacks displayPowerCallbacks)3163         WakelockController getWakelockController(int displayId,
3164                 DisplayPowerCallbacks displayPowerCallbacks) {
3165             return new WakelockController(displayId, displayPowerCallbacks);
3166         }
3167 
getDisplayPowerProximityStateController( WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig, Looper looper, Runnable nudgeUpdatePowerState, int displayId, SensorManager sensorManager)3168         DisplayPowerProximityStateController getDisplayPowerProximityStateController(
3169                 WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig,
3170                 Looper looper, Runnable nudgeUpdatePowerState,
3171                 int displayId, SensorManager sensorManager) {
3172             return new DisplayPowerProximityStateController(wakelockController, displayDeviceConfig,
3173                     looper, nudgeUpdatePowerState,
3174                     displayId, sensorManager, /* injector= */ null);
3175         }
3176 
getAutomaticBrightnessController( AutomaticBrightnessController.Callbacks callbacks, Looper looper, SensorManager sensorManager, Sensor lightSensor, SparseArray<BrightnessMappingStrategy> brightnessMappingStrategyMap, int lightSensorWarmUpTime, float brightnessMin, float brightnessMax, float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, long brighteningLightDebounceConfigIdle, long darkeningLightDebounceConfigIdle, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessModeController, BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, BrightnessClamperController brightnessClamperController, DisplayManagerFlags displayManagerFlags)3177         AutomaticBrightnessController getAutomaticBrightnessController(
3178                 AutomaticBrightnessController.Callbacks callbacks, Looper looper,
3179                 SensorManager sensorManager, Sensor lightSensor,
3180                 SparseArray<BrightnessMappingStrategy> brightnessMappingStrategyMap,
3181                 int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
3182                 float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
3183                 long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
3184                 long brighteningLightDebounceConfigIdle, long darkeningLightDebounceConfigIdle,
3185                 boolean resetAmbientLuxAfterWarmUpConfig,
3186                 HysteresisLevels ambientBrightnessThresholds,
3187                 HysteresisLevels screenBrightnessThresholds,
3188                 HysteresisLevels ambientBrightnessThresholdsIdle,
3189                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
3190                 BrightnessRangeController brightnessModeController,
3191                 BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort,
3192                 int ambientLightHorizonLong, float userLux, float userNits,
3193                 BrightnessClamperController brightnessClamperController,
3194                 DisplayManagerFlags displayManagerFlags) {
3195 
3196             return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
3197                     brightnessMappingStrategyMap, lightSensorWarmUpTime, brightnessMin,
3198                     brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate,
3199                     brighteningLightDebounceConfig, darkeningLightDebounceConfig,
3200                     brighteningLightDebounceConfigIdle, darkeningLightDebounceConfigIdle,
3201                     resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
3202                     screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
3203                     screenBrightnessThresholdsIdle, context, brightnessModeController,
3204                     brightnessThrottler, ambientLightHorizonShort, ambientLightHorizonLong, userLux,
3205                     userNits, displayManagerFlags);
3206         }
3207 
getDefaultModeBrightnessMapper(Context context, DisplayDeviceConfig displayDeviceConfig, DisplayWhiteBalanceController displayWhiteBalanceController)3208         BrightnessMappingStrategy getDefaultModeBrightnessMapper(Context context,
3209                 DisplayDeviceConfig displayDeviceConfig,
3210                 DisplayWhiteBalanceController displayWhiteBalanceController) {
3211             return BrightnessMappingStrategy.create(context, displayDeviceConfig,
3212                     AUTO_BRIGHTNESS_MODE_DEFAULT, displayWhiteBalanceController);
3213         }
3214 
getScreenOffBrightnessSensorController( SensorManager sensorManager, Sensor lightSensor, Handler handler, ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux, BrightnessMappingStrategy brightnessMapper)3215         ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
3216                 SensorManager sensorManager,
3217                 Sensor lightSensor,
3218                 Handler handler,
3219                 ScreenOffBrightnessSensorController.Clock clock,
3220                 int[] sensorValueToLux,
3221                 BrightnessMappingStrategy brightnessMapper) {
3222             return new ScreenOffBrightnessSensorController(
3223                     sensorManager,
3224                     lightSensor,
3225                     handler,
3226                     clock,
3227                     sensorValueToLux,
3228                     brightnessMapper
3229             );
3230         }
3231 
getHighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax, DisplayDeviceConfig.HighBrightnessModeData hbmData, HighBrightnessModeController.HdrBrightnessDeviceConfig hdrBrightnessCfg, Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context)3232         HighBrightnessModeController getHighBrightnessModeController(Handler handler, int width,
3233                 int height, IBinder displayToken, String displayUniqueId, float brightnessMin,
3234                 float brightnessMax, DisplayDeviceConfig.HighBrightnessModeData hbmData,
3235                 HighBrightnessModeController.HdrBrightnessDeviceConfig hdrBrightnessCfg,
3236                 Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata,
3237                 Context context) {
3238             return new HighBrightnessModeController(handler, width, height, displayToken,
3239                     displayUniqueId, brightnessMin, brightnessMax, hbmData, hdrBrightnessCfg,
3240                     hbmChangeCallback, hbmMetadata, context);
3241         }
3242 
getBrightnessRangeController( HighBrightnessModeController hbmController, Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig, Handler handler, DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info)3243         BrightnessRangeController getBrightnessRangeController(
3244                 HighBrightnessModeController hbmController, Runnable modeChangeCallback,
3245                 DisplayDeviceConfig displayDeviceConfig, Handler handler,
3246                 DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info) {
3247             return new BrightnessRangeController(hbmController,
3248                     modeChangeCallback, displayDeviceConfig, handler, flags, displayToken, info);
3249         }
3250 
getBrightnessClamperController(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager)3251         BrightnessClamperController getBrightnessClamperController(Handler handler,
3252                 BrightnessClamperController.ClamperChangeListener clamperChangeListener,
3253                 BrightnessClamperController.DisplayDeviceData data, Context context,
3254                 DisplayManagerFlags flags, SensorManager sensorManager) {
3255 
3256             return new BrightnessClamperController(handler, clamperChangeListener, data, context,
3257                     flags, sensorManager);
3258         }
3259 
getDisplayWhiteBalanceController(Handler handler, SensorManager sensorManager, Resources resources)3260         DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
3261                 SensorManager sensorManager, Resources resources) {
3262             return DisplayWhiteBalanceFactory.create(handler,
3263                     sensorManager, resources);
3264         }
3265 
isColorFadeEnabled()3266         boolean isColorFadeEnabled() {
3267             return !ActivityManager.isLowRamDeviceStatic();
3268         }
3269     }
3270 
3271     static class CachedBrightnessInfo {
3272         public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3273         public MutableFloat adjustedBrightness =
3274                 new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3275         public MutableFloat brightnessMin =
3276                 new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3277         public MutableFloat brightnessMax =
3278                 new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
3279         public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
3280         public MutableFloat hbmTransitionPoint =
3281                 new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
3282         public MutableInt brightnessMaxReason =
3283                 new MutableInt(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
3284 
checkAndSetFloat(MutableFloat mf, float f)3285         public boolean checkAndSetFloat(MutableFloat mf, float f) {
3286             if (mf.value != f) {
3287                 mf.value = f;
3288                 return true;
3289             }
3290             return false;
3291         }
3292 
checkAndSetInt(MutableInt mi, int i)3293         public boolean checkAndSetInt(MutableInt mi, int i) {
3294             if (mi.value != i) {
3295                 mi.value = i;
3296                 return true;
3297             }
3298             return false;
3299         }
3300     }
3301 }
3302