1 /* 2 * Copyright (C) 2023 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.feature; 18 19 import android.os.Build; 20 import android.os.SystemProperties; 21 import android.text.TextUtils; 22 import android.util.Slog; 23 24 import com.android.server.display.feature.flags.Flags; 25 import com.android.server.display.utils.DebugUtils; 26 27 import java.io.PrintWriter; 28 import java.util.function.Supplier; 29 30 /** 31 * Utility class to read the flags used in the display manager server. 32 */ 33 public class DisplayManagerFlags { 34 private static final String TAG = "DisplayManagerFlags"; 35 36 // To enable these logs, run: 37 // 'adb shell setprop persist.log.tag.DisplayManagerFlags DEBUG && adb reboot' 38 private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); 39 40 private final FlagState mPortInDisplayLayoutFlagState = new FlagState( 41 Flags.FLAG_ENABLE_PORT_IN_DISPLAY_LAYOUT, 42 Flags::enablePortInDisplayLayout); 43 44 private final FlagState mConnectedDisplayManagementFlagState = new FlagState( 45 Flags.FLAG_ENABLE_CONNECTED_DISPLAY_MANAGEMENT, 46 Flags::enableConnectedDisplayManagement); 47 48 private final FlagState mNbmControllerFlagState = new FlagState( 49 Flags.FLAG_ENABLE_NBM_CONTROLLER, 50 Flags::enableNbmController); 51 52 private final FlagState mHdrClamperFlagState = new FlagState( 53 Flags.FLAG_ENABLE_HDR_CLAMPER, 54 Flags::enableHdrClamper); 55 56 private final FlagState mAdaptiveToneImprovements1 = new FlagState( 57 Flags.FLAG_ENABLE_ADAPTIVE_TONE_IMPROVEMENTS_1, 58 Flags::enableAdaptiveToneImprovements1); 59 60 private final FlagState mAdaptiveToneImprovements2 = new FlagState( 61 Flags.FLAG_ENABLE_ADAPTIVE_TONE_IMPROVEMENTS_2, 62 Flags::enableAdaptiveToneImprovements2); 63 64 private final FlagState mDisplayOffloadFlagState = new FlagState( 65 Flags.FLAG_ENABLE_DISPLAY_OFFLOAD, 66 Flags::enableDisplayOffload); 67 68 private final FlagState mExternalDisplayLimitModeState = new FlagState( 69 Flags.FLAG_ENABLE_MODE_LIMIT_FOR_EXTERNAL_DISPLAY, 70 Flags::enableModeLimitForExternalDisplay); 71 72 private final FlagState mConnectedDisplayErrorHandlingFlagState = new FlagState( 73 Flags.FLAG_ENABLE_CONNECTED_DISPLAY_ERROR_HANDLING, 74 Flags::enableConnectedDisplayErrorHandling); 75 76 private final FlagState mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState = new FlagState( 77 Flags.FLAG_BACK_UP_SMOOTH_DISPLAY_AND_FORCE_PEAK_REFRESH_RATE, 78 Flags::backUpSmoothDisplayAndForcePeakRefreshRate); 79 80 private final FlagState mPowerThrottlingClamperFlagState = new FlagState( 81 Flags.FLAG_ENABLE_POWER_THROTTLING_CLAMPER, 82 Flags::enablePowerThrottlingClamper); 83 84 private final FlagState mEvenDimmerFlagState = new FlagState( 85 Flags.FLAG_EVEN_DIMMER, 86 Flags::evenDimmer); 87 private final FlagState mSmallAreaDetectionFlagState = new FlagState( 88 com.android.graphics.surfaceflinger.flags.Flags.FLAG_ENABLE_SMALL_AREA_DETECTION, 89 com.android.graphics.surfaceflinger.flags.Flags::enableSmallAreaDetection); 90 91 private final FlagState mBrightnessIntRangeUserPerceptionFlagState = new FlagState( 92 Flags.FLAG_BRIGHTNESS_INT_RANGE_USER_PERCEPTION, 93 Flags::brightnessIntRangeUserPerception); 94 95 private final FlagState mRestrictDisplayModes = new FlagState( 96 Flags.FLAG_ENABLE_RESTRICT_DISPLAY_MODES, 97 Flags::enableRestrictDisplayModes); 98 99 private final FlagState mResolutionBackupRestore = new FlagState( 100 Flags.FLAG_RESOLUTION_BACKUP_RESTORE, 101 Flags::resolutionBackupRestore); 102 103 private final FlagState mVsyncLowPowerVote = new FlagState( 104 Flags.FLAG_ENABLE_VSYNC_LOW_POWER_VOTE, 105 Flags::enableVsyncLowPowerVote); 106 107 private final FlagState mVsyncLowLightVote = new FlagState( 108 Flags.FLAG_ENABLE_VSYNC_LOW_LIGHT_VOTE, 109 Flags::enableVsyncLowLightVote); 110 111 private final FlagState mBrightnessWearBedtimeModeClamperFlagState = new FlagState( 112 Flags.FLAG_BRIGHTNESS_WEAR_BEDTIME_MODE_CLAMPER, 113 Flags::brightnessWearBedtimeModeClamper); 114 115 private final FlagState mAutoBrightnessModesFlagState = new FlagState( 116 Flags.FLAG_AUTO_BRIGHTNESS_MODES, 117 Flags::autoBrightnessModes); 118 119 private final FlagState mFastHdrTransitions = new FlagState( 120 Flags.FLAG_FAST_HDR_TRANSITIONS, 121 Flags::fastHdrTransitions); 122 123 private final FlagState mAlwaysRotateDisplayDevice = new FlagState( 124 Flags.FLAG_ALWAYS_ROTATE_DISPLAY_DEVICE, 125 Flags::alwaysRotateDisplayDevice); 126 127 private final FlagState mRefreshRateVotingTelemetry = new FlagState( 128 Flags.FLAG_REFRESH_RATE_VOTING_TELEMETRY, 129 Flags::refreshRateVotingTelemetry 130 ); 131 132 private final FlagState mPixelAnisotropyCorrectionEnabled = new FlagState( 133 Flags.FLAG_ENABLE_PIXEL_ANISOTROPY_CORRECTION, 134 Flags::enablePixelAnisotropyCorrection 135 ); 136 137 private final FlagState mSensorBasedBrightnessThrottling = new FlagState( 138 Flags.FLAG_SENSOR_BASED_BRIGHTNESS_THROTTLING, 139 Flags::sensorBasedBrightnessThrottling 140 ); 141 142 private final FlagState mIdleScreenRefreshRateTimeout = new FlagState( 143 Flags.FLAG_IDLE_SCREEN_REFRESH_RATE_TIMEOUT, 144 Flags::idleScreenRefreshRateTimeout 145 ); 146 147 private final FlagState mRefactorDisplayPowerController = new FlagState( 148 Flags.FLAG_REFACTOR_DISPLAY_POWER_CONTROLLER, 149 Flags::refactorDisplayPowerController 150 ); 151 152 private final FlagState mUseFusionProxSensor = new FlagState( 153 Flags.FLAG_USE_FUSION_PROX_SENSOR, 154 Flags::useFusionProxSensor 155 ); 156 157 private final FlagState mOffloadControlsDozeAutoBrightness = new FlagState( 158 Flags.FLAG_OFFLOAD_CONTROLS_DOZE_AUTO_BRIGHTNESS, 159 Flags::offloadControlsDozeAutoBrightness 160 ); 161 162 private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState( 163 Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT, 164 Flags::enablePeakRefreshRatePhysicalLimit 165 ); 166 167 private final FlagState mIgnoreAppPreferredRefreshRate = new FlagState( 168 Flags.FLAG_IGNORE_APP_PREFERRED_REFRESH_RATE_REQUEST, 169 Flags::ignoreAppPreferredRefreshRateRequest 170 ); 171 172 private final FlagState mSynthetic60hzModes = new FlagState( 173 Flags.FLAG_ENABLE_SYNTHETIC_60HZ_MODES, 174 Flags::enableSynthetic60hzModes 175 ); 176 177 private final FlagState mOffloadDozeOverrideHoldsWakelock = new FlagState( 178 Flags.FLAG_OFFLOAD_DOZE_OVERRIDE_HOLDS_WAKELOCK, 179 Flags::offloadDozeOverrideHoldsWakelock 180 ); 181 182 /** 183 * @return {@code true} if 'port' is allowed in display layout configuration file. 184 */ isPortInDisplayLayoutEnabled()185 public boolean isPortInDisplayLayoutEnabled() { 186 return mPortInDisplayLayoutFlagState.isEnabled(); 187 } 188 189 /** Returns whether connected display management is enabled or not. */ isConnectedDisplayManagementEnabled()190 public boolean isConnectedDisplayManagementEnabled() { 191 return mConnectedDisplayManagementFlagState.isEnabled(); 192 } 193 194 /** Returns whether NBM Controller is enabled or not. */ isNbmControllerEnabled()195 public boolean isNbmControllerEnabled() { 196 return mNbmControllerFlagState.isEnabled(); 197 } 198 199 /** Returns whether hdr clamper is enabled on not. */ isHdrClamperEnabled()200 public boolean isHdrClamperEnabled() { 201 return mHdrClamperFlagState.isEnabled(); 202 } 203 204 /** Returns whether power throttling clamper is enabled on not. */ isPowerThrottlingClamperEnabled()205 public boolean isPowerThrottlingClamperEnabled() { 206 return mPowerThrottlingClamperFlagState.isEnabled(); 207 } 208 209 /** 210 * Returns whether adaptive tone improvements are enabled 211 */ isAdaptiveTone1Enabled()212 public boolean isAdaptiveTone1Enabled() { 213 return mAdaptiveToneImprovements1.isEnabled(); 214 } 215 216 /** 217 * Returns whether adaptive tone improvements are enabled 218 */ isAdaptiveTone2Enabled()219 public boolean isAdaptiveTone2Enabled() { 220 return mAdaptiveToneImprovements2.isEnabled(); 221 } 222 223 /** Returns whether resolution range voting feature is enabled or not. */ isDisplayResolutionRangeVotingEnabled()224 public boolean isDisplayResolutionRangeVotingEnabled() { 225 return isExternalDisplayLimitModeEnabled(); 226 } 227 228 /** 229 * @return Whether user preferred mode is added as a vote in 230 * {@link com.android.server.display.mode.DisplayModeDirector} 231 */ isUserPreferredModeVoteEnabled()232 public boolean isUserPreferredModeVoteEnabled() { 233 return isExternalDisplayLimitModeEnabled(); 234 } 235 236 /** 237 * @return Whether external display mode limitation is enabled. 238 */ isExternalDisplayLimitModeEnabled()239 public boolean isExternalDisplayLimitModeEnabled() { 240 return mExternalDisplayLimitModeState.isEnabled(); 241 } 242 243 /** 244 * @return Whether displays refresh rate synchronization is enabled. 245 */ isDisplaysRefreshRatesSynchronizationEnabled()246 public boolean isDisplaysRefreshRatesSynchronizationEnabled() { 247 return isExternalDisplayLimitModeEnabled(); 248 } 249 250 /** Returns whether displayoffload is enabled on not */ isDisplayOffloadEnabled()251 public boolean isDisplayOffloadEnabled() { 252 return mDisplayOffloadFlagState.isEnabled(); 253 } 254 255 /** Returns whether error notifications for connected displays are enabled on not */ isConnectedDisplayErrorHandlingEnabled()256 public boolean isConnectedDisplayErrorHandlingEnabled() { 257 return mConnectedDisplayErrorHandlingFlagState.isEnabled(); 258 } 259 isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()260 public boolean isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled() { 261 return mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState.isEnabled(); 262 } 263 264 /** Returns whether brightness range is allowed to extend below traditional range. */ isEvenDimmerEnabled()265 public boolean isEvenDimmerEnabled() { 266 return mEvenDimmerFlagState.isEnabled(); 267 } 268 isSmallAreaDetectionEnabled()269 public boolean isSmallAreaDetectionEnabled() { 270 return mSmallAreaDetectionFlagState.isEnabled(); 271 } 272 isBrightnessIntRangeUserPerceptionEnabled()273 public boolean isBrightnessIntRangeUserPerceptionEnabled() { 274 return mBrightnessIntRangeUserPerceptionFlagState.isEnabled(); 275 } 276 isRestrictDisplayModesEnabled()277 public boolean isRestrictDisplayModesEnabled() { 278 return mRestrictDisplayModes.isEnabled(); 279 } 280 isResolutionBackupRestoreEnabled()281 public boolean isResolutionBackupRestoreEnabled() { 282 return mResolutionBackupRestore.isEnabled(); 283 } 284 isVsyncLowPowerVoteEnabled()285 public boolean isVsyncLowPowerVoteEnabled() { 286 return mVsyncLowPowerVote.isEnabled(); 287 } 288 isVsyncLowLightVoteEnabled()289 public boolean isVsyncLowLightVoteEnabled() { 290 return mVsyncLowLightVote.isEnabled(); 291 } 292 isBrightnessWearBedtimeModeClamperEnabled()293 public boolean isBrightnessWearBedtimeModeClamperEnabled() { 294 return mBrightnessWearBedtimeModeClamperFlagState.isEnabled(); 295 } 296 297 /** 298 * @return Whether generic auto-brightness modes are enabled 299 */ areAutoBrightnessModesEnabled()300 public boolean areAutoBrightnessModesEnabled() { 301 return mAutoBrightnessModesFlagState.isEnabled(); 302 } 303 isFastHdrTransitionsEnabled()304 public boolean isFastHdrTransitionsEnabled() { 305 return mFastHdrTransitions.isEnabled(); 306 } 307 isAlwaysRotateDisplayDeviceEnabled()308 public boolean isAlwaysRotateDisplayDeviceEnabled() { 309 return mAlwaysRotateDisplayDevice.isEnabled(); 310 } 311 isRefreshRateVotingTelemetryEnabled()312 public boolean isRefreshRateVotingTelemetryEnabled() { 313 return mRefreshRateVotingTelemetry.isEnabled(); 314 } 315 isPixelAnisotropyCorrectionInLogicalDisplayEnabled()316 public boolean isPixelAnisotropyCorrectionInLogicalDisplayEnabled() { 317 return mPixelAnisotropyCorrectionEnabled.isEnabled(); 318 } 319 isSensorBasedBrightnessThrottlingEnabled()320 public boolean isSensorBasedBrightnessThrottlingEnabled() { 321 return mSensorBasedBrightnessThrottling.isEnabled(); 322 } 323 isIdleScreenRefreshRateTimeoutEnabled()324 public boolean isIdleScreenRefreshRateTimeoutEnabled() { 325 return mIdleScreenRefreshRateTimeout.isEnabled(); 326 } 327 isRefactorDisplayPowerControllerEnabled()328 public boolean isRefactorDisplayPowerControllerEnabled() { 329 return mRefactorDisplayPowerController.isEnabled(); 330 } 331 isUseFusionProxSensorEnabled()332 public boolean isUseFusionProxSensorEnabled() { 333 return mUseFusionProxSensor.isEnabled(); 334 } 335 getUseFusionProxSensorFlagName()336 public String getUseFusionProxSensorFlagName() { 337 return mUseFusionProxSensor.getName(); 338 } 339 340 /** 341 * @return Whether DisplayOffload should control auto-brightness in doze 342 */ offloadControlsDozeAutoBrightness()343 public boolean offloadControlsDozeAutoBrightness() { 344 return mOffloadControlsDozeAutoBrightness.isEnabled(); 345 } 346 isPeakRefreshRatePhysicalLimitEnabled()347 public boolean isPeakRefreshRatePhysicalLimitEnabled() { 348 return mPeakRefreshRatePhysicalLimit.isEnabled(); 349 } 350 isOffloadDozeOverrideHoldsWakelockEnabled()351 public boolean isOffloadDozeOverrideHoldsWakelockEnabled() { 352 return mOffloadDozeOverrideHoldsWakelock.isEnabled(); 353 } 354 355 /** 356 * @return Whether to ignore preferredRefreshRate app request conversion to display mode or not 357 */ ignoreAppPreferredRefreshRateRequest()358 public boolean ignoreAppPreferredRefreshRateRequest() { 359 return mIgnoreAppPreferredRefreshRate.isEnabled(); 360 } 361 isSynthetic60HzModesEnabled()362 public boolean isSynthetic60HzModesEnabled() { 363 return mSynthetic60hzModes.isEnabled(); 364 } 365 366 /** 367 * dumps all flagstates 368 * @param pw printWriter 369 */ dump(PrintWriter pw)370 public void dump(PrintWriter pw) { 371 pw.println("DisplayManagerFlags:"); 372 pw.println(" " + mAdaptiveToneImprovements1); 373 pw.println(" " + mAdaptiveToneImprovements2); 374 pw.println(" " + mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState); 375 pw.println(" " + mConnectedDisplayErrorHandlingFlagState); 376 pw.println(" " + mConnectedDisplayManagementFlagState); 377 pw.println(" " + mDisplayOffloadFlagState); 378 pw.println(" " + mExternalDisplayLimitModeState); 379 pw.println(" " + mHdrClamperFlagState); 380 pw.println(" " + mNbmControllerFlagState); 381 pw.println(" " + mPowerThrottlingClamperFlagState); 382 pw.println(" " + mEvenDimmerFlagState); 383 pw.println(" " + mSmallAreaDetectionFlagState); 384 pw.println(" " + mBrightnessIntRangeUserPerceptionFlagState); 385 pw.println(" " + mRestrictDisplayModes); 386 pw.println(" " + mBrightnessWearBedtimeModeClamperFlagState); 387 pw.println(" " + mAutoBrightnessModesFlagState); 388 pw.println(" " + mFastHdrTransitions); 389 pw.println(" " + mAlwaysRotateDisplayDevice); 390 pw.println(" " + mRefreshRateVotingTelemetry); 391 pw.println(" " + mPixelAnisotropyCorrectionEnabled); 392 pw.println(" " + mSensorBasedBrightnessThrottling); 393 pw.println(" " + mIdleScreenRefreshRateTimeout); 394 pw.println(" " + mRefactorDisplayPowerController); 395 pw.println(" " + mResolutionBackupRestore); 396 pw.println(" " + mUseFusionProxSensor); 397 pw.println(" " + mOffloadControlsDozeAutoBrightness); 398 pw.println(" " + mPeakRefreshRatePhysicalLimit); 399 pw.println(" " + mIgnoreAppPreferredRefreshRate); 400 pw.println(" " + mSynthetic60hzModes); 401 pw.println(" " + mOffloadDozeOverrideHoldsWakelock); 402 } 403 404 private static class FlagState { 405 406 private final String mName; 407 408 private final Supplier<Boolean> mFlagFunction; 409 private boolean mEnabledSet; 410 private boolean mEnabled; 411 FlagState(String name, Supplier<Boolean> flagFunction)412 private FlagState(String name, Supplier<Boolean> flagFunction) { 413 mName = name; 414 mFlagFunction = flagFunction; 415 } 416 getName()417 private String getName() { 418 return mName; 419 } 420 isEnabled()421 private boolean isEnabled() { 422 if (mEnabledSet) { 423 if (DEBUG) { 424 Slog.d(TAG, mName + ": mEnabled. Recall = " + mEnabled); 425 } 426 return mEnabled; 427 } 428 mEnabled = flagOrSystemProperty(mFlagFunction, mName); 429 if (DEBUG) { 430 Slog.d(TAG, mName + ": mEnabled. Flag value = " + mEnabled); 431 } 432 mEnabledSet = true; 433 return mEnabled; 434 } 435 flagOrSystemProperty(Supplier<Boolean> flagFunction, String flagName)436 private boolean flagOrSystemProperty(Supplier<Boolean> flagFunction, String flagName) { 437 boolean flagValue = flagFunction.get(); 438 // TODO(b/299462337) Remove when the infrastructure is ready. 439 if (Build.IS_ENG || Build.IS_USERDEBUG) { 440 return SystemProperties.getBoolean("persist.sys." + flagName + "-override", 441 flagValue); 442 } 443 return flagValue; 444 } 445 446 @Override toString()447 public String toString() { 448 // remove com.android.server.display.feature.flags. from the beginning of the name. 449 // align all isEnabled() values. 450 // Adjust lengths if we end up with longer names 451 final int nameLength = mName.length(); 452 return TextUtils.substring(mName, 41, nameLength) + ": " 453 + TextUtils.formatSimple("%" + (93 - nameLength) + "s%s", " " , isEnabled()) 454 + " (def:" + mFlagFunction.get() + ")"; 455 } 456 } 457 } 458