1 /* 2 * Copyright (C) 2019 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.mode; 18 19 import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED; 20 import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE; 21 import static android.os.PowerManager.BRIGHTNESS_INVALID_FLOAT; 22 import static android.view.Display.Mode.INVALID_MODE_ID; 23 24 import static com.android.server.display.DisplayDeviceConfig.DEFAULT_LOW_REFRESH_RATE; 25 26 import android.annotation.IntegerRes; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.res.Resources; 32 import android.database.ContentObserver; 33 import android.hardware.Sensor; 34 import android.hardware.SensorEvent; 35 import android.hardware.SensorEventListener; 36 import android.hardware.SensorManager; 37 import android.hardware.display.BrightnessInfo; 38 import android.hardware.display.DisplayManager; 39 import android.hardware.display.DisplayManagerInternal; 40 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation; 41 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; 42 import android.net.Uri; 43 import android.os.Handler; 44 import android.os.IBinder; 45 import android.os.IThermalEventListener; 46 import android.os.IThermalService; 47 import android.os.Looper; 48 import android.os.Message; 49 import android.os.PowerManager; 50 import android.os.RemoteException; 51 import android.os.ServiceManager; 52 import android.os.SystemClock; 53 import android.os.Temperature; 54 import android.os.UserHandle; 55 import android.provider.DeviceConfig; 56 import android.provider.DeviceConfigInterface; 57 import android.provider.Settings; 58 import android.sysprop.SurfaceFlingerProperties; 59 import android.util.IndentingPrintWriter; 60 import android.util.Pair; 61 import android.util.Slog; 62 import android.util.SparseArray; 63 import android.util.SparseBooleanArray; 64 import android.util.SparseIntArray; 65 import android.view.Display; 66 import android.view.DisplayInfo; 67 import android.view.SurfaceControl; 68 import android.view.SurfaceControl.IdleScreenRefreshRateConfig; 69 import android.view.SurfaceControl.RefreshRateRange; 70 import android.view.SurfaceControl.RefreshRateRanges; 71 72 import com.android.internal.R; 73 import com.android.internal.annotations.GuardedBy; 74 import com.android.internal.annotations.VisibleForTesting; 75 import com.android.internal.display.BrightnessSynchronizer; 76 import com.android.internal.os.BackgroundThread; 77 import com.android.server.LocalServices; 78 import com.android.server.display.DisplayDeviceConfig; 79 import com.android.server.display.config.IdleScreenRefreshRateTimeoutLuxThresholdPoint; 80 import com.android.server.display.config.RefreshRateData; 81 import com.android.server.display.config.SupportedModeData; 82 import com.android.server.display.feature.DeviceConfigParameterProvider; 83 import com.android.server.display.feature.DisplayManagerFlags; 84 import com.android.server.display.utils.AmbientFilter; 85 import com.android.server.display.utils.AmbientFilterFactory; 86 import com.android.server.display.utils.DeviceConfigParsingUtils; 87 import com.android.server.display.utils.SensorUtils; 88 import com.android.server.sensors.SensorManagerInternal; 89 import com.android.server.statusbar.StatusBarManagerInternal; 90 91 import java.io.PrintWriter; 92 import java.text.SimpleDateFormat; 93 import java.util.ArrayList; 94 import java.util.Arrays; 95 import java.util.Date; 96 import java.util.HashSet; 97 import java.util.List; 98 import java.util.Locale; 99 import java.util.Objects; 100 import java.util.Set; 101 import java.util.concurrent.Callable; 102 import java.util.function.Function; 103 import java.util.function.IntSupplier; 104 105 /** 106 * The DisplayModeDirector is responsible for determining what modes are allowed to be automatically 107 * picked by the system based on system-wide and display-specific configuration. 108 */ 109 public class DisplayModeDirector { 110 111 public static final float SYNCHRONIZED_REFRESH_RATE_TARGET = DEFAULT_LOW_REFRESH_RATE; 112 public static final float SYNCHRONIZED_REFRESH_RATE_TOLERANCE = 1; 113 private static final String TAG = "DisplayModeDirector"; 114 private boolean mLoggingEnabled; 115 116 private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1; 117 private static final int MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED = 2; 118 private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3; 119 private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4; 120 private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5; 121 private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6; 122 private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7; 123 private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8; 124 private static final int MSG_SWITCH_USER = 9; 125 126 private final Object mLock = new Object(); 127 private final Context mContext; 128 129 private final DisplayModeDirectorHandler mHandler; 130 private final Injector mInjector; 131 132 private final AppRequestObserver mAppRequestObserver; 133 private final SettingsObserver mSettingsObserver; 134 private final DisplayObserver mDisplayObserver; 135 private final UdfpsObserver mUdfpsObserver; 136 private final ProximitySensorObserver mSensorObserver; 137 private final HbmObserver mHbmObserver; 138 private final SkinThermalStatusObserver mSkinThermalStatusObserver; 139 private final ModeChangeObserver mModeChangeObserver; 140 141 @Nullable 142 private final SystemRequestObserver mSystemRequestObserver; 143 private final DeviceConfigParameterProvider mConfigParameterProvider; 144 private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; 145 146 @GuardedBy("mLock") 147 @Nullable 148 private DisplayDeviceConfig mDefaultDisplayDeviceConfig; 149 150 // A map from the display ID to the supported modes on that display. 151 private SparseArray<Display.Mode[]> mSupportedModesByDisplay; 152 // A map from the display ID to the app supported modes on that display, might be different from 153 // mSupportedModesByDisplay for VRR displays, used in app mode requests. 154 private SparseArray<Display.Mode[]> mAppSupportedModesByDisplay; 155 // A map from the display ID to the default mode of that display. 156 private SparseArray<Display.Mode> mDefaultModeByDisplay; 157 // a map from display id to display device config 158 private SparseArray<DisplayDeviceConfig> mDisplayDeviceConfigByDisplay = new SparseArray<>(); 159 // set containing connected external display ids 160 private final Set<Integer> mExternalDisplaysConnected = new HashSet<>(); 161 162 private SparseBooleanArray mHasArrSupport; 163 164 private BrightnessObserver mBrightnessObserver; 165 166 private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener; 167 168 private boolean mAlwaysRespectAppRequest; 169 170 private final boolean mSupportsFrameRateOverride; 171 172 private final VotesStorage mVotesStorage; 173 174 @Nullable 175 private final VotesStatsReporter mVotesStatsReporter; 176 177 /** 178 * The allowed refresh rate switching type. This is used by SurfaceFlinger. 179 */ 180 @DisplayManager.SwitchingType 181 private int mModeSwitchingType = DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS; 182 183 /** 184 * Whether resolution range voting feature is enabled. 185 */ 186 private final boolean mIsDisplayResolutionRangeVotingEnabled; 187 188 /** 189 * Whether user preferred mode voting feature is enabled. 190 */ 191 private final boolean mIsUserPreferredModeVoteEnabled; 192 193 /** 194 * Whether limit display mode feature is enabled. 195 */ 196 private final boolean mIsExternalDisplayLimitModeEnabled; 197 198 private final boolean mIsDisplaysRefreshRatesSynchronizationEnabled; 199 200 private final boolean mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled; 201 202 private final boolean mHasArrSupportFlagEnabled; 203 204 private final DisplayManagerFlags mDisplayManagerFlags; 205 206 private final DisplayDeviceConfigProvider mDisplayDeviceConfigProvider; 207 DisplayModeDirector(@onNull Context context, @NonNull Handler handler, @NonNull DisplayManagerFlags displayManagerFlags, @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider)208 public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler, 209 @NonNull DisplayManagerFlags displayManagerFlags, 210 @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider) { 211 this(context, handler, new RealInjector(context), 212 displayManagerFlags, displayDeviceConfigProvider); 213 } 214 DisplayModeDirector(@onNull Context context, @NonNull Handler handler, @NonNull Injector injector, @NonNull DisplayManagerFlags displayManagerFlags, @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider)215 public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler, 216 @NonNull Injector injector, 217 @NonNull DisplayManagerFlags displayManagerFlags, 218 @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider) { 219 mIsDisplayResolutionRangeVotingEnabled = displayManagerFlags 220 .isDisplayResolutionRangeVotingEnabled(); 221 mIsUserPreferredModeVoteEnabled = displayManagerFlags.isUserPreferredModeVoteEnabled(); 222 mIsExternalDisplayLimitModeEnabled = displayManagerFlags 223 .isExternalDisplayLimitModeEnabled(); 224 mIsDisplaysRefreshRatesSynchronizationEnabled = displayManagerFlags 225 .isDisplaysRefreshRatesSynchronizationEnabled(); 226 mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled = displayManagerFlags 227 .isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled(); 228 mHasArrSupportFlagEnabled = displayManagerFlags.hasArrSupportFlag(); 229 mDisplayManagerFlags = displayManagerFlags; 230 mDisplayDeviceConfigProvider = displayDeviceConfigProvider; 231 mContext = context; 232 mHandler = new DisplayModeDirectorHandler(handler.getLooper()); 233 mInjector = injector; 234 mVotesStatsReporter = injector.getVotesStatsReporter(); 235 mSupportedModesByDisplay = new SparseArray<>(); 236 mAppSupportedModesByDisplay = new SparseArray<>(); 237 mDefaultModeByDisplay = new SparseArray<>(); 238 mHasArrSupport = new SparseBooleanArray(); 239 mAppRequestObserver = new AppRequestObserver(displayManagerFlags); 240 mConfigParameterProvider = new DeviceConfigParameterProvider(injector.getDeviceConfig()); 241 mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings(); 242 mSettingsObserver = new SettingsObserver(context, handler, displayManagerFlags); 243 mBrightnessObserver = new BrightnessObserver(context, handler, injector, 244 displayManagerFlags); 245 mDefaultDisplayDeviceConfig = null; 246 mUdfpsObserver = new UdfpsObserver(); 247 mVotesStorage = new VotesStorage(this::notifyDesiredDisplayModeSpecsChangedLocked, 248 mVotesStatsReporter); 249 mDisplayObserver = new DisplayObserver(context, handler, mVotesStorage, injector); 250 mSensorObserver = new ProximitySensorObserver(mVotesStorage, injector); 251 mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, mVotesStorage); 252 mModeChangeObserver = new ModeChangeObserver(mVotesStorage, injector, handler.getLooper()); 253 mHbmObserver = new HbmObserver(injector, mVotesStorage, BackgroundThread.getHandler(), 254 mDeviceConfigDisplaySettings); 255 if (displayManagerFlags.isRestrictDisplayModesEnabled()) { 256 mSystemRequestObserver = new SystemRequestObserver(mVotesStorage); 257 } else { 258 mSystemRequestObserver = null; 259 } 260 mAlwaysRespectAppRequest = false; 261 mSupportsFrameRateOverride = injector.supportsFrameRateOverride(); 262 } 263 264 /** 265 * Tells the DisplayModeDirector to update allowed votes and begin observing relevant system 266 * state. 267 * 268 * This has to be deferred because the object may be constructed before the rest of the system 269 * is ready. 270 */ start(SensorManager sensorManager)271 public void start(SensorManager sensorManager) { 272 // This has to be called first to read the supported display modes that will be used by 273 // other observers 274 mDisplayObserver.observe(); 275 276 mSettingsObserver.observe(); 277 mBrightnessObserver.observe(sensorManager); 278 mSensorObserver.observe(); 279 mHbmObserver.observe(); 280 mSkinThermalStatusObserver.observe(); 281 if (mDisplayManagerFlags.isDisplayConfigErrorHalEnabled()) { 282 mModeChangeObserver.observe(); 283 } 284 synchronized (mLock) { 285 // We may have a listener already registered before the call to start, so go ahead and 286 // notify them to pick up our newly initialized state. 287 notifyDesiredDisplayModeSpecsChangedLocked(); 288 } 289 } 290 291 /** 292 * Same as {@link #start(SensorManager)}, but for observers that need to be delayed even more, 293 * for example until SystemUI is ready. 294 */ onBootCompleted()295 public void onBootCompleted() { 296 // UDFPS observer registers a listener with SystemUI which might not be ready until the 297 // system is fully booted. 298 mUdfpsObserver.observe(); 299 } 300 301 /** 302 * Enables or disables component logging 303 */ setLoggingEnabled(boolean loggingEnabled)304 public void setLoggingEnabled(boolean loggingEnabled) { 305 if (mLoggingEnabled == loggingEnabled) { 306 return; 307 } 308 mLoggingEnabled = loggingEnabled; 309 mBrightnessObserver.setLoggingEnabled(loggingEnabled); 310 mSkinThermalStatusObserver.setLoggingEnabled(loggingEnabled); 311 mVotesStorage.setLoggingEnabled(loggingEnabled); 312 } 313 314 /** 315 * Calculates the refresh rate ranges and display modes that the system is allowed to freely 316 * switch between based on global and display-specific constraints. 317 * 318 * @param displayId The display to query for. 319 * @return The ID of the default mode the system should use, and the refresh rate range the 320 * system is allowed to switch between. 321 */ 322 @NonNull getDesiredDisplayModeSpecs(int displayId)323 public DesiredDisplayModeSpecs getDesiredDisplayModeSpecs(int displayId) { 324 synchronized (mLock) { 325 SparseArray<Vote> votes = mVotesStorage.getVotes(displayId); 326 Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); 327 Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId); 328 if (modes == null || defaultMode == null) { 329 Slog.e(TAG, 330 "Asked about unknown display, returning empty display mode specs!" 331 + "(id=" + displayId + ")"); 332 return new DesiredDisplayModeSpecs(); 333 } 334 335 List<Display.Mode> availableModes = new ArrayList<>(); 336 availableModes.add(defaultMode); 337 VoteSummary primarySummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled, 338 isVrrSupportedLocked(displayId), 339 mLoggingEnabled, mSupportsFrameRateOverride); 340 int lowestConsideredPriority = Vote.MIN_PRIORITY; 341 int highestConsideredPriority = Vote.MAX_PRIORITY; 342 343 if (mAlwaysRespectAppRequest) { 344 lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE; 345 highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE; 346 } 347 348 // We try to find a range of priorities which define a non-empty set of allowed display 349 // modes. Each time we fail we increase the lowest priority. 350 while (lowestConsideredPriority <= highestConsideredPriority) { 351 primarySummary.applyVotes( 352 votes, lowestConsideredPriority, highestConsideredPriority); 353 354 primarySummary.adjustSize(defaultMode, modes); 355 356 availableModes = primarySummary.filterModes(modes); 357 if (!availableModes.isEmpty()) { 358 if (mLoggingEnabled) { 359 Slog.w(TAG, "Found available modes=" + availableModes 360 + " with lowest priority considered " 361 + Vote.priorityToString(lowestConsideredPriority) 362 + " and summary: " + primarySummary); 363 } 364 break; 365 } 366 367 if (mLoggingEnabled) { 368 Slog.w(TAG, "Couldn't find available modes with lowest priority set to " 369 + Vote.priorityToString(lowestConsideredPriority) 370 + " and with the following summary: " + primarySummary); 371 } 372 373 // If we haven't found anything with the current set of votes, drop the 374 // current lowest priority vote. 375 lowestConsideredPriority++; 376 } 377 378 VoteSummary appRequestSummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled, 379 isVrrSupportedLocked(displayId), 380 mLoggingEnabled, mSupportsFrameRateOverride); 381 382 appRequestSummary.applyVotes(votes, 383 Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, 384 Vote.MAX_PRIORITY); 385 386 appRequestSummary.limitRefreshRanges(primarySummary); 387 388 Display.Mode baseMode = primarySummary.selectBaseMode(availableModes, defaultMode); 389 if (mVotesStatsReporter != null) { 390 mVotesStatsReporter.reportVotesActivated(displayId, lowestConsideredPriority, 391 baseMode, votes); 392 } 393 394 if (baseMode == null) { 395 Slog.w(TAG, "Can't find a set of allowed modes which satisfies the votes. Falling" 396 + " back to the default mode. Display = " + displayId + ", votes = " + votes 397 + ", supported modes = " + Arrays.toString(modes)); 398 399 float fps = defaultMode.getRefreshRate(); 400 final RefreshRateRange range = new RefreshRateRange(fps, fps); 401 final RefreshRateRanges ranges = new RefreshRateRanges(range, range); 402 return new DesiredDisplayModeSpecs(defaultMode.getModeId(), 403 /*allowGroupSwitching */ false, 404 ranges, ranges, mBrightnessObserver.getIdleScreenRefreshRateConfig()); 405 } 406 407 boolean modeSwitchingDisabled = 408 mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE 409 || mModeSwitchingType 410 == DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY; 411 412 if (modeSwitchingDisabled || primarySummary.disableRefreshRateSwitching) { 413 float fps = baseMode.getRefreshRate(); 414 primarySummary.disableModeSwitching(fps); 415 if (modeSwitchingDisabled) { 416 appRequestSummary.disableModeSwitching(fps); 417 primarySummary.disableRenderRateSwitching(fps); 418 if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) { 419 appRequestSummary.disableRenderRateSwitching(fps); 420 } 421 } 422 } 423 424 boolean allowGroupSwitching = 425 mModeSwitchingType == DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; 426 427 // Some external displays physical refresh rate modes are slightly above 60hz. 428 // SurfaceFlinger will not enable these display modes unless it is configured to allow 429 // render rate at least at this frame rate. 430 if (isExternalDisplayLocked(displayId)) { 431 primarySummary.maxRenderFrameRate = Math.max(baseMode.getRefreshRate(), 432 primarySummary.maxRenderFrameRate); 433 appRequestSummary.maxRenderFrameRate = Math.max(baseMode.getRefreshRate(), 434 appRequestSummary.maxRenderFrameRate); 435 } 436 437 return new DesiredDisplayModeSpecs(baseMode.getModeId(), 438 allowGroupSwitching, 439 new RefreshRateRanges( 440 new RefreshRateRange( 441 primarySummary.minPhysicalRefreshRate, 442 primarySummary.maxPhysicalRefreshRate), 443 new RefreshRateRange( 444 primarySummary.minRenderFrameRate, 445 primarySummary.maxRenderFrameRate)), 446 new RefreshRateRanges( 447 new RefreshRateRange( 448 appRequestSummary.minPhysicalRefreshRate, 449 appRequestSummary.maxPhysicalRefreshRate), 450 new RefreshRateRange( 451 appRequestSummary.minRenderFrameRate, 452 appRequestSummary.maxRenderFrameRate)), 453 mBrightnessObserver.getIdleScreenRefreshRateConfig()); 454 } 455 } 456 457 /** 458 * Gets the observer responsible for application display mode requests. 459 */ 460 @NonNull getAppRequestObserver()461 public AppRequestObserver getAppRequestObserver() { 462 // We don't need to lock here because mAppRequestObserver is a final field, which is 463 // guaranteed to be visible on all threads after construction. 464 return mAppRequestObserver; 465 } 466 467 // TODO(b/372019752) Rename all the occurrences of the VRR with ARR. isVrrSupportedLocked(int displayId)468 private boolean isVrrSupportedLocked(int displayId) { 469 if (mHasArrSupportFlagEnabled) { 470 Boolean hasArrSupport = mHasArrSupport.get(displayId); 471 return hasArrSupport != null && hasArrSupport; 472 } 473 // TODO(b/371041638) Remove config.isVrrSupportEnabled once hasArrSupport is rolled out 474 DisplayDeviceConfig config = mDisplayDeviceConfigByDisplay.get(displayId); 475 return config != null && config.isVrrSupportEnabled(); 476 } 477 478 /** 479 * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate ranges. 480 */ setDesiredDisplayModeSpecsListener( @ullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener)481 public void setDesiredDisplayModeSpecsListener( 482 @Nullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener) { 483 synchronized (mLock) { 484 mDesiredDisplayModeSpecsListener = desiredDisplayModeSpecsListener; 485 } 486 } 487 488 /** 489 * Called when the underlying display device of the default display is changed. 490 * Some data in this class relates to the physical display of the device, and so we need to 491 * reload the configurations based on this. 492 * E.g. the brightness sensors and refresh rate capabilities depend on the physical display 493 * device that is being used, so will be reloaded. 494 * 495 * @param displayDeviceConfig configurations relating to the underlying display device. 496 */ defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig)497 public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) { 498 synchronized (mLock) { 499 mDefaultDisplayDeviceConfig = displayDeviceConfig; 500 mSettingsObserver.setRefreshRates(displayDeviceConfig, 501 /* attemptReadFromFeatureParams= */ true); 502 mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig, 503 /* attemptReadFromFeatureParams= */ true); 504 mBrightnessObserver.loadIdleScreenRefreshRateConfigs(displayDeviceConfig); 505 mBrightnessObserver.reloadLightSensor(displayDeviceConfig); 506 mHbmObserver.setupHdrRefreshRates(displayDeviceConfig); 507 } 508 } 509 510 /** 511 * When enabled the app requested display mode is always selected and all 512 * other votes will be ignored. This is used for testing purposes. 513 */ setShouldAlwaysRespectAppRequestedMode(boolean enabled)514 public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { 515 synchronized (mLock) { 516 if (mAlwaysRespectAppRequest != enabled) { 517 mAlwaysRespectAppRequest = enabled; 518 notifyDesiredDisplayModeSpecsChangedLocked(); 519 } 520 } 521 } 522 523 /** 524 * Returns whether we are running in a mode which always selects the app requested display mode 525 * and ignores user settings and policies for low brightness, low battery etc. 526 */ shouldAlwaysRespectAppRequestedMode()527 public boolean shouldAlwaysRespectAppRequestedMode() { 528 synchronized (mLock) { 529 return mAlwaysRespectAppRequest; 530 } 531 } 532 533 /** 534 * Sets the display mode switching type. 535 * @param newType new mode switching type 536 */ setModeSwitchingType(@isplayManager.SwitchingType int newType)537 public void setModeSwitchingType(@DisplayManager.SwitchingType int newType) { 538 synchronized (mLock) { 539 if (newType != mModeSwitchingType) { 540 mModeSwitchingType = newType; 541 notifyDesiredDisplayModeSpecsChangedLocked(); 542 } 543 } 544 } 545 546 /** 547 * Returns the display mode switching type. 548 */ 549 @DisplayManager.SwitchingType getModeSwitchingType()550 public int getModeSwitchingType() { 551 synchronized (mLock) { 552 return mModeSwitchingType; 553 } 554 } 555 556 /** 557 * Retrieve the Vote for the given display and priority. Intended only for testing purposes. 558 * 559 * @param displayId the display to query for 560 * @param priority the priority of the vote to return 561 * @return the vote corresponding to the given {@code displayId} and {@code priority}, 562 * or {@code null} if there isn't one 563 */ 564 @VisibleForTesting 565 @Nullable getVote(int displayId, int priority)566 Vote getVote(int displayId, int priority) { 567 SparseArray<Vote> votes = mVotesStorage.getVotes(displayId); 568 return votes.get(priority); 569 } 570 571 /** 572 * Delegates requestDisplayModes call to SystemRequestObserver 573 */ requestDisplayModes(IBinder token, int displayId, int[] modeIds)574 public void requestDisplayModes(IBinder token, int displayId, int[] modeIds) { 575 if (mSystemRequestObserver != null) { 576 boolean vrrSupported; 577 synchronized (mLock) { 578 vrrSupported = isVrrSupportedLocked(displayId); 579 } 580 if (vrrSupported) { 581 mSystemRequestObserver.requestDisplayModes(token, displayId, modeIds); 582 } 583 } 584 } 585 586 /** 587 * Called when the user switches. 588 */ onSwitchUser()589 public void onSwitchUser() { 590 mHandler.obtainMessage(MSG_SWITCH_USER).sendToTarget(); 591 } 592 593 /** 594 * Print the object's state and debug information into the given stream. 595 * 596 * @param pw The stream to dump information to. 597 */ dump(PrintWriter pw)598 public void dump(PrintWriter pw) { 599 pw.println("DisplayModeDirector:"); 600 pw.println("--------------------"); 601 synchronized (mLock) { 602 pw.println(" mSupportedModesByDisplay:"); 603 for (int i = 0; i < mSupportedModesByDisplay.size(); i++) { 604 final int id = mSupportedModesByDisplay.keyAt(i); 605 final Display.Mode[] modes = mSupportedModesByDisplay.valueAt(i); 606 pw.println(" " + id + " -> " + Arrays.toString(modes)); 607 } 608 pw.println(" mAppSupportedModesByDisplay:"); 609 for (int i = 0; i < mAppSupportedModesByDisplay.size(); i++) { 610 final int id = mAppSupportedModesByDisplay.keyAt(i); 611 final Display.Mode[] modes = mAppSupportedModesByDisplay.valueAt(i); 612 pw.println(" " + id + " -> " + Arrays.toString(modes)); 613 } 614 pw.println(" mDefaultModeByDisplay:"); 615 for (int i = 0; i < mDefaultModeByDisplay.size(); i++) { 616 final int id = mDefaultModeByDisplay.keyAt(i); 617 final Display.Mode mode = mDefaultModeByDisplay.valueAt(i); 618 pw.println(" " + id + " -> " + mode); 619 } 620 pw.println(" mModeSwitchingType: " + switchingTypeToString(mModeSwitchingType)); 621 pw.println(" mAlwaysRespectAppRequest: " + mAlwaysRespectAppRequest); 622 mSettingsObserver.dumpLocked(pw); 623 mAppRequestObserver.dumpLocked(pw); 624 mBrightnessObserver.dumpLocked(pw); 625 mUdfpsObserver.dumpLocked(pw); 626 mHbmObserver.dumpLocked(pw); 627 mSkinThermalStatusObserver.dumpLocked(pw); 628 } 629 mVotesStorage.dump(pw); 630 mSensorObserver.dump(pw); 631 } 632 633 @GuardedBy("mLock") getMaxRefreshRateLocked(int displayId)634 private float getMaxRefreshRateLocked(int displayId) { 635 Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); 636 float maxRefreshRate = 0f; 637 for (Display.Mode mode : modes) { 638 if (mode.getRefreshRate() > maxRefreshRate) { 639 maxRefreshRate = mode.getRefreshRate(); 640 } 641 } 642 return maxRefreshRate; 643 } 644 notifyDesiredDisplayModeSpecsChangedLocked()645 private void notifyDesiredDisplayModeSpecsChangedLocked() { 646 if (mDesiredDisplayModeSpecsListener != null 647 && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) { 648 // We need to post this to a handler to avoid calling out while holding the lock 649 // since we know there are things that both listen for changes as well as provide 650 // information. If we did call out while holding the lock, then there's no 651 // guaranteed lock order and we run the real of risk deadlock. 652 Message msg = mHandler.obtainMessage( 653 MSG_REFRESH_RATE_RANGE_CHANGED, mDesiredDisplayModeSpecsListener); 654 msg.sendToTarget(); 655 } 656 } 657 isExternalDisplayLocked(int displayId)658 boolean isExternalDisplayLocked(int displayId) { 659 return mExternalDisplaysConnected.contains(displayId); 660 } 661 switchingTypeToString(@isplayManager.SwitchingType int type)662 private static String switchingTypeToString(@DisplayManager.SwitchingType int type) { 663 switch (type) { 664 case DisplayManager.SWITCHING_TYPE_NONE: 665 return "SWITCHING_TYPE_NONE"; 666 case DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS: 667 return "SWITCHING_TYPE_WITHIN_GROUPS"; 668 case DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS: 669 return "SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS"; 670 case DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY: 671 return "SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY"; 672 default: 673 return "Unknown SwitchingType " + type; 674 } 675 } 676 677 @VisibleForTesting injectSupportedModesByDisplay(SparseArray<Display.Mode[]> supportedModesByDisplay)678 void injectSupportedModesByDisplay(SparseArray<Display.Mode[]> supportedModesByDisplay) { 679 mSupportedModesByDisplay = supportedModesByDisplay; 680 } 681 682 @VisibleForTesting injectAppSupportedModesByDisplay(SparseArray<Display.Mode[]> appSupportedModesByDisplay)683 void injectAppSupportedModesByDisplay(SparseArray<Display.Mode[]> appSupportedModesByDisplay) { 684 mAppSupportedModesByDisplay = appSupportedModesByDisplay; 685 } 686 687 @VisibleForTesting injectDefaultModeByDisplay(SparseArray<Display.Mode> defaultModeByDisplay)688 void injectDefaultModeByDisplay(SparseArray<Display.Mode> defaultModeByDisplay) { 689 mDefaultModeByDisplay = defaultModeByDisplay; 690 } 691 692 @VisibleForTesting injectDisplayDeviceConfigByDisplay(SparseArray<DisplayDeviceConfig> ddcByDisplay)693 void injectDisplayDeviceConfigByDisplay(SparseArray<DisplayDeviceConfig> ddcByDisplay) { 694 mDisplayDeviceConfigByDisplay = ddcByDisplay; 695 } 696 697 @VisibleForTesting injectVotesByDisplay(SparseArray<SparseArray<Vote>> votesByDisplay)698 void injectVotesByDisplay(SparseArray<SparseArray<Vote>> votesByDisplay) { 699 mVotesStorage.injectVotesByDisplay(votesByDisplay); 700 } 701 702 @VisibleForTesting addExternalDisplayId(int externalDisplayId)703 void addExternalDisplayId(int externalDisplayId) { 704 mExternalDisplaysConnected.add(externalDisplayId); 705 } 706 707 @VisibleForTesting injectBrightnessObserver(BrightnessObserver brightnessObserver)708 void injectBrightnessObserver(BrightnessObserver brightnessObserver) { 709 mBrightnessObserver = brightnessObserver; 710 } 711 712 @VisibleForTesting getBrightnessObserver()713 BrightnessObserver getBrightnessObserver() { 714 return mBrightnessObserver; 715 } 716 717 @VisibleForTesting getSettingsObserver()718 SettingsObserver getSettingsObserver() { 719 return mSettingsObserver; 720 } 721 722 @VisibleForTesting getUdpfsObserver()723 UdfpsObserver getUdpfsObserver() { 724 return mUdfpsObserver; 725 } 726 727 @VisibleForTesting getHbmObserver()728 HbmObserver getHbmObserver() { 729 return mHbmObserver; 730 } 731 732 @VisibleForTesting getDisplayObserver()733 DisplayObserver getDisplayObserver() { 734 return mDisplayObserver; 735 } 736 737 @VisibleForTesting getDesiredDisplayModeSpecsWithInjectedFpsSettings( float minRefreshRate, float peakRefreshRate, float defaultRefreshRate)738 DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings( 739 float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) { 740 synchronized (mLock) { 741 mSettingsObserver.updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, 742 defaultRefreshRate, Display.DEFAULT_DISPLAY); 743 return getDesiredDisplayModeSpecs(Display.DEFAULT_DISPLAY); 744 } 745 } 746 747 /** 748 * Provides access to DisplayDeviceConfig for specific display 749 */ 750 public interface DisplayDeviceConfigProvider { 751 /** 752 * Returns DisplayDeviceConfig for specific display 753 */ getDisplayDeviceConfig(int displayId)754 @Nullable DisplayDeviceConfig getDisplayDeviceConfig(int displayId); 755 } 756 757 /** 758 * Listens for changes refresh rate coordination. 759 */ 760 public interface DesiredDisplayModeSpecsListener { 761 /** 762 * Called when the refresh rate range may have changed. 763 */ onDesiredDisplayModeSpecsChanged()764 void onDesiredDisplayModeSpecsChanged(); 765 } 766 767 private final class DisplayModeDirectorHandler extends Handler { DisplayModeDirectorHandler(Looper looper)768 DisplayModeDirectorHandler(Looper looper) { 769 super(looper, null, true /*async*/); 770 } 771 772 @Override handleMessage(Message msg)773 public void handleMessage(Message msg) { 774 switch (msg.what) { 775 case MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED: { 776 Pair<float[], float[]> thresholds = (Pair<float[], float[]>) msg.obj; 777 mBrightnessObserver.onDeviceConfigLowBrightnessThresholdsChanged( 778 thresholds.first, thresholds.second); 779 break; 780 } 781 782 case MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED: { 783 int refreshRateInZone = msg.arg1; 784 mBrightnessObserver.onDeviceConfigRefreshRateInLowZoneChanged( 785 refreshRateInZone); 786 break; 787 } 788 789 case MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED: { 790 Pair<float[], float[]> thresholds = (Pair<float[], float[]>) msg.obj; 791 792 mBrightnessObserver.onDeviceConfigHighBrightnessThresholdsChanged( 793 thresholds.first, thresholds.second); 794 795 break; 796 } 797 798 case MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED: { 799 int refreshRateInZone = msg.arg1; 800 mBrightnessObserver.onDeviceConfigRefreshRateInHighZoneChanged( 801 refreshRateInZone); 802 break; 803 } 804 805 case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED: 806 Float defaultPeakRefreshRate = (Float) msg.obj; 807 mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged( 808 defaultPeakRefreshRate); 809 break; 810 811 case MSG_REFRESH_RATE_RANGE_CHANGED: 812 DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener = 813 (DesiredDisplayModeSpecsListener) msg.obj; 814 desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged(); 815 break; 816 817 case MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED: { 818 int refreshRateInHbmSunlight = msg.arg1; 819 mHbmObserver.onDeviceConfigRefreshRateInHbmSunlightChanged( 820 refreshRateInHbmSunlight); 821 break; 822 } 823 824 case MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED: { 825 int refreshRateInHbmHdr = msg.arg1; 826 mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr); 827 break; 828 } 829 830 case MSG_SWITCH_USER: { 831 synchronized (mLock) { 832 mSettingsObserver.updateRefreshRateSettingLocked(); 833 mSettingsObserver.updateModeSwitchingTypeSettingLocked(); 834 } 835 } 836 } 837 } 838 } 839 840 /** 841 * Information about the desired display mode to be set by the system. Includes the base 842 * mode ID and the primary and app request refresh rate ranges. 843 * 844 * We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the 845 * distinction between the config ID / physical index that 846 * SurfaceControl.DesiredDisplayConfigSpecs uses, and the mode ID used here. 847 */ 848 public static final class DesiredDisplayModeSpecs { 849 850 /** 851 * Base mode ID. This is what system defaults to for all other settings, or 852 * if the refresh rate range is not available. 853 */ 854 public int baseModeId; 855 856 /** 857 * If true this will allow switching between modes in different display configuration 858 * groups. This way the user may see visual interruptions when the display mode changes. 859 */ 860 public boolean allowGroupSwitching; 861 862 /** 863 * Represents the idle time of the screen after which the associated display's refresh rate 864 * is to be reduced to preserve power 865 * Defaults to null, meaning that the device is not configured to have a timeout based on 866 * the surrounding conditions 867 * -1 means that the current conditions require no timeout 868 */ 869 @Nullable 870 public IdleScreenRefreshRateConfig mIdleScreenRefreshRateConfig; 871 872 /** 873 * The primary refresh rate ranges. 874 */ 875 public final RefreshRateRanges primary; 876 /** 877 * The app request refresh rate ranges. Lower priority considerations won't be included in 878 * this range, allowing SurfaceFlinger to consider additional refresh rates for apps that 879 * call setFrameRate(). This range will be greater than or equal to the primary refresh rate 880 * range, never smaller. 881 */ 882 public final RefreshRateRanges appRequest; 883 DesiredDisplayModeSpecs()884 public DesiredDisplayModeSpecs() { 885 primary = new RefreshRateRanges(); 886 appRequest = new RefreshRateRanges(); 887 } 888 DesiredDisplayModeSpecs(int baseModeId, boolean allowGroupSwitching, @NonNull RefreshRateRanges primary, @NonNull RefreshRateRanges appRequest, @Nullable SurfaceControl.IdleScreenRefreshRateConfig idleScreenRefreshRateConfig)889 public DesiredDisplayModeSpecs(int baseModeId, 890 boolean allowGroupSwitching, 891 @NonNull RefreshRateRanges primary, 892 @NonNull RefreshRateRanges appRequest, 893 @Nullable SurfaceControl.IdleScreenRefreshRateConfig idleScreenRefreshRateConfig) { 894 this.baseModeId = baseModeId; 895 this.allowGroupSwitching = allowGroupSwitching; 896 this.primary = primary; 897 this.appRequest = appRequest; 898 this.mIdleScreenRefreshRateConfig = idleScreenRefreshRateConfig; 899 } 900 901 /** 902 * Returns a string representation of the object. 903 */ 904 @Override toString()905 public String toString() { 906 return String.format("baseModeId=%d allowGroupSwitching=%b" 907 + " primary=%s" 908 + " appRequest=%s" 909 + " idleScreenRefreshRateConfig=%s", 910 baseModeId, allowGroupSwitching, primary.toString(), 911 appRequest.toString(), String.valueOf(mIdleScreenRefreshRateConfig)); 912 } 913 914 /** 915 * Checks whether the two objects have the same values. 916 */ 917 @Override equals(Object other)918 public boolean equals(Object other) { 919 if (other == this) { 920 return true; 921 } 922 923 if (!(other instanceof DesiredDisplayModeSpecs)) { 924 return false; 925 } 926 927 DesiredDisplayModeSpecs desiredDisplayModeSpecs = (DesiredDisplayModeSpecs) other; 928 929 if (baseModeId != desiredDisplayModeSpecs.baseModeId) { 930 return false; 931 } 932 if (allowGroupSwitching != desiredDisplayModeSpecs.allowGroupSwitching) { 933 return false; 934 } 935 if (!primary.equals(desiredDisplayModeSpecs.primary)) { 936 return false; 937 } 938 if (!appRequest.equals( 939 desiredDisplayModeSpecs.appRequest)) { 940 return false; 941 } 942 943 if (!Objects.equals(mIdleScreenRefreshRateConfig, 944 desiredDisplayModeSpecs.mIdleScreenRefreshRateConfig)) { 945 return false; 946 } 947 return true; 948 } 949 950 @Override hashCode()951 public int hashCode() { 952 return Objects.hash(baseModeId, allowGroupSwitching, primary, appRequest, 953 mIdleScreenRefreshRateConfig); 954 } 955 956 /** 957 * Copy values from the other object. 958 */ copyFrom(DesiredDisplayModeSpecs other)959 public void copyFrom(DesiredDisplayModeSpecs other) { 960 baseModeId = other.baseModeId; 961 allowGroupSwitching = other.allowGroupSwitching; 962 primary.physical.min = other.primary.physical.min; 963 primary.physical.max = other.primary.physical.max; 964 primary.render.min = other.primary.render.min; 965 primary.render.max = other.primary.render.max; 966 967 appRequest.physical.min = other.appRequest.physical.min; 968 appRequest.physical.max = other.appRequest.physical.max; 969 appRequest.render.min = other.appRequest.render.min; 970 appRequest.render.max = other.appRequest.render.max; 971 972 if (other.mIdleScreenRefreshRateConfig == null) { 973 mIdleScreenRefreshRateConfig = null; 974 } else { 975 mIdleScreenRefreshRateConfig = 976 new IdleScreenRefreshRateConfig( 977 other.mIdleScreenRefreshRateConfig.timeoutMillis); 978 } 979 } 980 } 981 982 @VisibleForTesting 983 final class SettingsObserver extends ContentObserver { 984 private final Uri mPeakRefreshRateSetting = 985 Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); 986 private final Uri mMinRefreshRateSetting = 987 Settings.System.getUriFor(Settings.System.MIN_REFRESH_RATE); 988 private final Uri mLowPowerModeSetting = 989 Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE); 990 private final Uri mMatchContentFrameRateSetting = 991 Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE); 992 993 private final boolean mVsyncLowPowerVoteEnabled; 994 private final boolean mPeakRefreshRatePhysicalLimitEnabled; 995 996 private final Context mContext; 997 private final Handler mHandler; 998 private float mDefaultPeakRefreshRate; 999 private float mDefaultRefreshRate; 1000 private boolean mIsLowPower = false; 1001 1002 private final DisplayManager.DisplayListener mDisplayListener = 1003 new DisplayManager.DisplayListener() { 1004 @Override 1005 public void onDisplayAdded(int displayId) { 1006 synchronized (mLock) { 1007 updateLowPowerModeAllowedModesLocked(); 1008 } 1009 } 1010 1011 @Override 1012 public void onDisplayRemoved(int displayId) { 1013 mVotesStorage.updateVote(displayId, Vote.PRIORITY_LOW_POWER_MODE_MODES, 1014 null); 1015 } 1016 1017 @Override 1018 public void onDisplayChanged(int displayId) { 1019 synchronized (mLock) { 1020 updateLowPowerModeAllowedModesLocked(); 1021 } 1022 } 1023 }; 1024 SettingsObserver(@onNull Context context, @NonNull Handler handler, DisplayManagerFlags flags)1025 SettingsObserver(@NonNull Context context, @NonNull Handler handler, 1026 DisplayManagerFlags flags) { 1027 super(handler); 1028 mContext = context; 1029 mHandler = handler; 1030 mVsyncLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled(); 1031 mPeakRefreshRatePhysicalLimitEnabled = flags.isPeakRefreshRatePhysicalLimitEnabled(); 1032 // We don't want to load from the DeviceConfig while constructing since this leads to 1033 // a spike in the latency of DisplayManagerService startup. This happens because 1034 // reading from the DeviceConfig is an intensive IO operation and having it in the 1035 // startup phase where we thrive to keep the latency very low has significant impact. 1036 setRefreshRates(/* displayDeviceConfig= */ null, 1037 /* attemptReadFromFeatureParams= */ false); 1038 } 1039 1040 /** 1041 * This is used to update the refresh rate configs from the DeviceConfig, which 1042 * if missing from DisplayDeviceConfig, and finally fallback to config.xml. 1043 */ setRefreshRates(DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1044 void setRefreshRates(DisplayDeviceConfig displayDeviceConfig, 1045 boolean attemptReadFromFeatureParams) { 1046 RefreshRateData refreshRateData = displayDeviceConfig == null ? null 1047 : displayDeviceConfig.getRefreshRateData(); 1048 setDefaultPeakRefreshRate(displayDeviceConfig, attemptReadFromFeatureParams); 1049 mDefaultRefreshRate = 1050 (refreshRateData == null) ? (float) mContext.getResources().getInteger( 1051 R.integer.config_defaultRefreshRate) 1052 : (float) refreshRateData.defaultRefreshRate; 1053 } 1054 observe()1055 public void observe() { 1056 final ContentResolver cr = mContext.getContentResolver(); 1057 mInjector.registerPeakRefreshRateObserver(cr, this); 1058 mInjector.registerMinRefreshRateObserver(cr, this); 1059 cr.registerContentObserver(mLowPowerModeSetting, /* notifyDescendants= */ false, this, 1060 UserHandle.USER_ALL); 1061 cr.registerContentObserver(mMatchContentFrameRateSetting, 1062 /* notifyDescendants= */ false, this, UserHandle.USER_ALL); 1063 mInjector.registerDisplayListener(mDisplayListener, mHandler); 1064 1065 float deviceConfigDefaultPeakRefresh = 1066 mConfigParameterProvider.getPeakRefreshRateDefault(); 1067 if (deviceConfigDefaultPeakRefresh != -1) { 1068 mDefaultPeakRefreshRate = deviceConfigDefaultPeakRefresh; 1069 } 1070 1071 synchronized (mLock) { 1072 updateRefreshRateSettingLocked(); 1073 updateLowPowerModeSettingLocked(); 1074 updateModeSwitchingTypeSettingLocked(); 1075 } 1076 1077 } 1078 setDefaultRefreshRate(float refreshRate)1079 public void setDefaultRefreshRate(float refreshRate) { 1080 synchronized (mLock) { 1081 mDefaultRefreshRate = refreshRate; 1082 updateRefreshRateSettingLocked(); 1083 } 1084 } 1085 onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate)1086 public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) { 1087 synchronized (mLock) { 1088 if (defaultPeakRefreshRate == null) { 1089 setDefaultPeakRefreshRate(mDefaultDisplayDeviceConfig, 1090 /* attemptReadFromFeatureParams= */ false); 1091 } else if (mDefaultPeakRefreshRate != defaultPeakRefreshRate) { 1092 mDefaultPeakRefreshRate = defaultPeakRefreshRate; 1093 } 1094 updateRefreshRateSettingLocked(); 1095 } 1096 } 1097 1098 @Override onChange(boolean selfChange, Uri uri, int userId)1099 public void onChange(boolean selfChange, Uri uri, int userId) { 1100 synchronized (mLock) { 1101 if (mPeakRefreshRateSetting.equals(uri) || mMinRefreshRateSetting.equals(uri)) { 1102 updateRefreshRateSettingLocked(); 1103 } else if (mLowPowerModeSetting.equals(uri)) { 1104 updateLowPowerModeSettingLocked(); 1105 } else if (mMatchContentFrameRateSetting.equals(uri)) { 1106 updateModeSwitchingTypeSettingLocked(); 1107 } 1108 } 1109 } 1110 1111 @VisibleForTesting getDefaultRefreshRate()1112 float getDefaultRefreshRate() { 1113 return mDefaultRefreshRate; 1114 } 1115 1116 @VisibleForTesting getDefaultPeakRefreshRate()1117 float getDefaultPeakRefreshRate() { 1118 return mDefaultPeakRefreshRate; 1119 } 1120 setDefaultPeakRefreshRate(DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1121 private void setDefaultPeakRefreshRate(DisplayDeviceConfig displayDeviceConfig, 1122 boolean attemptReadFromFeatureParams) { 1123 float defaultPeakRefreshRate = -1; 1124 1125 if (attemptReadFromFeatureParams) { 1126 try { 1127 defaultPeakRefreshRate = mConfigParameterProvider.getPeakRefreshRateDefault(); 1128 } catch (Exception exception) { 1129 // Do nothing 1130 } 1131 } 1132 if (defaultPeakRefreshRate == -1) { 1133 defaultPeakRefreshRate = 1134 (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger( 1135 R.integer.config_defaultPeakRefreshRate) 1136 : (float) displayDeviceConfig.getRefreshRateData() 1137 .defaultPeakRefreshRate; 1138 } 1139 mDefaultPeakRefreshRate = defaultPeakRefreshRate; 1140 } 1141 updateLowPowerModeSettingLocked()1142 private void updateLowPowerModeSettingLocked() { 1143 mIsLowPower = Settings.Global.getInt(mContext.getContentResolver(), 1144 Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0; 1145 final Vote vote; 1146 if (mIsLowPower) { 1147 vote = Vote.forRenderFrameRates(0f, 60f); 1148 } else { 1149 vote = null; 1150 } 1151 mVotesStorage.updateGlobalVote(Vote.PRIORITY_LOW_POWER_MODE_RENDER_RATE, vote); 1152 mBrightnessObserver.onLowPowerModeEnabledLocked(mIsLowPower); 1153 updateLowPowerModeAllowedModesLocked(); 1154 } 1155 updateLowPowerModeAllowedModesLocked()1156 private void updateLowPowerModeAllowedModesLocked() { 1157 if (!mVsyncLowPowerVoteEnabled) { 1158 return; 1159 } 1160 if (mIsLowPower) { 1161 for (int i = 0; i < mDisplayDeviceConfigByDisplay.size(); i++) { 1162 DisplayDeviceConfig config = mDisplayDeviceConfigByDisplay.valueAt(i); 1163 if (config == null) { 1164 continue; 1165 } 1166 List<SupportedModeData> supportedModes = config 1167 .getRefreshRateData().lowPowerSupportedModes; 1168 mVotesStorage.updateVote( 1169 mDisplayDeviceConfigByDisplay.keyAt(i), 1170 Vote.PRIORITY_LOW_POWER_MODE_MODES, 1171 Vote.forSupportedRefreshRates(supportedModes)); 1172 } 1173 } else { 1174 mVotesStorage.removeAllVotesForPriority(Vote.PRIORITY_LOW_POWER_MODE_MODES); 1175 } 1176 } 1177 1178 /** 1179 * Update refresh rate settings for all displays 1180 */ 1181 @GuardedBy("mLock") updateRefreshRateSettingLocked()1182 private void updateRefreshRateSettingLocked() { 1183 for (int i = 0; i < mSupportedModesByDisplay.size(); i++) { 1184 updateRefreshRateSettingLocked(mSupportedModesByDisplay.keyAt(i)); 1185 } 1186 } 1187 1188 /** 1189 * Update refresh rate settings for a specific display 1190 * @param displayId The display ID 1191 */ 1192 @GuardedBy("mLock") updateRefreshRateSettingLocked(int displayId)1193 private void updateRefreshRateSettingLocked(int displayId) { 1194 final ContentResolver cr = mContext.getContentResolver(); 1195 if (!mSupportedModesByDisplay.contains(displayId)) { 1196 Slog.e(TAG, "Cannot update refresh rate setting: no supported modes for display " 1197 + displayId); 1198 return; 1199 } 1200 float highestRefreshRate = getMaxRefreshRateLocked(displayId); 1201 1202 float minRefreshRate = Settings.System.getFloatForUser(cr, 1203 Settings.System.MIN_REFRESH_RATE, 0f, UserHandle.USER_CURRENT); 1204 if (Float.isInfinite(minRefreshRate)) { 1205 // Infinity means that we want the highest possible refresh rate 1206 minRefreshRate = highestRefreshRate; 1207 } 1208 1209 float peakRefreshRate = Settings.System.getFloatForUser(cr, 1210 Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, 1211 UserHandle.USER_CURRENT); 1212 if (Float.isInfinite(peakRefreshRate)) { 1213 // Infinity means that we want the highest possible refresh rate 1214 peakRefreshRate = highestRefreshRate; 1215 } 1216 1217 updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate, 1218 displayId); 1219 } 1220 1221 @GuardedBy("mLock") updateRefreshRateSettingLocked(float minRefreshRate, float peakRefreshRate, float defaultRefreshRate, int displayId)1222 private void updateRefreshRateSettingLocked(float minRefreshRate, float peakRefreshRate, 1223 float defaultRefreshRate, int displayId) { 1224 if (isExternalDisplayLocked(displayId)) { 1225 if (mLoggingEnabled) { 1226 Slog.d(TAG, "skip updateRefreshRateSettingLocked for external display " 1227 + displayId); 1228 } 1229 return; 1230 } 1231 // TODO(b/156304339): The logic in here, aside from updating the refresh rate votes, is 1232 // used to predict if we're going to be doing frequent refresh rate switching, and if 1233 // so, enable the brightness observer. The logic here is more complicated and fragile 1234 // than necessary, and we should improve it. See b/156304339 for more info. 1235 if (mPeakRefreshRatePhysicalLimitEnabled) { 1236 Vote peakVote = peakRefreshRate == 0f 1237 ? null 1238 : Vote.forPhysicalRefreshRates(0f, 1239 Math.max(minRefreshRate, peakRefreshRate)); 1240 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, 1241 peakVote); 1242 } 1243 Vote peakRenderVote = peakRefreshRate == 0f 1244 ? null 1245 : Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate)); 1246 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 1247 peakRenderVote); 1248 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1249 Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY)); 1250 Vote defaultVote = 1251 defaultRefreshRate == 0f 1252 ? null : Vote.forRenderFrameRates(0f, defaultRefreshRate); 1253 mVotesStorage.updateGlobalVote(Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE, defaultVote); 1254 1255 float maxRefreshRate; 1256 if (peakRefreshRate == 0f && defaultRefreshRate == 0f) { 1257 // We require that at least one of the peak or default refresh rate values are 1258 // set. The brightness observer requires that we're able to predict whether or not 1259 // we're going to do frequent refresh rate switching, and with the way the code is 1260 // currently written, we need either a default or peak refresh rate value for that. 1261 Slog.e(TAG, "Default and peak refresh rates are both 0. One of them should be set" 1262 + " to a valid value."); 1263 maxRefreshRate = minRefreshRate; 1264 } else if (peakRefreshRate == 0f) { 1265 maxRefreshRate = defaultRefreshRate; 1266 } else if (defaultRefreshRate == 0f) { 1267 maxRefreshRate = peakRefreshRate; 1268 } else { 1269 maxRefreshRate = Math.min(defaultRefreshRate, peakRefreshRate); 1270 } 1271 1272 // TODO(b/310237068): Make this work for multiple displays 1273 if (displayId == Display.DEFAULT_DISPLAY) { 1274 mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, 1275 maxRefreshRate); 1276 } 1277 } 1278 removeRefreshRateSetting(int displayId)1279 private void removeRefreshRateSetting(int displayId) { 1280 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, 1281 null); 1282 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 1283 null); 1284 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1285 null); 1286 mVotesStorage.updateVote(displayId, Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE, null); 1287 } 1288 updateModeSwitchingTypeSettingLocked()1289 private void updateModeSwitchingTypeSettingLocked() { 1290 final ContentResolver cr = mContext.getContentResolver(); 1291 int switchingType = Settings.Secure.getIntForUser(cr, 1292 Settings.Secure.MATCH_CONTENT_FRAME_RATE, /* default= */ mModeSwitchingType, 1293 UserHandle.USER_CURRENT); 1294 if (switchingType != mModeSwitchingType) { 1295 mModeSwitchingType = switchingType; 1296 notifyDesiredDisplayModeSpecsChangedLocked(); 1297 } 1298 } 1299 dumpLocked(PrintWriter pw)1300 public void dumpLocked(PrintWriter pw) { 1301 pw.println(" SettingsObserver"); 1302 pw.println(" mDefaultRefreshRate: " + mDefaultRefreshRate); 1303 pw.println(" mDefaultPeakRefreshRate: " + mDefaultPeakRefreshRate); 1304 } 1305 } 1306 1307 /** 1308 * Responsible for keeping track of app requested refresh rates per display 1309 */ 1310 public final class AppRequestObserver { 1311 private final boolean mIgnorePreferredRefreshRate; 1312 AppRequestObserver(DisplayManagerFlags flags)1313 AppRequestObserver(DisplayManagerFlags flags) { 1314 mIgnorePreferredRefreshRate = flags.ignoreAppPreferredRefreshRateRequest(); 1315 } 1316 1317 /** 1318 * Sets refresh rates from app request 1319 */ setAppRequest(int displayId, int modeId, float requestedRefreshRate, float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange)1320 public void setAppRequest(int displayId, int modeId, float requestedRefreshRate, 1321 float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) { 1322 Display.Mode requestedMode; 1323 boolean isExternalDisplay; 1324 synchronized (mLock) { 1325 requestedMode = findModeLocked(displayId, modeId, requestedRefreshRate); 1326 isExternalDisplay = isExternalDisplayLocked(displayId); 1327 } 1328 1329 Vote frameRateVote = getFrameRateVote( 1330 requestedMinRefreshRateRange, requestedMaxRefreshRateRange); 1331 Vote baseModeRefreshRateVote = getBaseModeVote(requestedMode, requestedRefreshRate); 1332 1333 mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 1334 frameRateVote); 1335 mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1336 baseModeRefreshRateVote); 1337 1338 if (!isExternalDisplay) { 1339 Vote sizeVote = getSizeVote(requestedMode); 1340 mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote); 1341 } 1342 } 1343 findModeLocked(int displayId, int modeId, float requestedRefreshRate)1344 private Display.Mode findModeLocked(int displayId, int modeId, float requestedRefreshRate) { 1345 Display.Mode mode = null; 1346 if (modeId != 0) { 1347 mode = findAppModeByIdLocked(displayId, modeId); 1348 } else if (requestedRefreshRate != 0 && !mIgnorePreferredRefreshRate) { // modeId == 0 1349 // Scan supported modes returned to find a mode with the same 1350 // size as the default display mode but with the specified refresh rate instead. 1351 mode = findDefaultModeByRefreshRateLocked(displayId, requestedRefreshRate); 1352 if (mode == null) { 1353 Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: " 1354 + requestedRefreshRate + " on Display: " + displayId); 1355 } 1356 } 1357 return mode; 1358 } 1359 getFrameRateVote(float minRefreshRate, float maxRefreshRate)1360 private Vote getFrameRateVote(float minRefreshRate, float maxRefreshRate) { 1361 RefreshRateRange refreshRateRange = null; 1362 if (minRefreshRate > 0 || maxRefreshRate > 0) { 1363 float max = maxRefreshRate > 0 1364 ? maxRefreshRate : Float.POSITIVE_INFINITY; 1365 refreshRateRange = new RefreshRateRange(minRefreshRate, max); 1366 if (refreshRateRange.min == 0 && refreshRateRange.max == 0) { 1367 // minRefreshRate/maxRefreshRate were invalid 1368 refreshRateRange = null; 1369 } 1370 } 1371 return refreshRateRange != null 1372 ? Vote.forRenderFrameRates(refreshRateRange.min, refreshRateRange.max) : null; 1373 } 1374 getSizeVote(@ullable Display.Mode mode)1375 private Vote getSizeVote(@Nullable Display.Mode mode) { 1376 return mode != null 1377 ? Vote.forSize(mode.getPhysicalWidth(), mode.getPhysicalHeight()) : null; 1378 } 1379 getBaseModeVote(@ullable Display.Mode mode, float requestedRefreshRate)1380 private Vote getBaseModeVote(@Nullable Display.Mode mode, float requestedRefreshRate) { 1381 Vote vote = null; 1382 if (mode != null) { 1383 if (mode.isSynthetic()) { 1384 vote = Vote.forRequestedRefreshRate(mode.getRefreshRate()); 1385 } else { 1386 vote = Vote.forBaseModeRefreshRate(mode.getRefreshRate()); 1387 } 1388 } else if (requestedRefreshRate != 0f && mIgnorePreferredRefreshRate) { 1389 vote = Vote.forRequestedRefreshRate(requestedRefreshRate); 1390 } // !mIgnorePreferredRefreshRate case is handled by findModeLocked 1391 return vote; 1392 } 1393 1394 @Nullable findDefaultModeByRefreshRateLocked(int displayId, float refreshRate)1395 private Display.Mode findDefaultModeByRefreshRateLocked(int displayId, float refreshRate) { 1396 Display.Mode[] modes = mAppSupportedModesByDisplay.get(displayId); 1397 Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId); 1398 for (int i = 0; i < modes.length; i++) { 1399 if (modes[i].matches(defaultMode.getPhysicalWidth(), 1400 defaultMode.getPhysicalHeight(), refreshRate)) { 1401 return modes[i]; 1402 } 1403 } 1404 return null; 1405 } 1406 findAppModeByIdLocked(int displayId, int modeId)1407 private Display.Mode findAppModeByIdLocked(int displayId, int modeId) { 1408 Display.Mode[] modes = mAppSupportedModesByDisplay.get(displayId); 1409 if (modes == null) { 1410 return null; 1411 } 1412 for (Display.Mode mode : modes) { 1413 if (mode.getModeId() == modeId) { 1414 return mode; 1415 } 1416 } 1417 return null; 1418 } 1419 dumpLocked(PrintWriter pw)1420 private void dumpLocked(PrintWriter pw) { 1421 pw.println(" AppRequestObserver"); 1422 pw.println(" mIgnorePreferredRefreshRate: " + mIgnorePreferredRefreshRate); 1423 } 1424 } 1425 1426 @VisibleForTesting 1427 public final class DisplayObserver implements DisplayManager.DisplayListener { 1428 // Note that we can never call into DisplayManager or any of the non-POD classes it 1429 // returns, while holding mLock since it may call into DMS, which might be simultaneously 1430 // calling into us already holding its own lock. 1431 private final Context mContext; 1432 private final Handler mHandler; 1433 private final VotesStorage mVotesStorage; 1434 1435 private int mExternalDisplayPeakWidth; 1436 private int mExternalDisplayPeakHeight; 1437 private int mExternalDisplayPeakRefreshRate; 1438 private final boolean mRefreshRateSynchronizationEnabled; 1439 DisplayObserver(Context context, Handler handler, VotesStorage votesStorage, Injector injector)1440 DisplayObserver(Context context, Handler handler, VotesStorage votesStorage, 1441 Injector injector) { 1442 mContext = context; 1443 mHandler = handler; 1444 mVotesStorage = votesStorage; 1445 mExternalDisplayPeakRefreshRate = mContext.getResources().getInteger( 1446 R.integer.config_externalDisplayPeakRefreshRate); 1447 mExternalDisplayPeakWidth = mContext.getResources().getInteger( 1448 R.integer.config_externalDisplayPeakWidth); 1449 mExternalDisplayPeakHeight = mContext.getResources().getInteger( 1450 R.integer.config_externalDisplayPeakHeight); 1451 mRefreshRateSynchronizationEnabled = mContext.getResources().getBoolean( 1452 R.bool.config_refreshRateSynchronizationEnabled); 1453 } 1454 isExternalDisplayLimitModeEnabled()1455 private boolean isExternalDisplayLimitModeEnabled() { 1456 return mExternalDisplayPeakWidth > 0 1457 && mExternalDisplayPeakHeight > 0 1458 && mExternalDisplayPeakRefreshRate > 0 1459 && mIsExternalDisplayLimitModeEnabled 1460 && mIsDisplayResolutionRangeVotingEnabled 1461 && mIsUserPreferredModeVoteEnabled; 1462 } 1463 isRefreshRateSynchronizationEnabled()1464 private boolean isRefreshRateSynchronizationEnabled() { 1465 return mRefreshRateSynchronizationEnabled 1466 && mIsDisplaysRefreshRatesSynchronizationEnabled; 1467 } 1468 observe()1469 public void observe() { 1470 mInjector.registerDisplayListener(this, mHandler); 1471 1472 // Populate existing displays 1473 SparseArray<Display.Mode[]> modes = new SparseArray<>(); 1474 SparseArray<Display.Mode[]> appModes = new SparseArray<>(); 1475 SparseArray<Display.Mode> defaultModes = new SparseArray<>(); 1476 Display[] displays = mInjector.getDisplays(); 1477 for (Display d : displays) { 1478 final int displayId = d.getDisplayId(); 1479 DisplayInfo info = getDisplayInfo(displayId); 1480 modes.put(displayId, info.supportedModes); 1481 appModes.put(displayId, info.appsSupportedModes); 1482 defaultModes.put(displayId, info.getDefaultMode()); 1483 } 1484 DisplayDeviceConfig defaultDisplayConfig = mDisplayDeviceConfigProvider 1485 .getDisplayDeviceConfig(Display.DEFAULT_DISPLAY); 1486 synchronized (mLock) { 1487 final int size = modes.size(); 1488 for (int i = 0; i < size; i++) { 1489 mSupportedModesByDisplay.put(modes.keyAt(i), modes.valueAt(i)); 1490 mAppSupportedModesByDisplay.put(appModes.keyAt(i), appModes.valueAt(i)); 1491 mDefaultModeByDisplay.put(defaultModes.keyAt(i), defaultModes.valueAt(i)); 1492 } 1493 mDisplayDeviceConfigByDisplay.put(Display.DEFAULT_DISPLAY, defaultDisplayConfig); 1494 } 1495 } 1496 1497 @Override onDisplayAdded(int displayId)1498 public void onDisplayAdded(int displayId) { 1499 updateDisplayDeviceConfig(displayId); 1500 DisplayInfo displayInfo = getDisplayInfo(displayId); 1501 registerExternalDisplay(displayInfo); 1502 updateDisplayModes(displayId, displayInfo); 1503 updateHasArrSupport(displayId, displayInfo); 1504 updateLayoutLimitedFrameRate(displayId, displayInfo); 1505 updateUserSettingDisplayPreferredSize(displayInfo); 1506 updateDisplaysPeakRefreshRateAndResolution(displayInfo); 1507 } 1508 1509 @Override onDisplayRemoved(int displayId)1510 public void onDisplayRemoved(int displayId) { 1511 synchronized (mLock) { 1512 mSupportedModesByDisplay.remove(displayId); 1513 mAppSupportedModesByDisplay.remove(displayId); 1514 mDefaultModeByDisplay.remove(displayId); 1515 mDisplayDeviceConfigByDisplay.remove(displayId); 1516 mSettingsObserver.removeRefreshRateSetting(displayId); 1517 mHasArrSupport.delete(displayId); 1518 } 1519 updateLayoutLimitedFrameRate(displayId, null); 1520 removeUserSettingDisplayPreferredSize(displayId); 1521 removeDisplaysPeakRefreshRateAndResolution(displayId); 1522 unregisterExternalDisplay(displayId); 1523 } 1524 1525 @Override onDisplayChanged(int displayId)1526 public void onDisplayChanged(int displayId) { 1527 updateDisplayDeviceConfig(displayId); 1528 DisplayInfo displayInfo = getDisplayInfo(displayId); 1529 updateHasArrSupport(displayId, displayInfo); 1530 updateDisplayModes(displayId, displayInfo); 1531 updateLayoutLimitedFrameRate(displayId, displayInfo); 1532 updateUserSettingDisplayPreferredSize(displayInfo); 1533 } 1534 registerExternalDisplay(DisplayInfo displayInfo)1535 private void registerExternalDisplay(DisplayInfo displayInfo) { 1536 if (displayInfo == null || displayInfo.type != Display.TYPE_EXTERNAL) { 1537 return; 1538 } 1539 synchronized (mLock) { 1540 mExternalDisplaysConnected.add(displayInfo.displayId); 1541 if (mExternalDisplaysConnected.size() == 1) { 1542 addDisplaysSynchronizedPeakRefreshRate(); 1543 } 1544 } 1545 } 1546 unregisterExternalDisplay(int displayId)1547 private void unregisterExternalDisplay(int displayId) { 1548 synchronized (mLock) { 1549 if (!isExternalDisplayLocked(displayId)) { 1550 return; 1551 } 1552 mExternalDisplaysConnected.remove(displayId); 1553 if (mExternalDisplaysConnected.isEmpty()) { 1554 removeDisplaysSynchronizedPeakRefreshRate(); 1555 } 1556 } 1557 } 1558 1559 @Nullable getDisplayInfo(int displayId)1560 private DisplayInfo getDisplayInfo(int displayId) { 1561 DisplayInfo info = new DisplayInfo(); 1562 // Display info might be invalid, in this case return null 1563 return mInjector.getDisplayInfo(displayId, info) ? info : null; 1564 } 1565 updateLayoutLimitedFrameRate(int displayId, @Nullable DisplayInfo info)1566 private void updateLayoutLimitedFrameRate(int displayId, @Nullable DisplayInfo info) { 1567 Vote refreshRateVote = null; 1568 Vote frameRateVote = null; 1569 if (info != null && info.layoutLimitedRefreshRate != null) { 1570 refreshRateVote = Vote.forPhysicalRefreshRates(info.layoutLimitedRefreshRate.min, 1571 info.layoutLimitedRefreshRate.max); 1572 frameRateVote = Vote.forRenderFrameRates(info.layoutLimitedRefreshRate.min, 1573 info.layoutLimitedRefreshRate.max); 1574 } 1575 mVotesStorage.updateVote( 1576 displayId, Vote.PRIORITY_LAYOUT_LIMITED_REFRESH_RATE, refreshRateVote); 1577 mVotesStorage.updateVote( 1578 displayId, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE, frameRateVote); 1579 } 1580 removeUserSettingDisplayPreferredSize(int displayId)1581 private void removeUserSettingDisplayPreferredSize(int displayId) { 1582 if (!mIsUserPreferredModeVoteEnabled) { 1583 return; 1584 } 1585 mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE, 1586 null); 1587 } 1588 updateUserSettingDisplayPreferredSize(@ullable DisplayInfo info)1589 private void updateUserSettingDisplayPreferredSize(@Nullable DisplayInfo info) { 1590 if (info == null || !mIsUserPreferredModeVoteEnabled) { 1591 return; 1592 } 1593 1594 var preferredMode = findDisplayPreferredMode(info); 1595 if (preferredMode == null) { 1596 removeUserSettingDisplayPreferredSize(info.displayId); 1597 return; 1598 } 1599 1600 if (info.type == Display.TYPE_EXTERNAL 1601 && mDisplayManagerFlags.isUserRefreshRateForExternalDisplayEnabled() 1602 && !isRefreshRateSynchronizationEnabled()) { 1603 mVotesStorage.updateVote(info.displayId, 1604 Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE, 1605 Vote.forSizeAndPhysicalRefreshRatesRange( 1606 /* minWidth */ preferredMode.getPhysicalWidth(), 1607 /* minHeight */ preferredMode.getPhysicalHeight(), 1608 /* width */ preferredMode.getPhysicalWidth(), 1609 /* height */ preferredMode.getPhysicalHeight(), 1610 /* minRefreshRate */ preferredMode.getRefreshRate(), 1611 /* maxRefreshRate */ preferredMode.getRefreshRate())); 1612 } else { 1613 mVotesStorage.updateVote(info.displayId, 1614 Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE, 1615 Vote.forSize(/* width */ preferredMode.getPhysicalWidth(), 1616 /* height */ preferredMode.getPhysicalHeight())); 1617 } 1618 } 1619 1620 @Nullable findDisplayPreferredMode(@onNull DisplayInfo info)1621 private Display.Mode findDisplayPreferredMode(@NonNull DisplayInfo info) { 1622 if (info.userPreferredModeId == INVALID_MODE_ID) { 1623 return null; 1624 } 1625 for (var mode : info.supportedModes) { 1626 if (mode.getModeId() == info.userPreferredModeId) { 1627 return mode; 1628 } 1629 } 1630 return null; 1631 } 1632 removeDisplaysPeakRefreshRateAndResolution(int displayId)1633 private void removeDisplaysPeakRefreshRateAndResolution(int displayId) { 1634 if (!isExternalDisplayLimitModeEnabled()) { 1635 return; 1636 } 1637 1638 mVotesStorage.updateVote(displayId, 1639 Vote.PRIORITY_LIMIT_MODE, null); 1640 } 1641 updateDisplaysPeakRefreshRateAndResolution(@ullable final DisplayInfo info)1642 private void updateDisplaysPeakRefreshRateAndResolution(@Nullable final DisplayInfo info) { 1643 // Only consider external display, only in case the refresh rate and resolution limits 1644 // are non-zero. 1645 if (info == null || info.type != Display.TYPE_EXTERNAL 1646 || !isExternalDisplayLimitModeEnabled()) { 1647 return; 1648 } 1649 1650 mVotesStorage.updateVote(info.displayId, 1651 Vote.PRIORITY_LIMIT_MODE, 1652 Vote.forSizeAndPhysicalRefreshRatesRange( 1653 /* minWidth */ 0, /* minHeight */ 0, 1654 mExternalDisplayPeakWidth, 1655 mExternalDisplayPeakHeight, 1656 /* minPhysicalRefreshRate */ 0, 1657 mExternalDisplayPeakRefreshRate)); 1658 } 1659 1660 /** 1661 * Sets 60Hz target refresh rate as the vote with 1662 * {@link Vote#PRIORITY_SYNCHRONIZED_REFRESH_RATE} priority. 1663 */ addDisplaysSynchronizedPeakRefreshRate()1664 private void addDisplaysSynchronizedPeakRefreshRate() { 1665 if (!isRefreshRateSynchronizationEnabled()) { 1666 return; 1667 } 1668 // set minRefreshRate as the max refresh rate. 1669 mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE, 1670 Vote.forPhysicalRefreshRates( 1671 SYNCHRONIZED_REFRESH_RATE_TARGET 1672 - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, 1673 SYNCHRONIZED_REFRESH_RATE_TARGET 1674 + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); 1675 mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, 1676 Vote.forRenderFrameRates( 1677 SYNCHRONIZED_REFRESH_RATE_TARGET 1678 - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, 1679 SYNCHRONIZED_REFRESH_RATE_TARGET 1680 + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); 1681 } 1682 removeDisplaysSynchronizedPeakRefreshRate()1683 private void removeDisplaysSynchronizedPeakRefreshRate() { 1684 if (!isRefreshRateSynchronizationEnabled()) { 1685 return; 1686 } 1687 mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE, null); 1688 mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, null); 1689 } 1690 updateDisplayDeviceConfig(int displayId)1691 private void updateDisplayDeviceConfig(int displayId) { 1692 DisplayDeviceConfig config = mDisplayDeviceConfigProvider 1693 .getDisplayDeviceConfig(displayId); 1694 synchronized (mLock) { 1695 mDisplayDeviceConfigByDisplay.put(displayId, config); 1696 } 1697 } 1698 updateDisplayModes(int displayId, @Nullable DisplayInfo info)1699 private void updateDisplayModes(int displayId, @Nullable DisplayInfo info) { 1700 if (info == null) { 1701 return; 1702 } 1703 boolean changed = false; 1704 synchronized (mLock) { 1705 if (!Arrays.equals(mSupportedModesByDisplay.get(displayId), info.supportedModes)) { 1706 mSupportedModesByDisplay.put(displayId, info.supportedModes); 1707 changed = true; 1708 } 1709 if (!Arrays.equals(mAppSupportedModesByDisplay.get(displayId), 1710 info.appsSupportedModes)) { 1711 mAppSupportedModesByDisplay.put(displayId, info.appsSupportedModes); 1712 changed = true; 1713 } 1714 if (!Objects.equals(mDefaultModeByDisplay.get(displayId), info.getDefaultMode())) { 1715 changed = true; 1716 mDefaultModeByDisplay.put(displayId, info.getDefaultMode()); 1717 } 1718 if (changed) { 1719 notifyDesiredDisplayModeSpecsChangedLocked(); 1720 mSettingsObserver.updateRefreshRateSettingLocked(displayId); 1721 } 1722 } 1723 } 1724 updateHasArrSupport(int displayId, @Nullable DisplayInfo info)1725 private void updateHasArrSupport(int displayId, @Nullable DisplayInfo info) { 1726 if (info == null) { 1727 return; 1728 } 1729 synchronized (mLock) { 1730 mHasArrSupport.put(displayId, info.hasArrSupport); 1731 } 1732 } 1733 1734 } 1735 1736 /** 1737 * This class manages brightness threshold for switching between 60 hz and higher refresh rate. 1738 * See more information at the definition of 1739 * {@link R.array#config_brightnessThresholdsOfPeakRefreshRate} and 1740 * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}. 1741 */ 1742 @VisibleForTesting 1743 public class BrightnessObserver implements DisplayManager.DisplayListener { 1744 private static final int LIGHT_SENSOR_RATE_MS = 250; 1745 1746 /** 1747 * Brightness thresholds for the low zone. Paired with lux thresholds. 1748 * 1749 * A negative value means that only the lux threshold should be applied. 1750 */ 1751 private float[] mLowDisplayBrightnessThresholds; 1752 /** 1753 * Lux thresholds for the low zone. Paired with brightness thresholds. 1754 * 1755 * A negative value means that only the display brightness threshold should be applied. 1756 */ 1757 private float[] mLowAmbientBrightnessThresholds; 1758 1759 /** 1760 * Brightness thresholds for the high zone. Paired with lux thresholds. 1761 * 1762 * A negative value means that only the lux threshold should be applied. 1763 */ 1764 private float[] mHighDisplayBrightnessThresholds; 1765 /** 1766 * Lux thresholds for the high zone. Paired with brightness thresholds. 1767 * 1768 * A negative value means that only the display brightness threshold should be applied. 1769 */ 1770 private float[] mHighAmbientBrightnessThresholds; 1771 // valid threshold if any item from the array >= 0 1772 private boolean mShouldObserveDisplayLowChange; 1773 private boolean mShouldObserveAmbientLowChange; 1774 private boolean mShouldObserveDisplayHighChange; 1775 private boolean mShouldObserveAmbientHighChange; 1776 private boolean mLoggingEnabled; 1777 1778 private SensorManager mSensorManager; 1779 private Sensor mLightSensor; 1780 private Sensor mRegisteredLightSensor; 1781 private String mLightSensorType; 1782 private String mLightSensorName; 1783 private final LightSensorEventListener mLightSensorListener = 1784 new LightSensorEventListener(); 1785 // Take it as low brightness before valid sensor data comes 1786 private float mAmbientLux = -1.0f; 1787 private AmbientFilter mAmbientFilter; 1788 1789 /** 1790 * The current timeout configuration. This value is used by surface flinger to track the 1791 * time after which an idle screen's refresh rate is to be reduced. 1792 */ 1793 @Nullable 1794 private SurfaceControl.IdleScreenRefreshRateConfig mIdleScreenRefreshRateConfig; 1795 1796 private float mBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; 1797 1798 private final Context mContext; 1799 private final Injector mInjector; 1800 private final Handler mHandler; 1801 1802 1803 private final boolean mVsyncLowLightBlockingVoteEnabled; 1804 1805 private final IThermalEventListener.Stub mThermalListener = 1806 new IThermalEventListener.Stub() { 1807 @Override 1808 public void notifyThrottling(Temperature temp) { 1809 @Temperature.ThrottlingStatus int currentStatus = temp.getStatus(); 1810 synchronized (mLock) { 1811 if (mThermalStatus != currentStatus) { 1812 mThermalStatus = currentStatus; 1813 } 1814 onBrightnessChangedLocked(); 1815 } 1816 } 1817 }; 1818 private boolean mThermalRegistered; 1819 1820 // Enable light sensor only when mShouldObserveAmbientLowChange is true or 1821 // mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate 1822 // changeable and low power mode off. After initialization, these states will 1823 // be updated from the same handler thread. 1824 private int mDefaultDisplayState = Display.STATE_UNKNOWN; 1825 private boolean mRefreshRateChangeable = false; 1826 private boolean mLowPowerModeEnabled = false; 1827 1828 @Nullable 1829 private SparseArray<RefreshRateRange> mLowZoneRefreshRateForThermals; 1830 private int mRefreshRateInLowZone; 1831 1832 @Nullable 1833 private SparseArray<RefreshRateRange> mHighZoneRefreshRateForThermals; 1834 private int mRefreshRateInHighZone; 1835 1836 @Nullable 1837 private List<IdleScreenRefreshRateTimeoutLuxThresholdPoint> 1838 mIdleScreenRefreshRateTimeoutLuxThresholdPoints; 1839 1840 @GuardedBy("mLock") 1841 private @Temperature.ThrottlingStatus int mThermalStatus = Temperature.THROTTLING_NONE; 1842 BrightnessObserver(Context context, Handler handler, Injector injector, DisplayManagerFlags flags)1843 BrightnessObserver(Context context, Handler handler, Injector injector, 1844 DisplayManagerFlags flags) { 1845 mContext = context; 1846 mHandler = handler; 1847 mInjector = injector; 1848 updateBlockingZoneThresholds(/* displayDeviceConfig= */ null, 1849 /* attemptReadFromFeatureParams= */ false); 1850 mRefreshRateInHighZone = context.getResources().getInteger( 1851 R.integer.config_fixedRefreshRateInHighZone); 1852 mVsyncLowLightBlockingVoteEnabled = flags.isVsyncLowLightVoteEnabled(); 1853 loadIdleScreenRefreshRateConfigs(/* displayDeviceConfig= */ null); 1854 } 1855 loadIdleScreenRefreshRateConfigs(DisplayDeviceConfig displayDeviceConfig)1856 private void loadIdleScreenRefreshRateConfigs(DisplayDeviceConfig displayDeviceConfig) { 1857 synchronized (mLock) { 1858 if (!mDisplayManagerFlags.isIdleScreenConfigInSubscribingLightSensorEnabled() 1859 || displayDeviceConfig == null || displayDeviceConfig 1860 .getIdleScreenRefreshRateTimeoutLuxThresholdPoint().isEmpty()) { 1861 // Setting this to null will let surface flinger know that the idle timer is not 1862 // configured in the display configs 1863 mIdleScreenRefreshRateConfig = null; 1864 mIdleScreenRefreshRateTimeoutLuxThresholdPoints = null; 1865 return; 1866 } 1867 mIdleScreenRefreshRateTimeoutLuxThresholdPoints = 1868 displayDeviceConfig 1869 .getIdleScreenRefreshRateTimeoutLuxThresholdPoint(); 1870 } 1871 } 1872 1873 /** 1874 * This is used to update the blocking zone thresholds from the DeviceConfig, which 1875 * if missing from DisplayDeviceConfig, and finally fallback to config.xml. 1876 */ updateBlockingZoneThresholds(@ullable DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1877 public void updateBlockingZoneThresholds(@Nullable DisplayDeviceConfig displayDeviceConfig, 1878 boolean attemptReadFromFeatureParams) { 1879 loadLowBrightnessThresholds(displayDeviceConfig, attemptReadFromFeatureParams); 1880 loadHighBrightnessThresholds(displayDeviceConfig, attemptReadFromFeatureParams); 1881 } 1882 1883 @VisibleForTesting getLowDisplayBrightnessThresholds()1884 float[] getLowDisplayBrightnessThresholds() { 1885 return mLowDisplayBrightnessThresholds; 1886 } 1887 1888 @VisibleForTesting getLowAmbientBrightnessThresholds()1889 float[] getLowAmbientBrightnessThresholds() { 1890 return mLowAmbientBrightnessThresholds; 1891 } 1892 1893 @VisibleForTesting getHighDisplayBrightnessThresholds()1894 float[] getHighDisplayBrightnessThresholds() { 1895 return mHighDisplayBrightnessThresholds; 1896 } 1897 1898 @VisibleForTesting getHighAmbientBrightnessThresholds()1899 float[] getHighAmbientBrightnessThresholds() { 1900 return mHighAmbientBrightnessThresholds; 1901 } 1902 1903 /** 1904 * @return the refresh rate to lock to when in a high brightness zone 1905 */ 1906 @VisibleForTesting getRefreshRateInHighZone()1907 int getRefreshRateInHighZone() { 1908 return mRefreshRateInHighZone; 1909 } 1910 1911 /** 1912 * @return the refresh rate to lock to when in a low brightness zone 1913 */ 1914 @VisibleForTesting getRefreshRateInLowZone()1915 int getRefreshRateInLowZone() { 1916 return mRefreshRateInLowZone; 1917 } 1918 1919 @Nullable 1920 @VisibleForTesting getIdleScreenRefreshRateConfig()1921 IdleScreenRefreshRateConfig getIdleScreenRefreshRateConfig() { 1922 return mIdleScreenRefreshRateConfig; 1923 } 1924 1925 @Nullable 1926 @VisibleForTesting 1927 List<IdleScreenRefreshRateTimeoutLuxThresholdPoint> getIdleScreenRefreshRateTimeoutLuxThresholdPoints()1928 getIdleScreenRefreshRateTimeoutLuxThresholdPoints() { 1929 return mIdleScreenRefreshRateTimeoutLuxThresholdPoints; 1930 } 1931 loadLowBrightnessThresholds(@ullable DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1932 private void loadLowBrightnessThresholds(@Nullable DisplayDeviceConfig displayDeviceConfig, 1933 boolean attemptReadFromFeatureParams) { 1934 loadRefreshRateInHighZone(displayDeviceConfig, attemptReadFromFeatureParams); 1935 loadRefreshRateInLowZone(displayDeviceConfig, attemptReadFromFeatureParams); 1936 mLowDisplayBrightnessThresholds = loadBrightnessThresholds( 1937 () -> mConfigParameterProvider.getLowDisplayBrightnessThresholds(), 1938 () -> displayDeviceConfig.getLowDisplayBrightnessThresholds(), 1939 R.array.config_brightnessThresholdsOfPeakRefreshRate, 1940 displayDeviceConfig, attemptReadFromFeatureParams, 1941 DeviceConfigParsingUtils::displayBrightnessThresholdsIntToFloat); 1942 mLowAmbientBrightnessThresholds = loadBrightnessThresholds( 1943 () -> mConfigParameterProvider.getLowAmbientBrightnessThresholds(), 1944 () -> displayDeviceConfig.getLowAmbientBrightnessThresholds(), 1945 R.array.config_ambientThresholdsOfPeakRefreshRate, 1946 displayDeviceConfig, attemptReadFromFeatureParams, 1947 DeviceConfigParsingUtils::ambientBrightnessThresholdsIntToFloat); 1948 if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) { 1949 throw new RuntimeException("display low brightness threshold array and ambient " 1950 + "brightness threshold array have different length: " 1951 + "displayBrightnessThresholds=" 1952 + Arrays.toString(mLowDisplayBrightnessThresholds) 1953 + ", ambientBrightnessThresholds=" 1954 + Arrays.toString(mLowAmbientBrightnessThresholds)); 1955 } 1956 } 1957 loadRefreshRateInLowZone(DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1958 private void loadRefreshRateInLowZone(DisplayDeviceConfig displayDeviceConfig, 1959 boolean attemptReadFromFeatureParams) { 1960 int refreshRateInLowZone = -1; 1961 if (attemptReadFromFeatureParams) { 1962 try { 1963 refreshRateInLowZone = mConfigParameterProvider.getRefreshRateInLowZone(); 1964 } catch (Exception exception) { 1965 // Do nothing 1966 } 1967 } 1968 if (refreshRateInLowZone == -1) { 1969 refreshRateInLowZone = (displayDeviceConfig == null) 1970 ? mContext.getResources().getInteger( 1971 R.integer.config_defaultRefreshRateInZone) 1972 : displayDeviceConfig.getDefaultLowBlockingZoneRefreshRate(); 1973 } 1974 mLowZoneRefreshRateForThermals = displayDeviceConfig == null ? null 1975 : displayDeviceConfig.getLowBlockingZoneThermalMap(); 1976 mRefreshRateInLowZone = refreshRateInLowZone; 1977 } 1978 loadRefreshRateInHighZone(DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)1979 private void loadRefreshRateInHighZone(DisplayDeviceConfig displayDeviceConfig, 1980 boolean attemptReadFromFeatureParams) { 1981 int refreshRateInHighZone = -1; 1982 if (attemptReadFromFeatureParams) { 1983 try { 1984 refreshRateInHighZone = mConfigParameterProvider.getRefreshRateInHighZone(); 1985 } catch (Exception exception) { 1986 // Do nothing 1987 } 1988 } 1989 if (refreshRateInHighZone == -1) { 1990 refreshRateInHighZone = (displayDeviceConfig == null) 1991 ? mContext.getResources().getInteger( 1992 R.integer.config_fixedRefreshRateInHighZone) 1993 : displayDeviceConfig.getDefaultHighBlockingZoneRefreshRate(); 1994 } 1995 mHighZoneRefreshRateForThermals = displayDeviceConfig == null ? null 1996 : displayDeviceConfig.getHighBlockingZoneThermalMap(); 1997 mRefreshRateInHighZone = refreshRateInHighZone; 1998 } 1999 loadHighBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams)2000 private void loadHighBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig, 2001 boolean attemptReadFromFeatureParams) { 2002 mHighDisplayBrightnessThresholds = loadBrightnessThresholds( 2003 () -> mConfigParameterProvider.getHighDisplayBrightnessThresholds(), 2004 () -> displayDeviceConfig.getHighDisplayBrightnessThresholds(), 2005 R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate, 2006 displayDeviceConfig, attemptReadFromFeatureParams, 2007 DeviceConfigParsingUtils::displayBrightnessThresholdsIntToFloat); 2008 mHighAmbientBrightnessThresholds = loadBrightnessThresholds( 2009 () -> mConfigParameterProvider.getHighAmbientBrightnessThresholds(), 2010 () -> displayDeviceConfig.getHighAmbientBrightnessThresholds(), 2011 R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate, 2012 displayDeviceConfig, attemptReadFromFeatureParams, 2013 DeviceConfigParsingUtils::ambientBrightnessThresholdsIntToFloat); 2014 if (mHighDisplayBrightnessThresholds.length 2015 != mHighAmbientBrightnessThresholds.length) { 2016 throw new RuntimeException("display high brightness threshold array and ambient " 2017 + "brightness threshold array have different length: " 2018 + "displayBrightnessThresholds=" 2019 + Arrays.toString(mHighDisplayBrightnessThresholds) 2020 + ", ambientBrightnessThresholds=" 2021 + Arrays.toString(mHighAmbientBrightnessThresholds)); 2022 } 2023 } 2024 loadBrightnessThresholds( Callable<float[]> loadFromDeviceConfigDisplaySettingsCallable, Callable<float[]> loadFromDisplayDeviceConfigCallable, int brightnessThresholdOfFixedRefreshRateKey, DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams, Function<int[], float[]> conversion)2025 private float[] loadBrightnessThresholds( 2026 Callable<float[]> loadFromDeviceConfigDisplaySettingsCallable, 2027 Callable<float[]> loadFromDisplayDeviceConfigCallable, 2028 int brightnessThresholdOfFixedRefreshRateKey, 2029 DisplayDeviceConfig displayDeviceConfig, boolean attemptReadFromFeatureParams, 2030 Function<int[], float[]> conversion) { 2031 float[] brightnessThresholds = null; 2032 2033 if (attemptReadFromFeatureParams) { 2034 try { 2035 brightnessThresholds = loadFromDeviceConfigDisplaySettingsCallable.call(); 2036 } catch (Exception exception) { 2037 // Do nothing 2038 } 2039 } 2040 if (brightnessThresholds == null) { 2041 try { 2042 brightnessThresholds = displayDeviceConfig == null ? conversion.apply( 2043 mContext.getResources().getIntArray( 2044 brightnessThresholdOfFixedRefreshRateKey)) : 2045 loadFromDisplayDeviceConfigCallable.call(); 2046 } catch (Exception e) { 2047 Slog.e(TAG, "Unexpectedly failed to load display brightness threshold"); 2048 e.printStackTrace(); 2049 } 2050 } 2051 return brightnessThresholds; 2052 } 2053 observe(SensorManager sensorManager)2054 private void observe(SensorManager sensorManager) { 2055 mSensorManager = sensorManager; 2056 mBrightness = getBrightness(Display.DEFAULT_DISPLAY); 2057 2058 // DeviceConfig is accessible after system ready. 2059 float[] lowDisplayBrightnessThresholds = 2060 mConfigParameterProvider.getLowDisplayBrightnessThresholds(); 2061 float[] lowAmbientBrightnessThresholds = 2062 mConfigParameterProvider.getLowAmbientBrightnessThresholds(); 2063 if (lowDisplayBrightnessThresholds != null && lowAmbientBrightnessThresholds != null 2064 && lowDisplayBrightnessThresholds.length 2065 == lowAmbientBrightnessThresholds.length) { 2066 mLowDisplayBrightnessThresholds = lowDisplayBrightnessThresholds; 2067 mLowAmbientBrightnessThresholds = lowAmbientBrightnessThresholds; 2068 } 2069 2070 float[] highDisplayBrightnessThresholds = 2071 mConfigParameterProvider.getHighDisplayBrightnessThresholds(); 2072 float[] highAmbientBrightnessThresholds = 2073 mConfigParameterProvider.getHighAmbientBrightnessThresholds(); 2074 if (highDisplayBrightnessThresholds != null && highAmbientBrightnessThresholds != null 2075 && highDisplayBrightnessThresholds.length 2076 == highAmbientBrightnessThresholds.length) { 2077 mHighDisplayBrightnessThresholds = highDisplayBrightnessThresholds; 2078 mHighAmbientBrightnessThresholds = highAmbientBrightnessThresholds; 2079 } 2080 2081 final int refreshRateInLowZone = mConfigParameterProvider.getRefreshRateInLowZone(); 2082 if (refreshRateInLowZone != -1) { 2083 mRefreshRateInLowZone = refreshRateInLowZone; 2084 } 2085 2086 final int refreshRateInHighZone = mConfigParameterProvider.getRefreshRateInHighZone(); 2087 if (refreshRateInHighZone != -1) { 2088 mRefreshRateInHighZone = refreshRateInHighZone; 2089 } 2090 2091 restartObserver(); 2092 mDeviceConfigDisplaySettings.startListening(); 2093 registerDisplayListener(); 2094 } 2095 registerDisplayListener()2096 private void registerDisplayListener() { 2097 mInjector.registerDisplayListener(this, mHandler, 2098 DisplayManager.EVENT_TYPE_DISPLAY_CHANGED, 2099 DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS); 2100 } 2101 setLoggingEnabled(boolean loggingEnabled)2102 private void setLoggingEnabled(boolean loggingEnabled) { 2103 if (mLoggingEnabled == loggingEnabled) { 2104 return; 2105 } 2106 mLoggingEnabled = loggingEnabled; 2107 mLightSensorListener.setLoggingEnabled(loggingEnabled); 2108 } 2109 2110 @VisibleForTesting onRefreshRateSettingChangedLocked(float min, float max)2111 public void onRefreshRateSettingChangedLocked(float min, float max) { 2112 boolean changeable = (max - min > 1f && max > 60f); 2113 if (mRefreshRateChangeable != changeable) { 2114 mRefreshRateChangeable = changeable; 2115 updateSensorStatus(); 2116 if (!changeable) { 2117 removeFlickerRefreshRateVotes(); 2118 } 2119 } 2120 } 2121 2122 @VisibleForTesting onLowPowerModeEnabledLocked(boolean enabled)2123 void onLowPowerModeEnabledLocked(boolean enabled) { 2124 if (mLowPowerModeEnabled != enabled) { 2125 mLowPowerModeEnabled = enabled; 2126 updateSensorStatus(); 2127 if (enabled) { 2128 removeFlickerRefreshRateVotes(); 2129 } 2130 } 2131 } 2132 removeFlickerRefreshRateVotes()2133 private void removeFlickerRefreshRateVotes() { 2134 // Revoke previous vote from BrightnessObserver 2135 mVotesStorage.updateGlobalVote(Vote.PRIORITY_FLICKER_REFRESH_RATE, null); 2136 mVotesStorage.updateGlobalVote(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, null); 2137 } 2138 onDeviceConfigLowBrightnessThresholdsChanged(float[] displayThresholds, float[] ambientThresholds)2139 private void onDeviceConfigLowBrightnessThresholdsChanged(float[] displayThresholds, 2140 float[] ambientThresholds) { 2141 if (displayThresholds != null && ambientThresholds != null 2142 && displayThresholds.length == ambientThresholds.length) { 2143 mLowDisplayBrightnessThresholds = displayThresholds; 2144 mLowAmbientBrightnessThresholds = ambientThresholds; 2145 } else { 2146 DisplayDeviceConfig displayDeviceConfig; 2147 synchronized (mLock) { 2148 displayDeviceConfig = mDefaultDisplayDeviceConfig; 2149 } 2150 mLowDisplayBrightnessThresholds = loadBrightnessThresholds( 2151 () -> mConfigParameterProvider.getLowDisplayBrightnessThresholds(), 2152 () -> displayDeviceConfig.getLowDisplayBrightnessThresholds(), 2153 R.array.config_brightnessThresholdsOfPeakRefreshRate, 2154 displayDeviceConfig, /* attemptReadFromFeatureParams= */ false, 2155 DeviceConfigParsingUtils::displayBrightnessThresholdsIntToFloat); 2156 mLowAmbientBrightnessThresholds = loadBrightnessThresholds( 2157 () -> mConfigParameterProvider.getLowAmbientBrightnessThresholds(), 2158 () -> displayDeviceConfig.getLowAmbientBrightnessThresholds(), 2159 R.array.config_ambientThresholdsOfPeakRefreshRate, 2160 displayDeviceConfig, /* attemptReadFromFeatureParams= */ false, 2161 DeviceConfigParsingUtils::ambientBrightnessThresholdsIntToFloat); 2162 } 2163 restartObserver(); 2164 } 2165 2166 /** 2167 * Used to reload the lower blocking zone refresh rate in case of changes in the 2168 * DeviceConfig properties. 2169 */ onDeviceConfigRefreshRateInLowZoneChanged(int refreshRate)2170 public void onDeviceConfigRefreshRateInLowZoneChanged(int refreshRate) { 2171 if (refreshRate == -1) { 2172 // Given there is no value available in DeviceConfig, lets not attempt loading it 2173 // from there. 2174 synchronized (mLock) { 2175 loadRefreshRateInLowZone(mDefaultDisplayDeviceConfig, 2176 /* attemptReadFromFeatureParams= */ false); 2177 } 2178 restartObserver(); 2179 } else if (refreshRate != mRefreshRateInLowZone) { 2180 mRefreshRateInLowZone = refreshRate; 2181 restartObserver(); 2182 } 2183 } 2184 onDeviceConfigHighBrightnessThresholdsChanged(float[] displayThresholds, float[] ambientThresholds)2185 private void onDeviceConfigHighBrightnessThresholdsChanged(float[] displayThresholds, 2186 float[] ambientThresholds) { 2187 if (displayThresholds != null && ambientThresholds != null 2188 && displayThresholds.length == ambientThresholds.length) { 2189 mHighDisplayBrightnessThresholds = displayThresholds; 2190 mHighAmbientBrightnessThresholds = ambientThresholds; 2191 } else { 2192 DisplayDeviceConfig displayDeviceConfig; 2193 synchronized (mLock) { 2194 displayDeviceConfig = mDefaultDisplayDeviceConfig; 2195 } 2196 mHighDisplayBrightnessThresholds = loadBrightnessThresholds( 2197 () -> mConfigParameterProvider.getLowDisplayBrightnessThresholds(), 2198 () -> displayDeviceConfig.getHighDisplayBrightnessThresholds(), 2199 R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate, 2200 displayDeviceConfig, /* attemptReadFromFeatureParams= */ false, 2201 DeviceConfigParsingUtils::displayBrightnessThresholdsIntToFloat); 2202 mHighAmbientBrightnessThresholds = loadBrightnessThresholds( 2203 () -> mConfigParameterProvider.getHighAmbientBrightnessThresholds(), 2204 () -> displayDeviceConfig.getHighAmbientBrightnessThresholds(), 2205 R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate, 2206 displayDeviceConfig, /* attemptReadFromFeatureParams= */ false, 2207 DeviceConfigParsingUtils::ambientBrightnessThresholdsIntToFloat); 2208 } 2209 restartObserver(); 2210 } 2211 2212 /** 2213 * Used to reload the higher blocking zone refresh rate in case of changes in the 2214 * DeviceConfig properties. 2215 */ onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate)2216 public void onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate) { 2217 if (refreshRate == -1) { 2218 // Given there is no value available in DeviceConfig, lets not attempt loading it 2219 // from there. 2220 synchronized (mLock) { 2221 loadRefreshRateInHighZone(mDefaultDisplayDeviceConfig, 2222 /* attemptReadFromFeatureParams= */ false); 2223 } 2224 restartObserver(); 2225 } else if (refreshRate != mRefreshRateInHighZone) { 2226 mRefreshRateInHighZone = refreshRate; 2227 restartObserver(); 2228 } 2229 } 2230 dumpLocked(PrintWriter pw)2231 void dumpLocked(PrintWriter pw) { 2232 pw.println(" BrightnessObserver"); 2233 pw.println(" mAmbientLux: " + mAmbientLux); 2234 pw.println(" mBrightness: " + mBrightness); 2235 pw.println(" mDefaultDisplayState: " + mDefaultDisplayState); 2236 pw.println(" mLowPowerModeEnabled: " + mLowPowerModeEnabled); 2237 pw.println(" mRefreshRateChangeable: " + mRefreshRateChangeable); 2238 pw.println(" mShouldObserveDisplayLowChange: " + mShouldObserveDisplayLowChange); 2239 pw.println(" mShouldObserveAmbientLowChange: " + mShouldObserveAmbientLowChange); 2240 pw.println(" mRefreshRateInLowZone: " + mRefreshRateInLowZone); 2241 2242 for (float d : mLowDisplayBrightnessThresholds) { 2243 pw.println(" mDisplayLowBrightnessThreshold: " + d); 2244 } 2245 2246 for (float d : mLowAmbientBrightnessThresholds) { 2247 pw.println(" mAmbientLowBrightnessThreshold: " + d); 2248 } 2249 2250 pw.println(" mShouldObserveDisplayHighChange: " + mShouldObserveDisplayHighChange); 2251 pw.println(" mShouldObserveAmbientHighChange: " + mShouldObserveAmbientHighChange); 2252 pw.println(" mRefreshRateInHighZone: " + mRefreshRateInHighZone); 2253 2254 for (float d : mHighDisplayBrightnessThresholds) { 2255 pw.println(" mDisplayHighBrightnessThresholds: " + d); 2256 } 2257 2258 for (float d : mHighAmbientBrightnessThresholds) { 2259 pw.println(" mAmbientHighBrightnessThresholds: " + d); 2260 } 2261 2262 pw.println(" mRegisteredLightSensor: " + mRegisteredLightSensor); 2263 pw.println(" mLightSensor: " + mLightSensor); 2264 pw.println(" mLightSensorName: " + mLightSensorName); 2265 pw.println(" mLightSensorType: " + mLightSensorType); 2266 mLightSensorListener.dumpLocked(pw); 2267 2268 if (mAmbientFilter != null) { 2269 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 2270 mAmbientFilter.dump(ipw); 2271 } 2272 } 2273 2274 @Override onDisplayAdded(int displayId)2275 public void onDisplayAdded(int displayId) {} 2276 2277 @Override onDisplayRemoved(int displayId)2278 public void onDisplayRemoved(int displayId) {} 2279 2280 @Override onDisplayChanged(int displayId)2281 public void onDisplayChanged(int displayId) { 2282 if (displayId == Display.DEFAULT_DISPLAY) { 2283 updateDefaultDisplayState(); 2284 2285 // We don't support multiple display blocking zones yet, so only handle 2286 // brightness changes for the default display for now. 2287 float brightness = getBrightness(displayId); 2288 synchronized (mLock) { 2289 if (!BrightnessSynchronizer.floatEquals(brightness, mBrightness)) { 2290 mBrightness = brightness; 2291 onBrightnessChangedLocked(); 2292 } 2293 } 2294 } 2295 } 2296 hasLowLightVrrConfig()2297 private boolean hasLowLightVrrConfig() { 2298 DisplayDeviceConfig config; 2299 synchronized (mLock) { 2300 config = mDefaultDisplayDeviceConfig; 2301 } 2302 return mVsyncLowLightBlockingVoteEnabled 2303 && config != null 2304 && config.isVrrSupportEnabled() 2305 && !config.getRefreshRateData().lowLightBlockingZoneSupportedModes.isEmpty(); 2306 } 2307 restartObserver()2308 private void restartObserver() { 2309 if (mRefreshRateInLowZone > 0 || hasLowLightVrrConfig()) { 2310 mShouldObserveDisplayLowChange = hasValidThreshold( 2311 mLowDisplayBrightnessThresholds); 2312 mShouldObserveAmbientLowChange = hasValidThreshold( 2313 mLowAmbientBrightnessThresholds); 2314 } else { 2315 mShouldObserveDisplayLowChange = false; 2316 mShouldObserveAmbientLowChange = false; 2317 } 2318 2319 if (mRefreshRateInHighZone > 0) { 2320 mShouldObserveDisplayHighChange = hasValidThreshold( 2321 mHighDisplayBrightnessThresholds); 2322 mShouldObserveAmbientHighChange = hasValidThreshold( 2323 mHighAmbientBrightnessThresholds); 2324 } else { 2325 mShouldObserveDisplayHighChange = false; 2326 mShouldObserveAmbientHighChange = false; 2327 } 2328 2329 if (shouldRegisterLightSensor()) { 2330 Sensor lightSensor = getLightSensor(); 2331 2332 if (lightSensor != null && lightSensor != mLightSensor) { 2333 final Resources res = mContext.getResources(); 2334 mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res); 2335 mLightSensor = lightSensor; 2336 } 2337 } else { 2338 mAmbientFilter = null; 2339 mLightSensor = null; 2340 } 2341 2342 updateSensorStatus(); 2343 synchronized (mLock) { 2344 onBrightnessChangedLocked(); 2345 } 2346 } 2347 reloadLightSensor(DisplayDeviceConfig displayDeviceConfig)2348 private void reloadLightSensor(DisplayDeviceConfig displayDeviceConfig) { 2349 reloadLightSensorData(displayDeviceConfig); 2350 restartObserver(); 2351 } 2352 reloadLightSensorData(DisplayDeviceConfig displayDeviceConfig)2353 private void reloadLightSensorData(DisplayDeviceConfig displayDeviceConfig) { 2354 // The displayDeviceConfig (ddc) contains display specific preferences. When loaded, 2355 // it naturally falls back to the global config.xml. 2356 if (displayDeviceConfig != null 2357 && displayDeviceConfig.getAmbientLightSensor() != null) { 2358 // This covers both the ddc and the config.xml fallback 2359 mLightSensorType = displayDeviceConfig.getAmbientLightSensor().type; 2360 mLightSensorName = displayDeviceConfig.getAmbientLightSensor().name; 2361 } else if (mLightSensorName == null && mLightSensorType == null) { 2362 Resources resources = mContext.getResources(); 2363 mLightSensorType = resources.getString( 2364 com.android.internal.R.string.config_displayLightSensorType); 2365 mLightSensorName = ""; 2366 } 2367 } 2368 getLightSensor()2369 private Sensor getLightSensor() { 2370 return SensorUtils.findSensor(mSensorManager, mLightSensorType, 2371 mLightSensorName, Sensor.TYPE_LIGHT); 2372 } 2373 2374 /** 2375 * Checks to see if at least one value is positive, in which case it is necessary to listen 2376 * to value changes. 2377 */ hasValidThreshold(float[] a)2378 private boolean hasValidThreshold(float[] a) { 2379 for (float d: a) { 2380 if (d >= 0) { 2381 return true; 2382 } 2383 } 2384 2385 return false; 2386 } 2387 2388 /** 2389 * Check if we're in the low zone where higher refresh rates aren't allowed to prevent 2390 * flickering. 2391 * @param brightness The brightness value or a negative value meaning that only the lux 2392 * threshold should be applied 2393 * @param lux The lux value. If negative, only the brightness threshold is applied 2394 * @return True if we're in the low zone 2395 */ isInsideLowZone(float brightness, float lux)2396 private boolean isInsideLowZone(float brightness, float lux) { 2397 for (int i = 0; i < mLowDisplayBrightnessThresholds.length; i++) { 2398 float disp = mLowDisplayBrightnessThresholds[i]; 2399 float ambi = mLowAmbientBrightnessThresholds[i]; 2400 2401 if (disp >= 0 && ambi >= 0) { 2402 if (brightness <= disp && lux <= ambi) { 2403 return true; 2404 } 2405 } else if (disp >= 0) { 2406 if (brightness <= disp) { 2407 return true; 2408 } 2409 } else if (ambi >= 0) { 2410 if (lux <= ambi) { 2411 return true; 2412 } 2413 } 2414 } 2415 2416 return false; 2417 } 2418 2419 /** 2420 * Check if we're in the high zone where higher refresh rates aren't allowed to prevent 2421 * flickering. 2422 * @param brightness The brightness value or a negative value meaning that only the lux 2423 * threshold should be applied 2424 * @param lux The lux value. If negative, only the brightness threshold is applied 2425 * @return True if we're in the high zone 2426 */ isInsideHighZone(float brightness, float lux)2427 private boolean isInsideHighZone(float brightness, float lux) { 2428 for (int i = 0; i < mHighDisplayBrightnessThresholds.length; i++) { 2429 float disp = mHighDisplayBrightnessThresholds[i]; 2430 float ambi = mHighAmbientBrightnessThresholds[i]; 2431 2432 if (disp >= 0 && ambi >= 0) { 2433 if (brightness >= disp && lux >= ambi) { 2434 return true; 2435 } 2436 } else if (disp >= 0) { 2437 if (brightness >= disp) { 2438 return true; 2439 } 2440 } else if (ambi >= 0) { 2441 if (lux >= ambi) { 2442 return true; 2443 } 2444 } 2445 } 2446 2447 return false; 2448 } 2449 2450 @GuardedBy("mLock") onBrightnessChangedLocked()2451 private void onBrightnessChangedLocked() { 2452 if (!mRefreshRateChangeable || mLowPowerModeEnabled) { 2453 return; 2454 } 2455 Vote refreshRateVote = null; 2456 Vote refreshRateSwitchingVote = null; 2457 2458 if (Float.isNaN(mBrightness)) { 2459 // Either the setting isn't available or we shouldn't be observing yet anyways. 2460 // Either way, just bail out since there's nothing we can do here. 2461 return; 2462 } 2463 2464 boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux); 2465 if (insideLowZone) { 2466 if (hasLowLightVrrConfig()) { 2467 refreshRateVote = Vote.forSupportedRefreshRates(mDefaultDisplayDeviceConfig 2468 .getRefreshRateData().lowLightBlockingZoneSupportedModes); 2469 } else { 2470 refreshRateVote = Vote.forPhysicalRefreshRates( 2471 mRefreshRateInLowZone, mRefreshRateInLowZone); 2472 refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching(); 2473 } 2474 if (mLowZoneRefreshRateForThermals != null) { 2475 RefreshRateRange range = SkinThermalStatusObserver 2476 .findBestMatchingRefreshRateRange(mThermalStatus, 2477 mLowZoneRefreshRateForThermals); 2478 if (range != null) { 2479 refreshRateVote = 2480 Vote.forPhysicalRefreshRates(range.min, range.max); 2481 } 2482 } 2483 } 2484 2485 boolean insideHighZone = hasValidHighZone() 2486 && isInsideHighZone(mBrightness, mAmbientLux); 2487 if (insideHighZone) { 2488 refreshRateVote = 2489 Vote.forPhysicalRefreshRates(mRefreshRateInHighZone, 2490 mRefreshRateInHighZone); 2491 if (mHighZoneRefreshRateForThermals != null) { 2492 RefreshRateRange range = SkinThermalStatusObserver 2493 .findBestMatchingRefreshRateRange(mThermalStatus, 2494 mHighZoneRefreshRateForThermals); 2495 if (range != null) { 2496 refreshRateVote = 2497 Vote.forPhysicalRefreshRates(range.min, range.max); 2498 } 2499 } 2500 refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching(); 2501 } 2502 2503 if (mLoggingEnabled) { 2504 Slog.d(TAG, "Display brightness " + mBrightness + ", ambient lux " + mAmbientLux 2505 + ", Vote " + refreshRateVote); 2506 } 2507 mVotesStorage.updateGlobalVote(Vote.PRIORITY_FLICKER_REFRESH_RATE, refreshRateVote); 2508 mVotesStorage.updateGlobalVote(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, 2509 refreshRateSwitchingVote); 2510 } 2511 hasValidLowZone()2512 private boolean hasValidLowZone() { 2513 return (mRefreshRateInLowZone > 0 || hasLowLightVrrConfig()) 2514 && (mShouldObserveDisplayLowChange || mShouldObserveAmbientLowChange); 2515 } 2516 hasValidHighZone()2517 private boolean hasValidHighZone() { 2518 return mRefreshRateInHighZone > 0 2519 && (mShouldObserveDisplayHighChange || mShouldObserveAmbientHighChange); 2520 } 2521 updateDefaultDisplayState()2522 private void updateDefaultDisplayState() { 2523 Display display = mInjector.getDisplay(Display.DEFAULT_DISPLAY); 2524 if (display == null) { 2525 return; 2526 } 2527 2528 setDefaultDisplayState(display.getState()); 2529 } 2530 2531 @VisibleForTesting setDefaultDisplayState(int state)2532 void setDefaultDisplayState(int state) { 2533 if (mLoggingEnabled) { 2534 Slog.d(TAG, "setDefaultDisplayState: mDefaultDisplayState = " 2535 + mDefaultDisplayState + ", state = " + state); 2536 } 2537 2538 if (mDefaultDisplayState != state) { 2539 mDefaultDisplayState = state; 2540 updateSensorStatus(); 2541 } 2542 } 2543 updateSensorStatus()2544 private void updateSensorStatus() { 2545 if (mSensorManager == null || mLightSensorListener == null) { 2546 return; 2547 } 2548 2549 if (mLoggingEnabled) { 2550 Slog.d(TAG, "updateSensorStatus: mShouldObserveAmbientLowChange = " 2551 + mShouldObserveAmbientLowChange + ", mShouldObserveAmbientHighChange = " 2552 + mShouldObserveAmbientHighChange); 2553 Slog.d(TAG, "updateSensorStatus: mLowPowerModeEnabled = " 2554 + mLowPowerModeEnabled + ", mRefreshRateChangeable = " 2555 + mRefreshRateChangeable); 2556 } 2557 2558 boolean registerForThermals = false; 2559 if (shouldRegisterLightSensor() && isDeviceActive() && !mLowPowerModeEnabled 2560 && mRefreshRateChangeable) { 2561 registerLightSensor(); 2562 registerForThermals = mLowZoneRefreshRateForThermals != null 2563 || mHighZoneRefreshRateForThermals != null; 2564 } else { 2565 unregisterSensorListener(); 2566 } 2567 2568 if (registerForThermals && !mThermalRegistered) { 2569 mThermalRegistered = mInjector.registerThermalServiceListener(mThermalListener); 2570 } else if (!registerForThermals && mThermalRegistered) { 2571 mInjector.unregisterThermalServiceListener(mThermalListener); 2572 mThermalRegistered = false; 2573 synchronized (mLock) { 2574 mThermalStatus = Temperature.THROTTLING_NONE; // reset 2575 } 2576 } 2577 } 2578 shouldRegisterLightSensor()2579 private boolean shouldRegisterLightSensor() { 2580 return mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange 2581 || isIdleScreenRefreshRateConfigDefined(); 2582 } 2583 isIdleScreenRefreshRateConfigDefined()2584 private boolean isIdleScreenRefreshRateConfigDefined() { 2585 return mDisplayManagerFlags.isIdleScreenConfigInSubscribingLightSensorEnabled() 2586 && mIdleScreenRefreshRateTimeoutLuxThresholdPoints != null 2587 && !mIdleScreenRefreshRateTimeoutLuxThresholdPoints.isEmpty(); 2588 } 2589 registerLightSensor()2590 private void registerLightSensor() { 2591 if (mRegisteredLightSensor == mLightSensor) { 2592 return; 2593 } 2594 2595 if (mRegisteredLightSensor != null) { 2596 unregisterSensorListener(); 2597 } 2598 2599 mSensorManager.registerListener(mLightSensorListener, 2600 mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler); 2601 mRegisteredLightSensor = mLightSensor; 2602 if (mLoggingEnabled) { 2603 Slog.d(TAG, "updateSensorStatus: registerListener"); 2604 } 2605 } 2606 unregisterSensorListener()2607 private void unregisterSensorListener() { 2608 mLightSensorListener.removeCallbacks(); 2609 mSensorManager.unregisterListener(mLightSensorListener); 2610 mRegisteredLightSensor = null; 2611 if (mLoggingEnabled) { 2612 Slog.d(TAG, "updateSensorStatus: unregisterListener"); 2613 } 2614 } 2615 isDeviceActive()2616 private boolean isDeviceActive() { 2617 return mDefaultDisplayState == Display.STATE_ON; 2618 } 2619 2620 /** 2621 * Get the brightness value for a display 2622 * @param displayId The ID of the display 2623 * @return The brightness value 2624 */ getBrightness(int displayId)2625 private float getBrightness(int displayId) { 2626 final BrightnessInfo info = mInjector.getBrightnessInfo(displayId); 2627 if (info != null) { 2628 return info.adjustedBrightness; 2629 } 2630 2631 return BRIGHTNESS_INVALID_FLOAT; 2632 } 2633 2634 private final class LightSensorEventListener implements SensorEventListener { 2635 private static final int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS; 2636 private float mLastSensorData; 2637 private long mTimestamp; 2638 private boolean mLoggingEnabled; 2639 dumpLocked(PrintWriter pw)2640 public void dumpLocked(PrintWriter pw) { 2641 pw.println(" mLastSensorData: " + mLastSensorData); 2642 pw.println(" mTimestamp: " + formatTimestamp(mTimestamp)); 2643 } 2644 2645 setLoggingEnabled(boolean loggingEnabled)2646 public void setLoggingEnabled(boolean loggingEnabled) { 2647 if (mLoggingEnabled == loggingEnabled) { 2648 return; 2649 } 2650 mLoggingEnabled = loggingEnabled; 2651 } 2652 2653 @Override onSensorChanged(SensorEvent event)2654 public void onSensorChanged(SensorEvent event) { 2655 mLastSensorData = event.values[0]; 2656 if (mLoggingEnabled) { 2657 Slog.d(TAG, "On sensor changed: " + mLastSensorData); 2658 } 2659 2660 boolean lowZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux, 2661 mLowAmbientBrightnessThresholds); 2662 boolean highZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux, 2663 mHighAmbientBrightnessThresholds); 2664 if ((lowZoneChanged && mLastSensorData < mAmbientLux) 2665 || (highZoneChanged && mLastSensorData > mAmbientLux)) { 2666 // Easier to see flicker at lower brightness environment or high brightness 2667 // environment. Forget the history to get immediate response. 2668 if (mAmbientFilter != null) { 2669 mAmbientFilter.clear(); 2670 } 2671 } 2672 2673 long now = SystemClock.uptimeMillis(); 2674 mTimestamp = System.currentTimeMillis(); 2675 if (mAmbientFilter != null) { 2676 mAmbientFilter.addValue(now, mLastSensorData); 2677 } 2678 2679 mHandler.removeCallbacks(mInjectSensorEventRunnable); 2680 processSensorData(now); 2681 2682 if ((lowZoneChanged && mLastSensorData > mAmbientLux) 2683 || (highZoneChanged && mLastSensorData < mAmbientLux)) { 2684 // Sensor may not report new event if there is no brightness change. 2685 // Need to keep querying the temporal filter for the latest estimation, 2686 // until sensor readout and filter estimation are in the same zone or 2687 // is interrupted by a new sensor event. 2688 mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS); 2689 } 2690 if (mDisplayManagerFlags.isIdleScreenRefreshRateTimeoutEnabled()) { 2691 updateIdleScreenRefreshRate(mAmbientLux); 2692 } 2693 } 2694 2695 @Override onAccuracyChanged(Sensor sensor, int accuracy)2696 public void onAccuracyChanged(Sensor sensor, int accuracy) { 2697 // Not used. 2698 } 2699 removeCallbacks()2700 public void removeCallbacks() { 2701 mHandler.removeCallbacks(mInjectSensorEventRunnable); 2702 } 2703 formatTimestamp(long time)2704 private String formatTimestamp(long time) { 2705 SimpleDateFormat dateFormat = 2706 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); 2707 return dateFormat.format(new Date(time)); 2708 } 2709 processSensorData(long now)2710 private void processSensorData(long now) { 2711 if (mAmbientFilter != null) { 2712 mAmbientLux = mAmbientFilter.getEstimate(now); 2713 } else { 2714 mAmbientLux = mLastSensorData; 2715 } 2716 2717 synchronized (mLock) { 2718 onBrightnessChangedLocked(); 2719 } 2720 } 2721 isDifferentZone(float lux1, float lux2, float[] luxThresholds)2722 private boolean isDifferentZone(float lux1, float lux2, float[] luxThresholds) { 2723 for (final float boundary : luxThresholds) { 2724 // Test each boundary. See if the current value and the new value are at 2725 // different sides. 2726 if ((lux1 <= boundary && lux2 > boundary) 2727 || (lux1 > boundary && lux2 <= boundary)) { 2728 return true; 2729 } 2730 } 2731 2732 return false; 2733 } 2734 2735 private final Runnable mInjectSensorEventRunnable = new Runnable() { 2736 @Override 2737 public void run() { 2738 long now = SystemClock.uptimeMillis(); 2739 // No need to really inject the last event into a temporal filter. 2740 processSensorData(now); 2741 2742 // Inject next event if there is a possible zone change. 2743 if (isDifferentZone(mLastSensorData, mAmbientLux, 2744 mLowAmbientBrightnessThresholds) 2745 || isDifferentZone(mLastSensorData, mAmbientLux, 2746 mHighAmbientBrightnessThresholds)) { 2747 mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS); 2748 } 2749 } 2750 }; 2751 } 2752 updateIdleScreenRefreshRate(float ambientLux)2753 private void updateIdleScreenRefreshRate(float ambientLux) { 2754 if (mIdleScreenRefreshRateTimeoutLuxThresholdPoints == null 2755 || mIdleScreenRefreshRateTimeoutLuxThresholdPoints.isEmpty()) { 2756 mIdleScreenRefreshRateConfig = null; 2757 return; 2758 } 2759 2760 int newTimeout = -1; 2761 for (IdleScreenRefreshRateTimeoutLuxThresholdPoint point : 2762 mIdleScreenRefreshRateTimeoutLuxThresholdPoints) { 2763 int newLux = point.getLux().intValue(); 2764 if (newLux <= ambientLux) { 2765 newTimeout = point.getTimeout().intValue(); 2766 } 2767 } 2768 if (mIdleScreenRefreshRateConfig == null 2769 || newTimeout != mIdleScreenRefreshRateConfig.timeoutMillis) { 2770 mIdleScreenRefreshRateConfig = 2771 new IdleScreenRefreshRateConfig(newTimeout); 2772 synchronized (mLock) { 2773 notifyDesiredDisplayModeSpecsChangedLocked(); 2774 } 2775 } 2776 } 2777 } 2778 2779 private class UdfpsObserver extends IUdfpsRefreshRateRequestCallback.Stub { 2780 private final SparseBooleanArray mUdfpsRefreshRateEnabled = new SparseBooleanArray(); 2781 private final SparseBooleanArray mAuthenticationPossible = new SparseBooleanArray(); 2782 observe()2783 public void observe() { 2784 StatusBarManagerInternal statusBar = mInjector.getStatusBarManagerInternal(); 2785 if (statusBar == null) { 2786 return; 2787 } 2788 2789 // Allow UDFPS vote by registering callback, only 2790 // if the device is configured to not ignore UDFPS vote. 2791 boolean ignoreUdfpsVote = mContext.getResources() 2792 .getBoolean(R.bool.config_ignoreUdfpsVote); 2793 if (!ignoreUdfpsVote) { 2794 statusBar.setUdfpsRefreshRateCallback(this); 2795 } 2796 } 2797 2798 @Override onRequestEnabled(int displayId)2799 public void onRequestEnabled(int displayId) { 2800 synchronized (mLock) { 2801 mUdfpsRefreshRateEnabled.put(displayId, true); 2802 updateVoteLocked(displayId, true, Vote.PRIORITY_UDFPS); 2803 } 2804 } 2805 2806 @Override onRequestDisabled(int displayId)2807 public void onRequestDisabled(int displayId) { 2808 synchronized (mLock) { 2809 mUdfpsRefreshRateEnabled.put(displayId, false); 2810 updateVoteLocked(displayId, false, Vote.PRIORITY_UDFPS); 2811 } 2812 } 2813 2814 @Override onAuthenticationPossible(int displayId, boolean isPossible)2815 public void onAuthenticationPossible(int displayId, boolean isPossible) { 2816 synchronized (mLock) { 2817 mAuthenticationPossible.put(displayId, isPossible); 2818 updateVoteLocked(displayId, isPossible, 2819 Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); 2820 } 2821 } 2822 2823 @GuardedBy("mLock") updateVoteLocked(int displayId, boolean enabled, int votePriority)2824 private void updateVoteLocked(int displayId, boolean enabled, int votePriority) { 2825 final Vote vote; 2826 if (enabled) { 2827 float maxRefreshRate = DisplayModeDirector.this.getMaxRefreshRateLocked(displayId); 2828 vote = Vote.forPhysicalRefreshRates(maxRefreshRate, maxRefreshRate); 2829 } else { 2830 vote = null; 2831 } 2832 mVotesStorage.updateVote(displayId, votePriority, vote); 2833 } 2834 dumpLocked(PrintWriter pw)2835 void dumpLocked(PrintWriter pw) { 2836 pw.println(" UdfpsObserver"); 2837 pw.println(" mUdfpsRefreshRateEnabled: "); 2838 for (int i = 0; i < mUdfpsRefreshRateEnabled.size(); i++) { 2839 final int displayId = mUdfpsRefreshRateEnabled.keyAt(i); 2840 final String enabled = mUdfpsRefreshRateEnabled.valueAt(i) ? "enabled" : "disabled"; 2841 pw.println(" Display " + displayId + ": " + enabled); 2842 } 2843 pw.println(" mAuthenticationPossible: "); 2844 for (int i = 0; i < mAuthenticationPossible.size(); i++) { 2845 final int displayId = mAuthenticationPossible.keyAt(i); 2846 final String isPossible = mAuthenticationPossible.valueAt(i) ? "possible" 2847 : "impossible"; 2848 pw.println(" Display " + displayId + ": " + isPossible); 2849 } 2850 } 2851 } 2852 2853 2854 /** 2855 * Listens to DisplayManager for HBM status and applies any refresh-rate restrictions for 2856 * HBM that are associated with that display. Restrictions are retrieved from 2857 * DisplayManagerInternal but originate in the display-device-config file. 2858 */ 2859 public class HbmObserver implements DisplayManager.DisplayListener { 2860 private final VotesStorage mVotesStorage; 2861 private final Handler mHandler; 2862 private final SparseIntArray mHbmMode = new SparseIntArray(); 2863 private final SparseBooleanArray mHbmActive = new SparseBooleanArray(); 2864 private final Injector mInjector; 2865 private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; 2866 private int mRefreshRateInHbmSunlight; 2867 private int mRefreshRateInHbmHdr; 2868 2869 private DisplayManagerInternal mDisplayManagerInternal; 2870 HbmObserver(Injector injector, VotesStorage votesStorage, Handler handler, DeviceConfigDisplaySettings displaySettings)2871 HbmObserver(Injector injector, VotesStorage votesStorage, Handler handler, 2872 DeviceConfigDisplaySettings displaySettings) { 2873 mInjector = injector; 2874 mVotesStorage = votesStorage; 2875 mHandler = handler; 2876 mDeviceConfigDisplaySettings = displaySettings; 2877 } 2878 2879 /** 2880 * Sets up the refresh rate to be used when HDR is enabled 2881 */ setupHdrRefreshRates(DisplayDeviceConfig displayDeviceConfig)2882 public void setupHdrRefreshRates(DisplayDeviceConfig displayDeviceConfig) { 2883 mRefreshRateInHbmHdr = mDeviceConfigDisplaySettings 2884 .getRefreshRateInHbmHdr(displayDeviceConfig); 2885 mRefreshRateInHbmSunlight = mDeviceConfigDisplaySettings 2886 .getRefreshRateInHbmSunlight(displayDeviceConfig); 2887 } 2888 2889 /** 2890 * Sets up the HDR refresh rates, and starts observing for the changes in the display that 2891 * might impact it 2892 */ observe()2893 public void observe() { 2894 synchronized (mLock) { 2895 setupHdrRefreshRates(mDefaultDisplayDeviceConfig); 2896 } 2897 mDisplayManagerInternal = mInjector.getDisplayManagerInternal(); 2898 mInjector.registerDisplayListener(this, mHandler, 2899 DisplayManager.EVENT_TYPE_DISPLAY_REMOVED, 2900 DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS); 2901 } 2902 2903 /** 2904 * @return the refresh to lock to when the device is in high brightness mode for Sunlight. 2905 */ 2906 @VisibleForTesting getRefreshRateInHbmSunlight()2907 int getRefreshRateInHbmSunlight() { 2908 return mRefreshRateInHbmSunlight; 2909 } 2910 2911 /** 2912 * @return the refresh to lock to when the device is in high brightness mode for HDR. 2913 */ 2914 @VisibleForTesting getRefreshRateInHbmHdr()2915 int getRefreshRateInHbmHdr() { 2916 return mRefreshRateInHbmHdr; 2917 } 2918 2919 /** 2920 * Recalculates the HBM vote when the device config has been changed. 2921 */ onDeviceConfigRefreshRateInHbmSunlightChanged(int refreshRate)2922 public void onDeviceConfigRefreshRateInHbmSunlightChanged(int refreshRate) { 2923 if (refreshRate != mRefreshRateInHbmSunlight) { 2924 mRefreshRateInHbmSunlight = refreshRate; 2925 onDeviceConfigRefreshRateInHbmChanged(); 2926 } 2927 } 2928 2929 /** 2930 * Recalculates the HBM vote when the device config has been changed. 2931 */ onDeviceConfigRefreshRateInHbmHdrChanged(int refreshRate)2932 public void onDeviceConfigRefreshRateInHbmHdrChanged(int refreshRate) { 2933 if (refreshRate != mRefreshRateInHbmHdr) { 2934 mRefreshRateInHbmHdr = refreshRate; 2935 onDeviceConfigRefreshRateInHbmChanged(); 2936 } 2937 } 2938 2939 @Override onDisplayAdded(int displayId)2940 public void onDisplayAdded(int displayId) {} 2941 2942 @Override onDisplayRemoved(int displayId)2943 public void onDisplayRemoved(int displayId) { 2944 mVotesStorage.updateVote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null); 2945 mHbmMode.delete(displayId); 2946 mHbmActive.delete(displayId); 2947 } 2948 2949 @Override onDisplayChanged(int displayId)2950 public void onDisplayChanged(int displayId) { 2951 final BrightnessInfo info = mInjector.getBrightnessInfo(displayId); 2952 if (info == null) { 2953 // Display no longer there. Assume we'll get an onDisplayRemoved very soon. 2954 return; 2955 } 2956 2957 final int hbmMode = info.highBrightnessMode; 2958 final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF 2959 && info.adjustedBrightness > info.highBrightnessTransitionPoint; 2960 if (hbmMode == mHbmMode.get(displayId) 2961 && isHbmActive == mHbmActive.get(displayId)) { 2962 // no change, ignore. 2963 return; 2964 } 2965 mHbmMode.put(displayId, hbmMode); 2966 mHbmActive.put(displayId, isHbmActive); 2967 recalculateVotesForDisplay(displayId); 2968 } 2969 onDeviceConfigRefreshRateInHbmChanged()2970 private void onDeviceConfigRefreshRateInHbmChanged() { 2971 final int[] displayIds = mHbmMode.copyKeys(); 2972 if (displayIds != null) { 2973 for (int id : displayIds) { 2974 recalculateVotesForDisplay(id); 2975 } 2976 } 2977 } 2978 recalculateVotesForDisplay(int displayId)2979 private void recalculateVotesForDisplay(int displayId) { 2980 Vote vote = null; 2981 if (mHbmActive.get(displayId, false)) { 2982 final int hbmMode = 2983 mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF); 2984 if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) { 2985 // Device resource properties take priority over DisplayDeviceConfig 2986 if (mRefreshRateInHbmSunlight > 0) { 2987 vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmSunlight, 2988 mRefreshRateInHbmSunlight); 2989 } else { 2990 final List<RefreshRateLimitation> limits = 2991 mDisplayManagerInternal.getRefreshRateLimitations(displayId); 2992 for (int i = 0; limits != null && i < limits.size(); i++) { 2993 final RefreshRateLimitation limitation = limits.get(i); 2994 if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) { 2995 vote = Vote.forPhysicalRefreshRates(limitation.range.min, 2996 limitation.range.max); 2997 break; 2998 } 2999 } 3000 } 3001 } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR 3002 && mRefreshRateInHbmHdr > 0) { 3003 // HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for 3004 // a vote from Device properties 3005 vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr); 3006 } else { 3007 Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId); 3008 } 3009 3010 } 3011 mVotesStorage.updateVote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote); 3012 } 3013 dumpLocked(PrintWriter pw)3014 void dumpLocked(PrintWriter pw) { 3015 pw.println(" HbmObserver"); 3016 pw.println(" mHbmMode: " + mHbmMode); 3017 pw.println(" mHbmActive: " + mHbmActive); 3018 pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight); 3019 pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr); 3020 } 3021 } 3022 3023 private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener { startListening()3024 public void startListening() { 3025 mConfigParameterProvider.addOnPropertiesChangedListener( 3026 BackgroundThread.getExecutor(), this); 3027 } 3028 getRefreshRateInHbmHdr(DisplayDeviceConfig displayDeviceConfig)3029 private int getRefreshRateInHbmHdr(DisplayDeviceConfig displayDeviceConfig) { 3030 return getRefreshRate( 3031 () -> mConfigParameterProvider.getRefreshRateInHbmHdr(), 3032 () -> displayDeviceConfig.getRefreshRateData().defaultRefreshRateInHbmHdr, 3033 R.integer.config_defaultRefreshRateInHbmHdr, 3034 displayDeviceConfig 3035 ); 3036 } 3037 getRefreshRateInHbmSunlight(DisplayDeviceConfig displayDeviceConfig)3038 private int getRefreshRateInHbmSunlight(DisplayDeviceConfig displayDeviceConfig) { 3039 return getRefreshRate( 3040 () -> mConfigParameterProvider.getRefreshRateInHbmSunlight(), 3041 () -> displayDeviceConfig.getRefreshRateData().defaultRefreshRateInHbmSunlight, 3042 R.integer.config_defaultRefreshRateInHbmSunlight, 3043 displayDeviceConfig 3044 ); 3045 } 3046 getRefreshRate(IntSupplier fromConfigPram, IntSupplier fromDisplayDeviceConfig, @IntegerRes int configKey, DisplayDeviceConfig displayDeviceConfig)3047 private int getRefreshRate(IntSupplier fromConfigPram, IntSupplier fromDisplayDeviceConfig, 3048 @IntegerRes int configKey, DisplayDeviceConfig displayDeviceConfig) { 3049 int refreshRate = -1; 3050 try { 3051 refreshRate = fromConfigPram.getAsInt(); 3052 } catch (NullPointerException npe) { 3053 // Do Nothing 3054 } 3055 if (refreshRate == -1) { 3056 refreshRate = (displayDeviceConfig == null) 3057 ? mContext.getResources().getInteger(configKey) 3058 : fromDisplayDeviceConfig.getAsInt(); 3059 } 3060 return refreshRate; 3061 } 3062 3063 @Override onPropertiesChanged(@onNull DeviceConfig.Properties properties)3064 public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { 3065 float defaultPeakRefreshRate = mConfigParameterProvider.getPeakRefreshRateDefault(); 3066 mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED, 3067 defaultPeakRefreshRate == -1 ? null : defaultPeakRefreshRate).sendToTarget(); 3068 3069 float[] lowDisplayBrightnessThresholds = 3070 mConfigParameterProvider.getLowDisplayBrightnessThresholds(); 3071 float[] lowAmbientBrightnessThresholds = 3072 mConfigParameterProvider.getLowAmbientBrightnessThresholds(); 3073 final int refreshRateInLowZone = mConfigParameterProvider.getRefreshRateInLowZone(); 3074 3075 mHandler.obtainMessage(MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED, 3076 new Pair<>(lowDisplayBrightnessThresholds, lowAmbientBrightnessThresholds)) 3077 .sendToTarget(); 3078 3079 mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone, 3080 0).sendToTarget(); 3081 3082 float[] highDisplayBrightnessThresholds = 3083 mConfigParameterProvider.getHighDisplayBrightnessThresholds(); 3084 float[] highAmbientBrightnessThresholds = 3085 mConfigParameterProvider.getHighAmbientBrightnessThresholds(); 3086 final int refreshRateInHighZone = mConfigParameterProvider.getRefreshRateInHighZone(); 3087 3088 mHandler.obtainMessage(MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED, 3089 new Pair<>(highDisplayBrightnessThresholds, highAmbientBrightnessThresholds)) 3090 .sendToTarget(); 3091 3092 mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 3093 0).sendToTarget(); 3094 3095 synchronized (mLock) { 3096 final int refreshRateInHbmSunlight = 3097 getRefreshRateInHbmSunlight(mDefaultDisplayDeviceConfig); 3098 mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED, 3099 refreshRateInHbmSunlight, 0) 3100 .sendToTarget(); 3101 3102 final int refreshRateInHbmHdr = 3103 getRefreshRateInHbmHdr(mDefaultDisplayDeviceConfig); 3104 mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED, refreshRateInHbmHdr, 0) 3105 .sendToTarget(); 3106 } 3107 } 3108 } 3109 3110 interface Injector { 3111 Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); 3112 Uri MIN_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.MIN_REFRESH_RATE); 3113 3114 @NonNull getDeviceConfig()3115 DeviceConfigInterface getDeviceConfig(); 3116 registerPeakRefreshRateObserver(@onNull ContentResolver cr, @NonNull ContentObserver observer)3117 void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, 3118 @NonNull ContentObserver observer); 3119 registerMinRefreshRateObserver(@onNull ContentResolver cr, @NonNull ContentObserver observer)3120 void registerMinRefreshRateObserver(@NonNull ContentResolver cr, 3121 @NonNull ContentObserver observer); 3122 registerDisplayListener(@onNull DisplayManager.DisplayListener listener, Handler handler)3123 void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, 3124 Handler handler); 3125 registerDisplayListener(@onNull DisplayManager.DisplayListener listener, Handler handler, long flags)3126 void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, 3127 Handler handler, long flags); 3128 registerDisplayListener(@onNull DisplayManager.DisplayListener listener, Handler handler, long flags, long privateFlags)3129 void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, 3130 Handler handler, long flags, long privateFlags); 3131 getDisplay(int displayId)3132 Display getDisplay(int displayId); 3133 getDisplays()3134 Display[] getDisplays(); 3135 getDisplayInfo(int displayId, DisplayInfo displayInfo)3136 boolean getDisplayInfo(int displayId, DisplayInfo displayInfo); 3137 getBrightnessInfo(int displayId)3138 BrightnessInfo getBrightnessInfo(int displayId); 3139 isDozeState(Display d)3140 boolean isDozeState(Display d); 3141 registerThermalServiceListener(IThermalEventListener listener)3142 boolean registerThermalServiceListener(IThermalEventListener listener); unregisterThermalServiceListener(IThermalEventListener listener)3143 void unregisterThermalServiceListener(IThermalEventListener listener); 3144 supportsFrameRateOverride()3145 boolean supportsFrameRateOverride(); 3146 getDisplayManagerInternal()3147 DisplayManagerInternal getDisplayManagerInternal(); 3148 getStatusBarManagerInternal()3149 StatusBarManagerInternal getStatusBarManagerInternal(); 3150 getSensorManagerInternal()3151 SensorManagerInternal getSensorManagerInternal(); 3152 3153 @Nullable getVotesStatsReporter()3154 VotesStatsReporter getVotesStatsReporter(); 3155 } 3156 3157 @VisibleForTesting 3158 static class RealInjector implements Injector { 3159 private final Context mContext; 3160 private DisplayManager mDisplayManager; 3161 RealInjector(Context context)3162 RealInjector(Context context) { 3163 mContext = context; 3164 } 3165 3166 @Override 3167 @NonNull getDeviceConfig()3168 public DeviceConfigInterface getDeviceConfig() { 3169 return DeviceConfigInterface.REAL; 3170 } 3171 3172 @Override registerPeakRefreshRateObserver(@onNull ContentResolver cr, @NonNull ContentObserver observer)3173 public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, 3174 @NonNull ContentObserver observer) { 3175 cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, 3176 observer, UserHandle.USER_ALL); 3177 } 3178 3179 @Override registerMinRefreshRateObserver(@onNull ContentResolver cr, @NonNull ContentObserver observer)3180 public void registerMinRefreshRateObserver(@NonNull ContentResolver cr, 3181 @NonNull ContentObserver observer) { 3182 cr.registerContentObserver(MIN_REFRESH_RATE_URI, false /*notifyDescendants*/, 3183 observer, UserHandle.USER_ALL); 3184 } 3185 3186 @Override registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler)3187 public void registerDisplayListener(DisplayManager.DisplayListener listener, 3188 Handler handler) { 3189 getDisplayManager().registerDisplayListener(listener, handler); 3190 } 3191 3192 @Override registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler, long flags)3193 public void registerDisplayListener(DisplayManager.DisplayListener listener, 3194 Handler handler, long flags) { 3195 getDisplayManager().registerDisplayListener(listener, handler, flags); 3196 } 3197 3198 @Override registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler, long flags, long privateFlags)3199 public void registerDisplayListener(DisplayManager.DisplayListener listener, 3200 Handler handler, long flags, long privateFlags) { 3201 getDisplayManager().registerDisplayListener(listener, handler, flags, privateFlags); 3202 } 3203 3204 @Override getDisplay(int displayId)3205 public Display getDisplay(int displayId) { 3206 return getDisplayManager().getDisplay(displayId); 3207 } 3208 3209 @Override getDisplays()3210 public Display[] getDisplays() { 3211 return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); 3212 } 3213 3214 @Override getDisplayInfo(int displayId, DisplayInfo displayInfo)3215 public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) { 3216 Display display = getDisplayManager().getDisplay(displayId); 3217 if (display == null) { 3218 // We can occasionally get a display added or changed event for a display that was 3219 // subsequently removed, which means this returns null. Check this case and bail 3220 // out early; if it gets re-attached we'll eventually get another call back for it. 3221 return false; 3222 } 3223 return display.getDisplayInfo(displayInfo); 3224 } 3225 3226 @Override getBrightnessInfo(int displayId)3227 public BrightnessInfo getBrightnessInfo(int displayId) { 3228 final Display display = getDisplayManager().getDisplay(displayId); 3229 if (display != null) { 3230 return display.getBrightnessInfo(); 3231 } 3232 return null; 3233 } 3234 3235 @Override isDozeState(Display d)3236 public boolean isDozeState(Display d) { 3237 if (d == null) { 3238 return false; 3239 } 3240 return Display.isDozeState(d.getState()); 3241 } 3242 3243 @Override registerThermalServiceListener(IThermalEventListener listener)3244 public boolean registerThermalServiceListener(IThermalEventListener listener) { 3245 IThermalService thermalService = getThermalService(); 3246 if (thermalService == null) { 3247 Slog.w(TAG, "Could not observe thermal status. Service not available"); 3248 return false; 3249 } 3250 try { 3251 thermalService.registerThermalEventListenerWithType(listener, 3252 Temperature.TYPE_SKIN); 3253 } catch (RemoteException e) { 3254 Slog.e(TAG, "Failed to register thermal status listener", e); 3255 return false; 3256 } 3257 return true; 3258 } 3259 3260 @Override unregisterThermalServiceListener(IThermalEventListener listener)3261 public void unregisterThermalServiceListener(IThermalEventListener listener) { 3262 IThermalService thermalService = getThermalService(); 3263 if (thermalService == null) { 3264 Slog.w(TAG, "Could not unregister thermal status. Service not available"); 3265 } 3266 try { 3267 thermalService.unregisterThermalEventListener(listener); 3268 } catch (RemoteException e) { 3269 Slog.e(TAG, "Failed to unregister thermal status listener", e); 3270 } 3271 } 3272 3273 @Override supportsFrameRateOverride()3274 public boolean supportsFrameRateOverride() { 3275 return SurfaceFlingerProperties.enable_frame_rate_override().orElse(true); 3276 } 3277 3278 @Override getDisplayManagerInternal()3279 public DisplayManagerInternal getDisplayManagerInternal() { 3280 return LocalServices.getService(DisplayManagerInternal.class); 3281 } 3282 3283 @Override getStatusBarManagerInternal()3284 public StatusBarManagerInternal getStatusBarManagerInternal() { 3285 return LocalServices.getService(StatusBarManagerInternal.class); 3286 } 3287 3288 @Override getSensorManagerInternal()3289 public SensorManagerInternal getSensorManagerInternal() { 3290 return LocalServices.getService(SensorManagerInternal.class); 3291 } 3292 3293 @Override getVotesStatsReporter()3294 public VotesStatsReporter getVotesStatsReporter() { 3295 // if frame rate override supported, renderRates will be ignored in mode selection 3296 return new VotesStatsReporter(supportsFrameRateOverride()); 3297 } 3298 getDisplayManager()3299 private DisplayManager getDisplayManager() { 3300 if (mDisplayManager == null) { 3301 mDisplayManager = mContext.getSystemService(DisplayManager.class); 3302 } 3303 return mDisplayManager; 3304 } 3305 getThermalService()3306 private IThermalService getThermalService() { 3307 return IThermalService.Stub.asInterface( 3308 ServiceManager.getService(Context.THERMAL_SERVICE)); 3309 } 3310 } 3311 } 3312