• 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.brightness;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.hardware.display.DisplayManagerInternal;
23 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
24 import android.util.IndentingPrintWriter;
25 import android.util.Slog;
26 import android.view.Display;
27 
28 import com.android.internal.R;
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.server.display.brightness.strategy.AutoBrightnessFallbackStrategy;
31 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
32 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
33 import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
34 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
35 import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
36 import com.android.server.display.brightness.strategy.FallbackBrightnessStrategy;
37 import com.android.server.display.brightness.strategy.FollowerBrightnessStrategy;
38 import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
39 import com.android.server.display.brightness.strategy.OffloadBrightnessStrategy;
40 import com.android.server.display.brightness.strategy.OverrideBrightnessStrategy;
41 import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
42 import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy;
43 import com.android.server.display.feature.DisplayManagerFlags;
44 
45 import java.io.PrintWriter;
46 
47 /**
48  * This maintains the logic needed to decide the eligible display brightness strategy.
49  */
50 public class DisplayBrightnessStrategySelector {
51     private static final String TAG = "DisplayBrightnessStrategySelector";
52     // True if the config to use the light sensor to automatically determine doze screen brightness
53     // is enabled. Note that the actual value representing if the auto-brightness is to be kept
54     // enabled while dozing can differ, but is dependent on this
55     private final boolean mAllowAutoBrightnessWhileDozingConfig;
56 
57     // True if light sensor is to be used to automatically determine doze screen brightness.
58     private boolean mAllowAutoBrightnessWhileDozing;
59 
60     // The brightness strategy used to manage the brightness state when the display is dozing.
61     private final DozeBrightnessStrategy mDozeBrightnessStrategy;
62     // The brightness strategy used to manage the brightness state when the display is in
63     // screen off state.
64     private final ScreenOffBrightnessStrategy mScreenOffBrightnessStrategy;
65     // The brightness strategy used to manage the brightness state when the request state is
66     // invalid.
67     private final OverrideBrightnessStrategy mOverrideBrightnessStrategy;
68     // The brightness strategy used to manage the brightness state in temporary state
69     private final TemporaryBrightnessStrategy mTemporaryBrightnessStrategy;
70     // The brightness strategy used to manage the brightness state when boost is requested
71     private final BoostBrightnessStrategy mBoostBrightnessStrategy;
72     // The brightness strategy used for additional displays
73     private final FollowerBrightnessStrategy mFollowerBrightnessStrategy;
74     // The brightness strategy used to manage the brightness state when the request is invalid.
75     private final InvalidBrightnessStrategy mInvalidBrightnessStrategy;
76     // Controls brightness when automatic (adaptive) brightness is running.
77     private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy;
78 
79     // The automatic strategy which controls the brightness when adaptive mode is ON.
80     private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy1;
81 
82     // The deprecated AutomaticBrightnessStrategy. Avoid using it for any new features without
83     // consulting with the display frameworks team. Use {@link AutomaticBrightnessStrategy} instead.
84     // This will be removed once the flag
85     // {@link DisplayManagerFlags#isRefactorDisplayPowerControllerEnabled is fully rolled out
86     private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy2;
87     // Controls the brightness if adaptive brightness is on and there exists an active offload
88     // session. Brightness value is provided by the offload session.
89     @Nullable
90     private final OffloadBrightnessStrategy mOffloadBrightnessStrategy;
91 
92     @Nullable
93     private final AutoBrightnessFallbackStrategy mAutoBrightnessFallbackStrategy;
94 
95     @Nullable
96     private final FallbackBrightnessStrategy mFallbackBrightnessStrategy;
97 
98     // A collective representation of all the strategies that the selector is aware of. This is
99     // non null, but the strategies this is tracking can be null
100     @NonNull
101     @VisibleForTesting
102     final DisplayBrightnessStrategy[] mDisplayBrightnessStrategies;
103 
104     @NonNull
105     private final DisplayManagerFlags mDisplayManagerFlags;
106 
107     // We take note of the old brightness strategy so that we can know when the strategy changes.
108     private String mOldBrightnessStrategyName;
109 
110     private final int mDisplayId;
111 
112     private final Context mContext;
113 
114     /**
115      * The constructor of DozeBrightnessStrategy.
116      */
DisplayBrightnessStrategySelector(Context context, Injector injector, int displayId, DisplayManagerFlags flags)117     public DisplayBrightnessStrategySelector(Context context, Injector injector, int displayId,
118             DisplayManagerFlags flags) {
119         if (injector == null) {
120             injector = new Injector();
121         }
122         mContext = context;
123         mDisplayManagerFlags = flags;
124         mDisplayId = displayId;
125         mDozeBrightnessStrategy = injector.getDozeBrightnessStrategy();
126         mScreenOffBrightnessStrategy = injector.getScreenOffBrightnessStrategy();
127         mOverrideBrightnessStrategy = injector.getOverrideBrightnessStrategy();
128         mTemporaryBrightnessStrategy = injector.getTemporaryBrightnessStrategy();
129         mBoostBrightnessStrategy = injector.getBoostBrightnessStrategy();
130         mFollowerBrightnessStrategy = injector.getFollowerBrightnessStrategy(displayId);
131         mInvalidBrightnessStrategy = injector.getInvalidBrightnessStrategy();
132         mAutomaticBrightnessStrategy1 =
133                 (!mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) ? null
134                         : injector.getAutomaticBrightnessStrategy1(context, displayId,
135                                 mDisplayManagerFlags);
136         mAutomaticBrightnessStrategy2 =
137                 (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) ? null
138                         : injector.getAutomaticBrightnessStrategy2(context, displayId);
139         mAutomaticBrightnessStrategy =
140                 (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled())
141                         ? mAutomaticBrightnessStrategy1 : mAutomaticBrightnessStrategy2;
142         mAutoBrightnessFallbackStrategy = (mDisplayManagerFlags
143                 .isRefactorDisplayPowerControllerEnabled())
144                 ? injector.getAutoBrightnessFallbackStrategy() : null;
145         if (flags.isDisplayOffloadEnabled()) {
146             mOffloadBrightnessStrategy = injector
147                     .getOffloadBrightnessStrategy(mDisplayManagerFlags);
148         } else {
149             mOffloadBrightnessStrategy = null;
150         }
151         mFallbackBrightnessStrategy = (mDisplayManagerFlags
152                 .isRefactorDisplayPowerControllerEnabled())
153                 ? injector.getFallbackBrightnessStrategy() : null;
154         mDisplayBrightnessStrategies = new DisplayBrightnessStrategy[]{mInvalidBrightnessStrategy,
155                 mScreenOffBrightnessStrategy, mDozeBrightnessStrategy, mFollowerBrightnessStrategy,
156                 mBoostBrightnessStrategy, mOverrideBrightnessStrategy, mTemporaryBrightnessStrategy,
157                 mAutomaticBrightnessStrategy1, mOffloadBrightnessStrategy,
158                 mAutoBrightnessFallbackStrategy, mFallbackBrightnessStrategy};
159         mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
160                 R.bool.config_allowAutoBrightnessWhileDozing);
161         mAllowAutoBrightnessWhileDozing = mAllowAutoBrightnessWhileDozingConfig;
162         mOldBrightnessStrategyName = mInvalidBrightnessStrategy.getName();
163     }
164 
165     /**
166      * Selects the appropriate DisplayBrightnessStrategy based on the request and the display state
167      * to which the display is transitioning
168      */
169     @NonNull
selectStrategy( StrategySelectionRequest strategySelectionRequest)170     public DisplayBrightnessStrategy selectStrategy(
171             StrategySelectionRequest strategySelectionRequest) {
172         DisplayBrightnessStrategy displayBrightnessStrategy = mInvalidBrightnessStrategy;
173         int targetDisplayState = strategySelectionRequest.getTargetDisplayState();
174         DisplayPowerRequest displayPowerRequest = strategySelectionRequest
175                 .getDisplayPowerRequest();
176         setAllowAutoBrightnessWhileDozing(strategySelectionRequest.getDisplayOffloadSession());
177         if (targetDisplayState == Display.STATE_OFF) {
178             displayBrightnessStrategy = mScreenOffBrightnessStrategy;
179         } else if (shouldUseDozeBrightnessStrategy(displayPowerRequest)) {
180             displayBrightnessStrategy = mDozeBrightnessStrategy;
181         } else if (BrightnessUtils.isValidBrightnessValue(
182                 mFollowerBrightnessStrategy.getBrightnessToFollow())) {
183             displayBrightnessStrategy = mFollowerBrightnessStrategy;
184         } else if (displayPowerRequest.boostScreenBrightness) {
185             displayBrightnessStrategy = mBoostBrightnessStrategy;
186         } else if (BrightnessUtils.isValidBrightnessValue(
187                 displayPowerRequest.screenBrightnessOverride)
188                 || BrightnessUtils.isValidBrightnessValue(
189                         mOverrideBrightnessStrategy.getWindowManagerBrightnessOverride())) {
190             displayBrightnessStrategy = mOverrideBrightnessStrategy;
191         } else if (BrightnessUtils.isValidBrightnessValue(
192                 mTemporaryBrightnessStrategy.getTemporaryScreenBrightness())) {
193             displayBrightnessStrategy = mTemporaryBrightnessStrategy;
194         } else if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()
195                 && isAutomaticBrightnessStrategyValid(strategySelectionRequest)) {
196             displayBrightnessStrategy = mAutomaticBrightnessStrategy1;
197         } else if (mAutomaticBrightnessStrategy.shouldUseAutoBrightness()
198                 && mOffloadBrightnessStrategy != null && BrightnessUtils.isValidBrightnessValue(
199                 mOffloadBrightnessStrategy.getOffloadScreenBrightness())) {
200             displayBrightnessStrategy = mOffloadBrightnessStrategy;
201         } else if (isAutoBrightnessFallbackStrategyValid()) {
202             displayBrightnessStrategy = mAutoBrightnessFallbackStrategy;
203         } else {
204             // This will become the ultimate fallback strategy once the flag has been fully rolled
205             // out
206             if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
207                 displayBrightnessStrategy = mFallbackBrightnessStrategy;
208             }
209         }
210 
211         if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
212             postProcess(constructStrategySelectionNotifyRequest(displayBrightnessStrategy,
213                     strategySelectionRequest));
214         }
215 
216         if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
217             Slog.i(TAG,
218                     "Changing the DisplayBrightnessStrategy from " + mOldBrightnessStrategyName
219                             + " to " + displayBrightnessStrategy.getName() + " for display "
220                             + mDisplayId);
221             mOldBrightnessStrategyName = displayBrightnessStrategy.getName();
222         }
223         return displayBrightnessStrategy;
224     }
225 
getTemporaryDisplayBrightnessStrategy()226     public TemporaryBrightnessStrategy getTemporaryDisplayBrightnessStrategy() {
227         return mTemporaryBrightnessStrategy;
228     }
229 
getFollowerDisplayBrightnessStrategy()230     public FollowerBrightnessStrategy getFollowerDisplayBrightnessStrategy() {
231         return mFollowerBrightnessStrategy;
232     }
233 
getAutomaticBrightnessStrategy()234     public AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy() {
235         return mAutomaticBrightnessStrategy;
236     }
237 
238     @Nullable
getOffloadBrightnessStrategy()239     public OffloadBrightnessStrategy getOffloadBrightnessStrategy() {
240         return mOffloadBrightnessStrategy;
241     }
242 
243     /**
244      * Returns a boolean flag indicating if the light sensor is to be used to decide the screen
245      * brightness when dozing
246      */
isAllowAutoBrightnessWhileDozing()247     public boolean isAllowAutoBrightnessWhileDozing() {
248         return mAllowAutoBrightnessWhileDozing;
249     }
250 
251     /**
252      * Returns the config value indicating whether auto brightness while dozing is to be
253      * allowed ot not
254      */
isAllowAutoBrightnessWhileDozingConfig()255     public boolean isAllowAutoBrightnessWhileDozingConfig() {
256         return mAllowAutoBrightnessWhileDozingConfig;
257     }
258 
259     @Nullable
getAutoBrightnessFallbackStrategy()260     public AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
261         return mAutoBrightnessFallbackStrategy;
262     }
263 
getOverrideBrightnessStrategy()264     public OverrideBrightnessStrategy getOverrideBrightnessStrategy() {
265         return mOverrideBrightnessStrategy;
266     }
267 
268     /**
269      * Dumps the state of this class.
270      */
dump(PrintWriter writer)271     public void dump(PrintWriter writer) {
272         writer.println();
273         writer.println("DisplayBrightnessStrategySelector:");
274         writer.println("----------------------------------");
275         writer.println("  mDisplayId= " + mDisplayId);
276         writer.println("  mOldBrightnessStrategyName= " + mOldBrightnessStrategyName);
277         writer.println(
278                 "  mAllowAutoBrightnessWhileDozingConfig= "
279                         + mAllowAutoBrightnessWhileDozingConfig);
280         writer.println(
281                 "  mAllowAutoBrightnessWhileDozing= " + mAllowAutoBrightnessWhileDozing);
282         IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
283         for (DisplayBrightnessStrategy displayBrightnessStrategy : mDisplayBrightnessStrategies) {
284             if (displayBrightnessStrategy != null) {
285                 displayBrightnessStrategy.dump(ipw);
286             }
287         }
288     }
289 
290     @VisibleForTesting
setAllowAutoBrightnessWhileDozing( DisplayManagerInternal.DisplayOffloadSession displayOffloadSession)291     void setAllowAutoBrightnessWhileDozing(
292             DisplayManagerInternal.DisplayOffloadSession displayOffloadSession) {
293         mAllowAutoBrightnessWhileDozing = mAllowAutoBrightnessWhileDozingConfig;
294         if (mDisplayManagerFlags.isDisplayOffloadEnabled()
295                 && displayOffloadSession != null) {
296             mAllowAutoBrightnessWhileDozing &= displayOffloadSession.allowAutoBrightnessInDoze();
297         }
298     }
299 
isAutoBrightnessFallbackStrategyValid()300     private boolean isAutoBrightnessFallbackStrategyValid() {
301         return mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()
302                 && mAutoBrightnessFallbackStrategy != null
303                 && getAutomaticBrightnessStrategy().shouldUseAutoBrightness()
304                 && mAutoBrightnessFallbackStrategy.isValid();
305     }
306 
isAutomaticBrightnessStrategyValid( StrategySelectionRequest strategySelectionRequest)307     private boolean isAutomaticBrightnessStrategyValid(
308             StrategySelectionRequest strategySelectionRequest) {
309         mAutomaticBrightnessStrategy1.setAutoBrightnessState(
310                 strategySelectionRequest.getTargetDisplayState(),
311                 mAllowAutoBrightnessWhileDozing,
312                 BrightnessReason.REASON_UNKNOWN,
313                 strategySelectionRequest.getDisplayPowerRequest().policy,
314                 strategySelectionRequest.getDisplayPowerRequest().useNormalBrightnessForDoze,
315                 strategySelectionRequest.getLastUserSetScreenBrightness(),
316                 strategySelectionRequest.isUserSetBrightnessChanged(),
317                 strategySelectionRequest.isWearBedtimeModeEnabled());
318         return !strategySelectionRequest.isStylusBeingUsed()
319                 && mAutomaticBrightnessStrategy1.isAutoBrightnessValid();
320     }
321 
constructStrategySelectionNotifyRequest( DisplayBrightnessStrategy selectedDisplayBrightnessStrategy, StrategySelectionRequest strategySelectionRequest)322     private StrategySelectionNotifyRequest constructStrategySelectionNotifyRequest(
323             DisplayBrightnessStrategy selectedDisplayBrightnessStrategy,
324             StrategySelectionRequest strategySelectionRequest) {
325         return new StrategySelectionNotifyRequest(
326                 strategySelectionRequest.getDisplayPowerRequest(),
327                 strategySelectionRequest.getTargetDisplayState(),
328                 selectedDisplayBrightnessStrategy,
329                 strategySelectionRequest.getLastUserSetScreenBrightness(),
330                 strategySelectionRequest.isUserSetBrightnessChanged(),
331                 mAllowAutoBrightnessWhileDozing,
332                 getAutomaticBrightnessStrategy().shouldUseAutoBrightness(),
333                 strategySelectionRequest.isWearBedtimeModeEnabled());
334     }
335 
postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest)336     private void postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
337         for (DisplayBrightnessStrategy displayBrightnessStrategy : mDisplayBrightnessStrategies) {
338             if (displayBrightnessStrategy != null) {
339                 displayBrightnessStrategy.strategySelectionPostProcessor(
340                         strategySelectionNotifyRequest);
341             }
342         }
343     }
344 
345     /**
346      * Validates if the conditions are met to qualify for the DozeBrightnessStrategy.
347      */
shouldUseDozeBrightnessStrategy(DisplayPowerRequest displayPowerRequest)348     private boolean shouldUseDozeBrightnessStrategy(DisplayPowerRequest displayPowerRequest) {
349         // We are not checking the targetDisplayState, but rather relying on the policy because
350         // a user can define a different display state(displayPowerRequest.dozeScreenState) too
351         // in the request with the Doze policy and user might request an override to force certain
352         // brightness.
353         return (!mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled(mContext)
354                 || !displayPowerRequest.useNormalBrightnessForDoze)
355                 && displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
356                 && !mAllowAutoBrightnessWhileDozing
357                 && BrightnessUtils.isValidBrightnessValue(displayPowerRequest.dozeScreenBrightness);
358     }
359 
360     @VisibleForTesting
361     static class Injector {
getScreenOffBrightnessStrategy()362         ScreenOffBrightnessStrategy getScreenOffBrightnessStrategy() {
363             return new ScreenOffBrightnessStrategy();
364         }
365 
getDozeBrightnessStrategy()366         DozeBrightnessStrategy getDozeBrightnessStrategy() {
367             return new DozeBrightnessStrategy();
368         }
369 
getOverrideBrightnessStrategy()370         OverrideBrightnessStrategy getOverrideBrightnessStrategy() {
371             return new OverrideBrightnessStrategy();
372         }
373 
getTemporaryBrightnessStrategy()374         TemporaryBrightnessStrategy getTemporaryBrightnessStrategy() {
375             return new TemporaryBrightnessStrategy();
376         }
377 
getBoostBrightnessStrategy()378         BoostBrightnessStrategy getBoostBrightnessStrategy() {
379             return new BoostBrightnessStrategy();
380         }
381 
getFollowerBrightnessStrategy(int displayId)382         FollowerBrightnessStrategy getFollowerBrightnessStrategy(int displayId) {
383             return new FollowerBrightnessStrategy(displayId);
384         }
385 
getInvalidBrightnessStrategy()386         InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
387             return new InvalidBrightnessStrategy();
388         }
389 
getAutomaticBrightnessStrategy1(Context context, int displayId, DisplayManagerFlags displayManagerFlags)390         AutomaticBrightnessStrategy getAutomaticBrightnessStrategy1(Context context,
391                 int displayId, DisplayManagerFlags displayManagerFlags) {
392             return new AutomaticBrightnessStrategy(context, displayId, displayManagerFlags);
393         }
394 
getAutomaticBrightnessStrategy2(Context context, int displayId)395         AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy2(Context context,
396                 int displayId) {
397             return new AutomaticBrightnessStrategy2(context, displayId);
398         }
399 
getOffloadBrightnessStrategy( DisplayManagerFlags displayManagerFlags)400         OffloadBrightnessStrategy getOffloadBrightnessStrategy(
401                 DisplayManagerFlags displayManagerFlags) {
402             return new OffloadBrightnessStrategy(displayManagerFlags);
403         }
404 
getAutoBrightnessFallbackStrategy()405         AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
406             return new AutoBrightnessFallbackStrategy(/* injector= */ null);
407         }
408 
getFallbackBrightnessStrategy()409         FallbackBrightnessStrategy getFallbackBrightnessStrategy() {
410             return new FallbackBrightnessStrategy();
411         }
412     }
413 }
414