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