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