1 /*
2  * Copyright (C) 2024 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 package com.android.server.display.brightness.strategy;
17 
18 import android.annotation.Nullable;
19 import android.content.Context;
20 import android.hardware.display.BrightnessConfiguration;
21 import android.os.PowerManager;
22 import android.os.UserHandle;
23 import android.provider.Settings;
24 import android.view.Display;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.server.display.AutomaticBrightnessController;
28 import com.android.server.display.brightness.BrightnessEvent;
29 import com.android.server.display.brightness.BrightnessReason;
30 import com.android.server.display.brightness.BrightnessUtils;
31 import com.android.server.display.feature.DisplayManagerFlags;
32 
33 import java.io.PrintWriter;
34 
35 /**
36  * Helps manage the brightness based on the ambient environment (Ambient Light/lux sensor) using
37  * mappings from lux to nits to brightness, configured in the
38  * {@link com.android.server.display.DisplayDeviceConfig} class. This class inherently assumes
39  * that it is being executed from the power thread, and hence doesn't synchronize
40  * any of its resources
41  *
42  * @deprecated This class is relevant only while the
43  * {@link DisplayManagerFlags#isRefactorDisplayPowerControllerEnabled()} is not fully rolled out.
44  * Till then, please replicated your changes to {@link AutomaticBrightnessStrategy} as well.
45  */
46 @Deprecated
47 public class AutomaticBrightnessStrategy2 {
48     private final Context mContext;
49     // The DisplayId of the associated logical display
50     private final int mDisplayId;
51     // The last auto brightness adjustment that was set by the user and is not temporary. Set to
52     // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
53     private float mAutoBrightnessAdjustment;
54     // The pending auto brightness adjustment that will take effect on the next power state update.
55     private float mPendingAutoBrightnessAdjustment;
56     // The temporary auto brightness adjustment. This was historically used when a user interacts
57     // with the adjustment slider but hasn't settled on a choice yet.
58     // Set to PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
59     private float mTemporaryAutoBrightnessAdjustment;
60     // Indicates if the temporary auto brightness adjustment has been applied while updating the
61     // associated display brightness
62     private boolean mAppliedTemporaryAutoBrightnessAdjustment;
63     // Indicates if the auto brightness adjustment has happened.
64     private boolean mAutoBrightnessAdjustmentChanged;
65     // Indicates the reasons for the auto-brightness adjustment
66     private int mAutoBrightnessAdjustmentReasonsFlags = 0;
67     // Indicates if the short term model should be reset before fetching the new brightness
68     // Todo(273543270): Short term model is an internal information of
69     //  AutomaticBrightnessController and shouldn't be exposed outside of that class
70     private boolean mShouldResetShortTermModel = false;
71     // Remembers whether the auto-brightness has been applied in the latest brightness update.
72     private boolean mAppliedAutoBrightness = false;
73     // The controller for the automatic brightness level.
74     @Nullable
75     private AutomaticBrightnessController mAutomaticBrightnessController;
76     // The system setting denoting if the auto-brightness for the current user is enabled or not
77     private boolean mUseAutoBrightness = false;
78     // Indicates if the auto-brightness is currently enabled or not. It's possible that even if
79     // the user has enabled the auto-brightness from the settings, it is disabled because the
80     // display is off
81     private boolean mIsAutoBrightnessEnabled = false;
82     // Indicates if auto-brightness is disabled due to the display being off. Needed for metric
83     // purposes.
84     private boolean mAutoBrightnessDisabledDueToDisplayOff;
85     // If the auto-brightness model for the last manual changes done by the user.
86     private boolean mIsShortTermModelActive = false;
87 
88     // The BrightnessConfiguration currently being used
89     // Todo(273543270): BrightnessConfiguration is an internal implementation detail of
90     //  AutomaticBrightnessController, and AutomaticBrightnessStrategy shouldn't be aware of its
91     //  existence.
92     @Nullable
93     private BrightnessConfiguration mBrightnessConfiguration;
94 
AutomaticBrightnessStrategy2(Context context, int displayId)95     public AutomaticBrightnessStrategy2(Context context, int displayId) {
96         mContext = context;
97         mDisplayId = displayId;
98         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
99         mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
100         mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
101     }
102 
103     /**
104      * Sets up the automatic brightness states of this class. Also configures
105      * AutomaticBrightnessController accounting for any manual changes made by the user.
106      */
setAutoBrightnessState(int targetDisplayState, boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy, float lastUserSetScreenBrightness, boolean userSetBrightnessChanged)107     public void setAutoBrightnessState(int targetDisplayState,
108             boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy,
109             float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) {
110         final boolean autoBrightnessEnabledInDoze =
111                 allowAutoBrightnessWhileDozingConfig && Display.isDozeState(targetDisplayState);
112         mIsAutoBrightnessEnabled = shouldUseAutoBrightness()
113                 && (targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze)
114                 && brightnessReason != BrightnessReason.REASON_OVERRIDE
115                 && mAutomaticBrightnessController != null;
116         mAutoBrightnessDisabledDueToDisplayOff = shouldUseAutoBrightness()
117                 && !(targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze);
118         final int autoBrightnessState = mIsAutoBrightnessEnabled
119                 && brightnessReason != BrightnessReason.REASON_FOLLOWER
120                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
121                 : mAutoBrightnessDisabledDueToDisplayOff
122                         ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
123                         : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
124 
125         accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness,
126                 policy, targetDisplayState, mBrightnessConfiguration, autoBrightnessState);
127     }
128 
isAutoBrightnessEnabled()129     public boolean isAutoBrightnessEnabled() {
130         return mIsAutoBrightnessEnabled;
131     }
132 
isAutoBrightnessDisabledDueToDisplayOff()133     public boolean isAutoBrightnessDisabledDueToDisplayOff() {
134         return mAutoBrightnessDisabledDueToDisplayOff;
135     }
136 
137     /**
138      * Updates the {@link BrightnessConfiguration} that is currently being used by the associated
139      * display.
140      */
setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration, boolean shouldResetShortTermModel)141     public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration,
142             boolean shouldResetShortTermModel) {
143         mBrightnessConfiguration = brightnessConfiguration;
144         setShouldResetShortTermModel(shouldResetShortTermModel);
145     }
146 
147     /**
148      * Promotes the pending auto-brightness adjustments which are yet to be applied to the current
149      * adjustments. Note that this is not applying the new adjustments to the AutoBrightness mapping
150      * strategies, but is only accommodating the changes in this class.
151      */
processPendingAutoBrightnessAdjustments()152     public boolean processPendingAutoBrightnessAdjustments() {
153         mAutoBrightnessAdjustmentChanged = false;
154         if (Float.isNaN(mPendingAutoBrightnessAdjustment)) {
155             return false;
156         }
157         if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
158             mPendingAutoBrightnessAdjustment = Float.NaN;
159             return false;
160         }
161         mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
162         mPendingAutoBrightnessAdjustment = Float.NaN;
163         mTemporaryAutoBrightnessAdjustment = Float.NaN;
164         mAutoBrightnessAdjustmentChanged = true;
165         return true;
166     }
167 
168     /**
169      * Updates the associated AutomaticBrightnessController
170      */
setAutomaticBrightnessController( AutomaticBrightnessController automaticBrightnessController)171     public void setAutomaticBrightnessController(
172             AutomaticBrightnessController automaticBrightnessController) {
173         if (automaticBrightnessController == mAutomaticBrightnessController) {
174             return;
175         }
176         if (mAutomaticBrightnessController != null) {
177             mAutomaticBrightnessController.stop();
178         }
179         mAutomaticBrightnessController = automaticBrightnessController;
180     }
181 
182     /**
183      * Returns if the auto-brightness of the associated display has been enabled or not
184      */
shouldUseAutoBrightness()185     public boolean shouldUseAutoBrightness() {
186         return mUseAutoBrightness;
187     }
188 
189     /**
190      * Sets the auto-brightness state of the associated display. Called when the user makes a change
191      * in the system setting to enable/disable the auto-brightness.
192      */
setUseAutoBrightness(boolean useAutoBrightness)193     public void setUseAutoBrightness(boolean useAutoBrightness) {
194         mUseAutoBrightness = useAutoBrightness;
195     }
196 
197     /**
198      * Returns if the user made brightness change events(Typically when they interact with the
199      * brightness slider) were accommodated in the auto-brightness mapping strategies. This doesn't
200      * account for the latest changes that have been made by the user.
201      */
isShortTermModelActive()202     public boolean isShortTermModelActive() {
203         return mIsShortTermModelActive;
204     }
205 
206     /**
207      * Sets the pending auto-brightness adjustments in the system settings. Executed
208      * when there is a change in the brightness system setting, or when there is a user switch.
209      */
updatePendingAutoBrightnessAdjustments()210     public void updatePendingAutoBrightnessAdjustments() {
211         final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
212                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
213         mPendingAutoBrightnessAdjustment = Float.isNaN(adj) ? Float.NaN
214                 : BrightnessUtils.clampBrightnessAdjustment(adj);
215     }
216 
217     /**
218      * Sets the temporary auto-brightness adjustments
219      */
setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment)220     public void setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment) {
221         mTemporaryAutoBrightnessAdjustment = temporaryAutoBrightnessAdjustment;
222     }
223 
224     /**
225      * Dumps the state of this class.
226      */
dump(PrintWriter writer)227     public void dump(PrintWriter writer) {
228         writer.println("AutomaticBrightnessStrategy:");
229         writer.println("  mDisplayId=" + mDisplayId);
230         writer.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
231         writer.println("  mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
232         writer.println(
233                 "  mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
234         writer.println("  mShouldResetShortTermModel=" + mShouldResetShortTermModel);
235         writer.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
236         writer.println("  mAutoBrightnessAdjustmentChanged=" + mAutoBrightnessAdjustmentChanged);
237         writer.println("  mAppliedTemporaryAutoBrightnessAdjustment="
238                 + mAppliedTemporaryAutoBrightnessAdjustment);
239         writer.println("  mUseAutoBrightness=" + mUseAutoBrightness);
240         writer.println("  mWasShortTermModelActive=" + mIsShortTermModelActive);
241         writer.println("  mAutoBrightnessAdjustmentReasonsFlags="
242                 + mAutoBrightnessAdjustmentReasonsFlags);
243     }
244 
245     /**
246      * Indicates if any auto-brightness adjustments have happened since the last auto-brightness was
247      * set.
248      */
getAutoBrightnessAdjustmentChanged()249     public boolean getAutoBrightnessAdjustmentChanged() {
250         return mAutoBrightnessAdjustmentChanged;
251     }
252 
253     /**
254      * Returns whether the latest temporary auto-brightness adjustments have been applied or not
255      */
isTemporaryAutoBrightnessAdjustmentApplied()256     public boolean isTemporaryAutoBrightnessAdjustmentApplied() {
257         return mAppliedTemporaryAutoBrightnessAdjustment;
258     }
259 
260     /**
261      * Evaluates the target automatic brightness of the associated display.
262      * @param brightnessEvent Event object to populate with details about why the specific
263      *                        brightness was chosen.
264      */
getAutomaticScreenBrightness(BrightnessEvent brightnessEvent)265     public float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
266         float brightness = (mAutomaticBrightnessController != null)
267                 ? mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent)
268                 : PowerManager.BRIGHTNESS_INVALID_FLOAT;
269         adjustAutomaticBrightnessStateIfValid(brightness);
270         return brightness;
271     }
272 
273     /**
274      * Gets the auto-brightness adjustment flag change reason
275      */
getAutoBrightnessAdjustmentReasonsFlags()276     public int getAutoBrightnessAdjustmentReasonsFlags() {
277         return mAutoBrightnessAdjustmentReasonsFlags;
278     }
279 
280     /**
281      * Returns if the auto brightness has been applied
282      */
hasAppliedAutoBrightness()283     public boolean hasAppliedAutoBrightness() {
284         return mAppliedAutoBrightness;
285     }
286 
287     /**
288      * Used to adjust the state of this class when the automatic brightness value for the
289      * associated display is valid
290      */
291     @VisibleForTesting
adjustAutomaticBrightnessStateIfValid(float brightnessState)292     void adjustAutomaticBrightnessStateIfValid(float brightnessState) {
293         mAutoBrightnessAdjustmentReasonsFlags = isTemporaryAutoBrightnessAdjustmentApplied()
294                 ? BrightnessReason.ADJUSTMENT_AUTO_TEMP
295                 : BrightnessReason.ADJUSTMENT_AUTO;
296         float newAutoBrightnessAdjustment =
297                 (mAutomaticBrightnessController != null)
298                         ? mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()
299                         : 0.0f;
300         if (!Float.isNaN(newAutoBrightnessAdjustment)
301                 && mAutoBrightnessAdjustment != newAutoBrightnessAdjustment) {
302             // If the auto-brightness controller has decided to change the adjustment value
303             // used, make sure that's reflected in settings.
304             putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
305         } else {
306             mAutoBrightnessAdjustmentReasonsFlags = 0;
307         }
308     }
309 
310     /**
311      * Sets up the system to reset the short term model. Note that this will not reset the model
312      * right away, but ensures that the reset happens whenever the next brightness change happens
313      */
314     @VisibleForTesting
setShouldResetShortTermModel(boolean shouldResetShortTermModel)315     void setShouldResetShortTermModel(boolean shouldResetShortTermModel) {
316         mShouldResetShortTermModel = shouldResetShortTermModel;
317     }
318 
319     @VisibleForTesting
shouldResetShortTermModel()320     boolean shouldResetShortTermModel() {
321         return mShouldResetShortTermModel;
322     }
323 
324     @VisibleForTesting
getAutoBrightnessAdjustment()325     float getAutoBrightnessAdjustment() {
326         return mAutoBrightnessAdjustment;
327     }
328 
329     @VisibleForTesting
getPendingAutoBrightnessAdjustment()330     float getPendingAutoBrightnessAdjustment() {
331         return mPendingAutoBrightnessAdjustment;
332     }
333 
334     @VisibleForTesting
getTemporaryAutoBrightnessAdjustment()335     float getTemporaryAutoBrightnessAdjustment() {
336         return mTemporaryAutoBrightnessAdjustment;
337     }
338 
339     @VisibleForTesting
putAutoBrightnessAdjustmentSetting(float adjustment)340     void putAutoBrightnessAdjustmentSetting(float adjustment) {
341         if (mDisplayId == Display.DEFAULT_DISPLAY) {
342             mAutoBrightnessAdjustment = adjustment;
343             Settings.System.putFloatForUser(mContext.getContentResolver(),
344                     Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment,
345                     UserHandle.USER_CURRENT);
346         }
347     }
348 
349     /**
350      * Sets if the auto-brightness is applied on the latest brightness change.
351      */
setAutoBrightnessApplied(boolean autoBrightnessApplied)352     public void setAutoBrightnessApplied(boolean autoBrightnessApplied) {
353         mAppliedAutoBrightness = autoBrightnessApplied;
354     }
355 
356     /**
357      * Accommodates the latest manual changes made by the user. Also updates {@link
358      * AutomaticBrightnessController} about the changes and configures it accordingly.
359      */
360     @VisibleForTesting
accommodateUserBrightnessChanges(boolean userSetBrightnessChanged, float lastUserSetScreenBrightness, int policy, int displayState, BrightnessConfiguration brightnessConfiguration, int autoBrightnessState)361     void accommodateUserBrightnessChanges(boolean userSetBrightnessChanged,
362             float lastUserSetScreenBrightness, int policy, int displayState,
363             BrightnessConfiguration brightnessConfiguration, int autoBrightnessState) {
364         // Update the pending auto-brightness adjustments if any. This typically checks and adjusts
365         // the state of the class if the user moves the brightness slider and has settled to a
366         // different value
367         processPendingAutoBrightnessAdjustments();
368         // Update the temporary auto-brightness adjustments if any. This typically checks and
369         // adjusts the state of this class if the user is in the process of moving the brightness
370         // slider, but hasn't settled to any value yet
371         float autoBrightnessAdjustment = updateTemporaryAutoBrightnessAdjustments();
372         mIsShortTermModelActive = false;
373         // Configure auto-brightness.
374         if (mAutomaticBrightnessController != null) {
375             // Accommodate user changes if any in the auto-brightness model
376             mAutomaticBrightnessController.configure(autoBrightnessState,
377                     brightnessConfiguration,
378                     lastUserSetScreenBrightness,
379                     userSetBrightnessChanged, autoBrightnessAdjustment,
380                     mAutoBrightnessAdjustmentChanged, policy, displayState,
381                     mShouldResetShortTermModel);
382             mShouldResetShortTermModel = false;
383             // We take note if the user brightness point is still being used in the current
384             // auto-brightness model.
385             mIsShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
386         }
387     }
388 
389     /**
390      * Evaluates if there are any temporary auto-brightness adjustments which is not applied yet.
391      * Temporary brightness adjustments happen when the user moves the brightness slider in the
392      * auto-brightness mode, but hasn't settled to a value yet
393      */
updateTemporaryAutoBrightnessAdjustments()394     private float updateTemporaryAutoBrightnessAdjustments() {
395         mAppliedTemporaryAutoBrightnessAdjustment =
396                 !Float.isNaN(mTemporaryAutoBrightnessAdjustment);
397         // We do not update the mAutoBrightnessAdjustment with mTemporaryAutoBrightnessAdjustment
398         // since we have not settled to a value yet
399         return mAppliedTemporaryAutoBrightnessAdjustment
400                 ? mTemporaryAutoBrightnessAdjustment : mAutoBrightnessAdjustment;
401     }
402 
403     /**
404      * Returns the auto-brightness adjustment that is set in the system setting.
405      */
getAutoBrightnessAdjustmentSetting()406     private float getAutoBrightnessAdjustmentSetting() {
407         final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
408                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
409         return Float.isNaN(adj) ? 0.0f : BrightnessUtils.clampBrightnessAdjustment(adj);
410     }
411 }
412