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.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA; 20 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS; 21 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS; 22 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS; 23 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS; 24 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT; 25 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR; 26 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT; 27 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE; 28 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE; 29 30 import static com.android.server.display.mode.Vote.INVALID_SIZE; 31 32 import static com.google.common.truth.Truth.assertThat; 33 34 import static org.junit.Assert.assertArrayEquals; 35 import static org.junit.Assert.assertEquals; 36 import static org.junit.Assert.assertNotNull; 37 import static org.junit.Assert.assertNull; 38 import static org.junit.Assert.assertTrue; 39 import static org.mockito.ArgumentMatchers.anyInt; 40 import static org.mockito.ArgumentMatchers.eq; 41 import static org.mockito.Mockito.any; 42 import static org.mockito.Mockito.atLeastOnce; 43 import static org.mockito.Mockito.doAnswer; 44 import static org.mockito.Mockito.mock; 45 import static org.mockito.Mockito.never; 46 import static org.mockito.Mockito.spy; 47 import static org.mockito.Mockito.verify; 48 import static org.mockito.Mockito.when; 49 import static org.mockito.internal.verification.VerificationModeFactory.times; 50 51 import android.annotation.NonNull; 52 import android.content.ContentResolver; 53 import android.content.Context; 54 import android.content.ContextWrapper; 55 import android.content.res.Resources; 56 import android.database.ContentObserver; 57 import android.hardware.Sensor; 58 import android.hardware.SensorEventListener; 59 import android.hardware.SensorManager; 60 import android.hardware.display.BrightnessInfo; 61 import android.hardware.display.DisplayManager; 62 import android.hardware.display.DisplayManager.DisplayListener; 63 import android.hardware.display.DisplayManagerGlobal; 64 import android.hardware.display.DisplayManagerInternal; 65 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation; 66 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; 67 import android.os.Handler; 68 import android.os.IThermalEventListener; 69 import android.os.Looper; 70 import android.os.RemoteException; 71 import android.os.Temperature; 72 import android.provider.DeviceConfig; 73 import android.provider.Settings; 74 import android.test.mock.MockContentResolver; 75 import android.util.Slog; 76 import android.util.SparseArray; 77 import android.util.TypedValue; 78 import android.view.Display; 79 import android.view.DisplayInfo; 80 import android.view.SurfaceControl.RefreshRateRange; 81 import android.view.SurfaceControl.RefreshRateRanges; 82 83 import androidx.test.core.app.ApplicationProvider; 84 import androidx.test.filters.SmallTest; 85 86 import com.android.internal.R; 87 import com.android.internal.display.BrightnessSynchronizer; 88 import com.android.internal.os.BackgroundThread; 89 import com.android.internal.util.Preconditions; 90 import com.android.internal.util.test.FakeSettingsProvider; 91 import com.android.internal.util.test.FakeSettingsProviderRule; 92 import com.android.server.LocalServices; 93 import com.android.server.display.DisplayDeviceConfig; 94 import com.android.server.display.TestUtils; 95 import com.android.server.display.mode.DisplayModeDirector.BrightnessObserver; 96 import com.android.server.display.mode.DisplayModeDirector.DesiredDisplayModeSpecs; 97 import com.android.server.sensors.SensorManagerInternal; 98 import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener; 99 import com.android.server.statusbar.StatusBarManagerInternal; 100 import com.android.server.testutils.FakeDeviceConfigInterface; 101 102 import org.junit.Before; 103 import org.junit.Rule; 104 import org.junit.Test; 105 import org.junit.runner.RunWith; 106 import org.mockito.ArgumentCaptor; 107 import org.mockito.Mock; 108 import org.mockito.Mockito; 109 import org.mockito.MockitoAnnotations; 110 import org.mockito.stubbing.Answer; 111 112 import java.util.ArrayList; 113 import java.util.Arrays; 114 import java.util.List; 115 import java.util.concurrent.Executor; 116 import java.util.concurrent.TimeUnit; 117 import java.util.stream.Collectors; 118 119 import junitparams.JUnitParamsRunner; 120 import junitparams.Parameters; 121 122 @SmallTest 123 @RunWith(JUnitParamsRunner.class) 124 public class DisplayModeDirectorTest { 125 // The tolerance within which we consider something approximately equals. 126 private static final String TAG = "DisplayModeDirectorTest"; 127 private static final boolean DEBUG = false; 128 private static final float FLOAT_TOLERANCE = 0.01f; 129 private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; 130 private static final int MODE_ID = 1; 131 private static final float TRANSITION_POINT = 0.763f; 132 133 private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY; 134 135 private Context mContext; 136 private FakesInjector mInjector; 137 private Handler mHandler; 138 @Rule 139 public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); 140 @Mock 141 public StatusBarManagerInternal mStatusBarMock; 142 @Mock 143 public SensorManagerInternal mSensorManagerInternalMock; 144 @Mock 145 public DisplayManagerInternal mDisplayManagerInternalMock; 146 147 @Before setUp()148 public void setUp() throws Exception { 149 MockitoAnnotations.initMocks(this); 150 mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); 151 final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext); 152 when(mContext.getContentResolver()).thenReturn(resolver); 153 mInjector = spy(new FakesInjector()); 154 mHandler = new Handler(Looper.getMainLooper()); 155 156 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 157 LocalServices.addService(StatusBarManagerInternal.class, mStatusBarMock); 158 LocalServices.removeServiceForTest(SensorManagerInternal.class); 159 LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock); 160 LocalServices.removeServiceForTest(DisplayManagerInternal.class); 161 LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); 162 } 163 createDirectorFromRefreshRateArray( float[] refreshRates, int baseModeId)164 private DisplayModeDirector createDirectorFromRefreshRateArray( 165 float[] refreshRates, int baseModeId) { 166 return createDirectorFromRefreshRateArray(refreshRates, baseModeId, refreshRates[0]); 167 } 168 createDirectorFromRefreshRateArray( float[] refreshRates, int baseModeId, float defaultRefreshRate)169 private DisplayModeDirector createDirectorFromRefreshRateArray( 170 float[] refreshRates, int baseModeId, float defaultRefreshRate) { 171 Display.Mode[] modes = new Display.Mode[refreshRates.length]; 172 Display.Mode defaultMode = null; 173 for (int i = 0; i < refreshRates.length; i++) { 174 modes[i] = new Display.Mode( 175 /*modeId=*/baseModeId + i, /*width=*/1000, /*height=*/1000, refreshRates[i]); 176 if (refreshRates[i] == defaultRefreshRate) { 177 defaultMode = modes[i]; 178 } 179 } 180 assertThat(defaultMode).isNotNull(); 181 return createDirectorFromModeArray(modes, defaultMode); 182 } 183 createDirectorFromModeArray(Display.Mode[] modes, Display.Mode defaultMode)184 private DisplayModeDirector createDirectorFromModeArray(Display.Mode[] modes, 185 Display.Mode defaultMode) { 186 DisplayModeDirector director = 187 new DisplayModeDirector(mContext, mHandler, mInjector); 188 director.setLoggingEnabled(true); 189 SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); 190 supportedModesByDisplay.put(DISPLAY_ID, modes); 191 director.injectSupportedModesByDisplay(supportedModesByDisplay); 192 SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>(); 193 defaultModesByDisplay.put(DISPLAY_ID, defaultMode); 194 director.injectDefaultModeByDisplay(defaultModesByDisplay); 195 return director; 196 } 197 createDirectorFromFpsRange(int minFps, int maxFps)198 private DisplayModeDirector createDirectorFromFpsRange(int minFps, int maxFps) { 199 int numRefreshRates = maxFps - minFps + 1; 200 float[] refreshRates = new float[numRefreshRates]; 201 for (int i = 0; i < numRefreshRates; i++) { 202 refreshRates[i] = minFps + i; 203 } 204 return createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/minFps, 205 /*defaultRefreshRate=*/minFps); 206 } 207 208 @Test testDisplayModeVoting()209 public void testDisplayModeVoting() { 210 // With no votes present, DisplayModeDirector should allow any refresh rate. 211 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 212 DesiredDisplayModeSpecs modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 213 assertThat(modeSpecs.baseModeId).isEqualTo(60); 214 assertThat(modeSpecs.primary.physical.min).isEqualTo(0f); 215 assertThat(modeSpecs.primary.physical.max).isEqualTo(Float.POSITIVE_INFINITY); 216 assertThat(modeSpecs.primary.render.min).isEqualTo(0f); 217 assertThat(modeSpecs.primary.render.max).isEqualTo(Float.POSITIVE_INFINITY); 218 assertThat(modeSpecs.appRequest.physical.min).isEqualTo(0f); 219 assertThat(modeSpecs.appRequest.physical.max).isEqualTo(Float.POSITIVE_INFINITY); 220 assertThat(modeSpecs.appRequest.render.min).isEqualTo(0f); 221 assertThat(modeSpecs.appRequest.render.max).isEqualTo(Float.POSITIVE_INFINITY); 222 223 int numPriorities = Vote.MAX_PRIORITY - Vote.MIN_PRIORITY + 1; 224 225 // Ensure vote priority works as expected. As we add new votes with higher priority, they 226 // should take precedence over lower priority votes. 227 { 228 int minFps = 60; 229 int maxFps = 90; 230 director = createDirectorFromFpsRange(60, 90); 231 assertTrue(2 * numPriorities < maxFps - minFps + 1); 232 SparseArray<Vote> votes = new SparseArray<>(); 233 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 234 votesByDisplay.put(DISPLAY_ID, votes); 235 for (int i = 0; i < numPriorities; i++) { 236 int priority = Vote.MIN_PRIORITY + i; 237 votes.put(priority, Vote.forPhysicalRefreshRates(minFps + i, maxFps - i)); 238 director.injectVotesByDisplay(votesByDisplay); 239 modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 240 assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i); 241 assertThat(modeSpecs.primary.physical.min) 242 .isEqualTo((float) (minFps + i)); 243 assertThat(modeSpecs.primary.physical.max) 244 .isEqualTo((float) (maxFps - i)); 245 assertThat(modeSpecs.primary.render.min).isZero(); 246 assertThat(modeSpecs.primary.render.max) 247 .isEqualTo((float) (maxFps - i)); 248 if (priority >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF) { 249 assertThat(modeSpecs.appRequest.physical.min) 250 .isEqualTo((float) (minFps + i)); 251 assertThat(modeSpecs.appRequest.physical.max) 252 .isEqualTo((float) (maxFps - i)); 253 assertThat(modeSpecs.appRequest.render.min).isZero(); 254 assertThat(modeSpecs.appRequest.render.max).isEqualTo( 255 (float) (maxFps - i)); 256 } else { 257 assertThat(modeSpecs.appRequest.physical.min).isZero(); 258 assertThat(modeSpecs.appRequest.physical.max).isPositiveInfinity(); 259 assertThat(modeSpecs.appRequest.render.min).isZero(); 260 assertThat(modeSpecs.appRequest.render.max).isPositiveInfinity(); 261 } 262 263 } 264 } 265 266 // Ensure lower priority votes are able to influence the final decision, even in the 267 // presence of higher priority votes. 268 { 269 assertTrue(numPriorities >= 2); 270 director = createDirectorFromFpsRange(60, 90); 271 SparseArray<Vote> votes = new SparseArray<>(); 272 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 273 votesByDisplay.put(DISPLAY_ID, votes); 274 votes.put(Vote.MAX_PRIORITY, Vote.forPhysicalRefreshRates(65, 85)); 275 votes.put(Vote.MIN_PRIORITY, Vote.forPhysicalRefreshRates(70, 80)); 276 director.injectVotesByDisplay(votesByDisplay); 277 modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 278 assertThat(modeSpecs.baseModeId).isEqualTo(70); 279 assertThat(modeSpecs.primary.physical.min).isEqualTo(70f); 280 assertThat(modeSpecs.primary.physical.max).isEqualTo(80f); 281 } 282 } 283 284 @Test testVotingWithFloatingPointErrors()285 public void testVotingWithFloatingPointErrors() { 286 DisplayModeDirector director = createDirectorFromFpsRange(50, 90); 287 SparseArray<Vote> votes = new SparseArray<>(); 288 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 289 votesByDisplay.put(DISPLAY_ID, votes); 290 float error = FLOAT_TOLERANCE / 4; 291 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 292 Vote.forRenderFrameRates(0, 60)); 293 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, 294 Vote.forPhysicalRefreshRates(60 + error, 60 + error)); 295 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 296 Vote.forPhysicalRefreshRates(60 - error, 60 - error)); 297 director.injectVotesByDisplay(votesByDisplay); 298 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 299 300 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 301 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 302 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 303 304 votes.clear(); 305 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 306 Vote.forRenderFrameRates(0, 60 - error)); 307 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 308 Vote.forRenderFrameRates(60 + error, Float.POSITIVE_INFINITY)); 309 director.injectVotesByDisplay(votesByDisplay); 310 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 311 312 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 313 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 314 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 315 } 316 317 @Test testFlickerHasLowerPriorityThanUserAndRangeIsSingle()318 public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle() { 319 assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE 320 < Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 321 assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE 322 < Vote.PRIORITY_APP_REQUEST_SIZE); 323 324 assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH 325 > Vote.PRIORITY_LOW_POWER_MODE); 326 327 Display.Mode[] modes = new Display.Mode[4]; 328 modes[0] = new Display.Mode( 329 /*modeId=*/1, /*width=*/1000, /*height=*/1000, 60); 330 modes[1] = new Display.Mode( 331 /*modeId=*/2, /*width=*/2000, /*height=*/2000, 60); 332 modes[2] = new Display.Mode( 333 /*modeId=*/3, /*width=*/1000, /*height=*/1000, 90); 334 modes[3] = new Display.Mode( 335 /*modeId=*/4, /*width=*/2000, /*height=*/2000, 90); 336 337 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 338 SparseArray<Vote> votes = new SparseArray<>(); 339 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 340 votesByDisplay.put(DISPLAY_ID, votes); 341 Display.Mode appRequestedMode = modes[1]; 342 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 343 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 344 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 345 appRequestedMode.getPhysicalHeight())); 346 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60)); 347 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 348 director.injectVotesByDisplay(votesByDisplay); 349 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 350 assertThat(desiredSpecs.baseModeId).isEqualTo(2); 351 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 352 assertThat(desiredSpecs.primary.physical.max) 353 .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min); 354 355 votes.clear(); 356 appRequestedMode = modes[3]; 357 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 358 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 359 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 360 appRequestedMode.getPhysicalHeight())); 361 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(90, 90)); 362 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 363 director.injectVotesByDisplay(votesByDisplay); 364 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 365 assertThat(desiredSpecs.baseModeId).isEqualTo(4); 366 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 367 assertThat(desiredSpecs.primary.physical.max) 368 .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min); 369 370 votes.clear(); 371 appRequestedMode = modes[3]; 372 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 373 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 374 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 375 appRequestedMode.getPhysicalHeight())); 376 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60)); 377 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 378 director.injectVotesByDisplay(votesByDisplay); 379 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 380 assertThat(desiredSpecs.baseModeId).isEqualTo(4); 381 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 382 assertThat(desiredSpecs.primary.physical.max) 383 .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min); 384 385 votes.clear(); 386 appRequestedMode = modes[1]; 387 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 388 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 389 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 390 appRequestedMode.getPhysicalHeight())); 391 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(90, 90)); 392 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 393 director.injectVotesByDisplay(votesByDisplay); 394 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 395 assertThat(desiredSpecs.baseModeId).isEqualTo(2); 396 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 397 assertThat(desiredSpecs.primary.physical.max) 398 .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min); 399 } 400 401 @Test 402 public void testLPMHasHigherPriorityThanUser() { 403 assertTrue(Vote.PRIORITY_LOW_POWER_MODE 404 > Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 405 assertTrue(Vote.PRIORITY_LOW_POWER_MODE 406 > Vote.PRIORITY_APP_REQUEST_SIZE); 407 408 Display.Mode[] modes = new Display.Mode[4]; 409 modes[0] = new Display.Mode( 410 /*modeId=*/1, /*width=*/1000, /*height=*/1000, 60); 411 modes[1] = new Display.Mode( 412 /*modeId=*/2, /*width=*/2000, /*height=*/2000, 60); 413 modes[2] = new Display.Mode( 414 /*modeId=*/3, /*width=*/1000, /*height=*/1000, 90); 415 modes[3] = new Display.Mode( 416 /*modeId=*/4, /*width=*/2000, /*height=*/2000, 90); 417 418 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 419 SparseArray<Vote> votes = new SparseArray<>(); 420 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 421 votesByDisplay.put(DISPLAY_ID, votes); 422 Display.Mode appRequestedMode = modes[1]; 423 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 424 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 425 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 426 appRequestedMode.getPhysicalHeight())); 427 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(60, 60)); 428 director.injectVotesByDisplay(votesByDisplay); 429 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 430 assertThat(desiredSpecs.baseModeId).isEqualTo(2); 431 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 432 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 433 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 434 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 435 436 votes.clear(); 437 appRequestedMode = modes[3]; 438 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 439 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 440 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 441 appRequestedMode.getPhysicalHeight())); 442 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90)); 443 director.injectVotesByDisplay(votesByDisplay); 444 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 445 assertThat(desiredSpecs.baseModeId).isEqualTo(4); 446 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 447 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 448 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90); 449 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90); 450 451 votes.clear(); 452 appRequestedMode = modes[3]; 453 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 454 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 455 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 456 appRequestedMode.getPhysicalHeight())); 457 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(60, 60)); 458 director.injectVotesByDisplay(votesByDisplay); 459 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 460 assertThat(desiredSpecs.baseModeId).isEqualTo(2); 461 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 462 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 463 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 464 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 465 466 votes.clear(); 467 appRequestedMode = modes[1]; 468 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 469 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 470 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 471 appRequestedMode.getPhysicalHeight())); 472 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90)); 473 director.injectVotesByDisplay(votesByDisplay); 474 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 475 assertThat(desiredSpecs.baseModeId).isEqualTo(4); 476 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 477 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 478 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90); 479 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90); 480 } 481 482 @Test testAppRequestRefreshRateRange()483 public void testAppRequestRefreshRateRange() { 484 // Confirm that the app request range doesn't include flicker or min refresh rate settings, 485 // but does include everything else. 486 assertTrue( 487 Vote.PRIORITY_FLICKER_REFRESH_RATE 488 < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF); 489 assertTrue(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE 490 < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF); 491 assertTrue(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE 492 >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF); 493 494 Display.Mode[] modes = new Display.Mode[3]; 495 modes[0] = new Display.Mode( 496 /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60); 497 modes[1] = new Display.Mode( 498 /*modeId=*/75, /*width=*/2000, /*height=*/2000, 75); 499 modes[2] = new Display.Mode( 500 /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90); 501 502 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 503 SparseArray<Vote> votes = new SparseArray<>(); 504 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 505 votesByDisplay.put(DISPLAY_ID, votes); 506 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60)); 507 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 508 director.injectVotesByDisplay(votesByDisplay); 509 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 510 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 511 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 512 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 513 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 514 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 515 516 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 517 Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY)); 518 director.injectVotesByDisplay(votesByDisplay); 519 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 520 assertThat(desiredSpecs.baseModeId).isEqualTo(90); 521 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 522 assertThat(desiredSpecs.primary.physical.max).isAtLeast(90f); 523 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 524 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 525 526 Display.Mode appRequestedMode = modes[1]; 527 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 528 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 529 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 530 appRequestedMode.getPhysicalHeight())); 531 director.injectVotesByDisplay(votesByDisplay); 532 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 533 assertThat(desiredSpecs.baseModeId).isEqualTo(75); 534 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(75); 535 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(75); 536 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 537 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 538 } 539 540 void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps, 541 float peakFps, float defaultFps, RefreshRateRanges primary, 542 RefreshRateRanges appRequest) { 543 DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings( 544 minFps, peakFps, defaultFps); 545 assertThat(specs.primary).isEqualTo(primary); 546 assertThat(specs.appRequest).isEqualTo(appRequest); 547 } 548 549 @Test 550 public void testSpecsFromRefreshRateSettings() { 551 // Confirm that, with varying settings for min, peak, and default refresh rate, 552 // DesiredDisplayModeSpecs is calculated correctly. 553 float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f}; 554 DisplayModeDirector director = 555 createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0); 556 557 float inf = Float.POSITIVE_INFINITY; 558 RefreshRateRange rangeAll = new RefreshRateRange(0, inf); 559 RefreshRateRange range0to60 = new RefreshRateRange(0, 60); 560 RefreshRateRange range0to90 = new RefreshRateRange(0, 90); 561 RefreshRateRange range0to120 = new RefreshRateRange(0, 120); 562 RefreshRateRange range60to90 = new RefreshRateRange(60, 90); 563 RefreshRateRange range90to90 = new RefreshRateRange(90, 90); 564 RefreshRateRange range90to120 = new RefreshRateRange(90, 120); 565 RefreshRateRange range60toInf = new RefreshRateRange(60, inf); 566 RefreshRateRange range90toInf = new RefreshRateRange(90, inf); 567 568 RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll); 569 RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf); 570 RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60); 571 RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90); 572 RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120); 573 RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90); 574 RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90); 575 RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120); 576 577 verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll); 578 verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll); 579 verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90); 580 verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90); 581 verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90, 582 frameRate0to90); 583 verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll); 584 verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120, 585 frameRateAll); 586 verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll); 587 verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120, 588 frameRate0to120); 589 verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90, 590 frameRate0to90); 591 verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90, 592 frameRate0to120); 593 } 594 595 void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps, 596 float defaultFps, float brightnessObserverMin, float brightnessObserverMax) { 597 BrightnessObserver brightnessObserver = mock(BrightnessObserver.class); 598 director.injectBrightnessObserver(brightnessObserver); 599 director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(minFps, peakFps, defaultFps); 600 verify(brightnessObserver) 601 .onRefreshRateSettingChangedLocked(brightnessObserverMin, brightnessObserverMax); 602 } 603 604 @Test 605 public void testBrightnessObserverCallWithRefreshRateSettings() { 606 // Confirm that, with varying settings for min, peak, and default refresh rate, we make the 607 // correct call to the brightness observer. 608 float[] refreshRates = {60.f, 90.f, 120.f}; 609 DisplayModeDirector director = 610 createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0); 611 verifyBrightnessObserverCall(director, 0, 0, 0, 0, 0); 612 verifyBrightnessObserverCall(director, 0, 0, 90, 0, 90); 613 verifyBrightnessObserverCall(director, 0, 90, 0, 0, 90); 614 verifyBrightnessObserverCall(director, 0, 90, 60, 0, 60); 615 verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90); 616 verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90); 617 } 618 619 @Test 620 public void testBrightnessObserver_LowPowerModeRemovesFlickerVotes() { 621 float[] refreshRates = {60.f, 90.f, 120.f}; 622 DisplayModeDirector director = 623 createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0); 624 SparseArray<Vote> votes = new SparseArray<>(); 625 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 626 votesByDisplay.put(-1, votes); // Global Vote 627 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(0, 60)); 628 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forRenderFrameRates(60, 90)); 629 director.injectVotesByDisplay(votesByDisplay); 630 631 director.getBrightnessObserver().onLowPowerModeEnabledLocked(true); 632 633 assertNull(director.getVote(-1, Vote.PRIORITY_FLICKER_REFRESH_RATE)); 634 assertNull(director.getVote(-1, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH)); 635 } 636 637 @Test 638 public void testVotingWithAlwaysRespectAppRequest() { 639 Display.Mode[] modes = new Display.Mode[3]; 640 modes[0] = new Display.Mode( 641 /*modeId=*/50, /*width=*/1000, /*height=*/1000, 50); 642 modes[1] = new Display.Mode( 643 /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60); 644 modes[2] = new Display.Mode( 645 /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90); 646 647 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 648 649 SparseArray<Vote> votes = new SparseArray<>(); 650 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 651 votesByDisplay.put(DISPLAY_ID, votes); 652 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(0, 60)); 653 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 654 Vote.forRenderFrameRates(60, 90)); 655 Display.Mode appRequestedMode = modes[2]; 656 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 657 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 658 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 659 Vote.forRenderFrameRates(60, 60)); 660 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 661 director.injectVotesByDisplay(votesByDisplay); 662 663 assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); 664 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 665 666 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 667 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 668 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 669 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 670 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 671 672 director.setShouldAlwaysRespectAppRequestedMode(true); 673 assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue(); 674 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 675 assertThat(desiredSpecs.primary.physical.min).isAtMost(50); 676 assertThat(desiredSpecs.primary.physical.max).isAtLeast(90); 677 assertThat(desiredSpecs.primary.render.min).isAtMost(50); 678 assertThat(desiredSpecs.primary.render.max).isAtLeast(90); 679 assertThat(desiredSpecs.baseModeId).isEqualTo(90); 680 681 director.setShouldAlwaysRespectAppRequestedMode(false); 682 assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); 683 684 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 685 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 686 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 687 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 688 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 689 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 690 } 691 692 @Test 693 public void testVotingWithSwitchingTypeNone() { 694 DisplayModeDirector director = createDirectorFromFpsRange(0, 90); 695 SparseArray<Vote> votes = new SparseArray<>(); 696 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 697 votesByDisplay.put(DISPLAY_ID, votes); 698 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 699 Vote.forRenderFrameRates(30, 90)); 700 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 701 702 director.injectVotesByDisplay(votesByDisplay); 703 assertThat(director.getModeSwitchingType()) 704 .isNotEqualTo(DisplayManager.SWITCHING_TYPE_NONE); 705 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 706 707 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 708 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 709 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30); 710 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 711 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 712 assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity(); 713 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0); 714 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 715 assertThat(desiredSpecs.baseModeId).isEqualTo(30); 716 717 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_NONE); 718 assertThat(director.getModeSwitchingType()) 719 .isEqualTo(DisplayManager.SWITCHING_TYPE_NONE); 720 721 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 722 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 723 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(30); 724 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30); 725 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(30); 726 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 727 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(30); 728 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(30); 729 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30); 730 assertThat(desiredSpecs.baseModeId).isEqualTo(30); 731 } 732 733 @Test 734 public void testVotingWithSwitchingTypeRenderFrameRateOnly() { 735 DisplayModeDirector director = createDirectorFromFpsRange(0, 90); 736 SparseArray<Vote> votes = new SparseArray<>(); 737 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 738 votesByDisplay.put(DISPLAY_ID, votes); 739 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 740 Vote.forRenderFrameRates(30, 90)); 741 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 742 743 director.injectVotesByDisplay(votesByDisplay); 744 assertThat(director.getModeSwitchingType()) 745 .isNotEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 746 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 747 748 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 749 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 750 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30); 751 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 752 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 753 assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity(); 754 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0); 755 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 756 assertThat(desiredSpecs.baseModeId).isEqualTo(30); 757 758 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 759 assertThat(director.getModeSwitchingType()) 760 .isEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 761 762 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 763 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 764 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(30); 765 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30); 766 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(30); 767 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 768 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(30); 769 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0); 770 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30); 771 772 assertThat(desiredSpecs.baseModeId).isEqualTo(30); 773 } 774 775 @Test 776 public void testVotingWithSwitchingTypeRenderFrameRateOnlyRenderRateIsNotPhysicalRefreshRate() { 777 DisplayModeDirector director = createDirectorFromFpsRange(60, 120); 778 SparseArray<Vote> votes = new SparseArray<>(); 779 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 780 votesByDisplay.put(DISPLAY_ID, votes); 781 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 782 Vote.forRenderFrameRates(30, 90)); 783 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 784 785 director.injectVotesByDisplay(votesByDisplay); 786 assertThat(director.getModeSwitchingType()) 787 .isNotEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 788 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 789 790 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30); 791 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 792 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30); 793 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 794 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 795 assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity(); 796 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0); 797 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 798 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 799 800 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 801 assertThat(director.getModeSwitchingType()) 802 .isEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); 803 804 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 805 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 806 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 807 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60); 808 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 809 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 810 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 811 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0); 812 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 813 814 assertThat(desiredSpecs.baseModeId).isEqualTo(60); 815 } 816 817 @Test 818 public void testVotingWithSwitchingTypeWithinGroups() { 819 DisplayModeDirector director = createDirectorFromFpsRange(0, 90); 820 821 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); 822 assertThat(director.getModeSwitchingType()) 823 .isEqualTo(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); 824 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 825 assertThat(desiredSpecs.allowGroupSwitching).isFalse(); 826 } 827 828 @Test 829 public void testVotingWithSwitchingTypeWithinAndAcrossGroups() { 830 DisplayModeDirector director = createDirectorFromFpsRange(0, 90); 831 832 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); 833 assertThat(director.getModeSwitchingType()) 834 .isEqualTo(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); 835 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 836 assertThat(desiredSpecs.allowGroupSwitching).isTrue(); 837 } 838 839 @Test 840 public void testDefaultDisplayModeIsSelectedIfAvailable() { 841 final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f}; 842 final int defaultModeId = 3; 843 DisplayModeDirector director = createDirectorFromRefreshRateArray( 844 refreshRates, /*baseModeId=*/0, refreshRates[defaultModeId]); 845 846 DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 847 assertThat(specs.baseModeId).isEqualTo(defaultModeId); 848 } 849 850 @Test 851 public void testStaleAppRequestSize() { 852 DisplayModeDirector director = 853 new DisplayModeDirector(mContext, mHandler, mInjector); 854 Display.Mode[] modes = new Display.Mode[] { 855 new Display.Mode(1, 1280, 720, 60), 856 }; 857 Display.Mode defaultMode = modes[0]; 858 859 // Inject supported modes 860 SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); 861 supportedModesByDisplay.put(DISPLAY_ID, modes); 862 director.injectSupportedModesByDisplay(supportedModesByDisplay); 863 864 // Inject default mode 865 SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>(); 866 defaultModesByDisplay.put(DISPLAY_ID, defaultMode); 867 director.injectDefaultModeByDisplay(defaultModesByDisplay); 868 869 // Inject votes 870 SparseArray<Vote> votes = new SparseArray<>(); 871 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(1920, 1080)); 872 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 873 Vote.forBaseModeRefreshRate(60)); 874 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 875 votesByDisplay.put(DISPLAY_ID, votes); 876 director.injectVotesByDisplay(votesByDisplay); 877 878 director.setShouldAlwaysRespectAppRequestedMode(true); 879 880 // We should return the only available mode 881 DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 882 assertThat(specs.baseModeId).isEqualTo(defaultMode.getModeId()); 883 } 884 885 @Test 886 public void testBrightnessObserverGetsUpdatedRefreshRatesForZone() { 887 DisplayModeDirector director = 888 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0); 889 SensorManager sensorManager = createMockSensorManager(createLightSensor()); 890 891 final int initialRefreshRate = 60; 892 mInjector.getDeviceConfig().setRefreshRateInLowZone(initialRefreshRate); 893 director.start(sensorManager); 894 assertThat(director.getBrightnessObserver().getRefreshRateInLowZone()) 895 .isEqualTo(initialRefreshRate); 896 897 final int updatedRefreshRate = 90; 898 mInjector.getDeviceConfig().setRefreshRateInLowZone(updatedRefreshRate); 899 // Need to wait for the property change to propagate to the main thread. 900 waitForIdleSync(); 901 assertThat(director.getBrightnessObserver().getRefreshRateInLowZone()) 902 .isEqualTo(updatedRefreshRate); 903 } 904 905 @Test 906 public void testBrightnessObserverThresholdsInZone() { 907 DisplayModeDirector director = 908 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0); 909 SensorManager sensorManager = createMockSensorManager(createLightSensor()); 910 911 final int[] initialDisplayThresholds = { 10 }; 912 final int[] initialAmbientThresholds = { 20 }; 913 914 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 915 config.setLowDisplayBrightnessThresholds(initialDisplayThresholds); 916 config.setLowAmbientBrightnessThresholds(initialAmbientThresholds); 917 director.start(sensorManager); 918 919 float[] expectedDisplayThresholds = { BrightnessSynchronizer.brightnessIntToFloat(10) }; 920 float[] expectedAmbientThresholds = { 20 }; 921 assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds()) 922 .isEqualTo(expectedDisplayThresholds); 923 assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds()) 924 .isEqualTo(expectedAmbientThresholds); 925 926 final int[] updatedDisplayThresholds = { 9, 14 }; 927 final int[] updatedAmbientThresholds = { -1, 19 }; 928 config.setLowDisplayBrightnessThresholds(updatedDisplayThresholds); 929 config.setLowAmbientBrightnessThresholds(updatedAmbientThresholds); 930 // Need to wait for the property change to propagate to the main thread. 931 waitForIdleSync(); 932 933 expectedDisplayThresholds = new float[]{ BrightnessSynchronizer.brightnessIntToFloat(9), 934 BrightnessSynchronizer.brightnessIntToFloat(14) }; 935 expectedAmbientThresholds = new float[]{ -1, 19 }; 936 assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds()) 937 .isEqualTo(expectedDisplayThresholds); 938 assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds()) 939 .isEqualTo(expectedAmbientThresholds); 940 } 941 942 @Test 943 public void setBrightness_doesNotLockFpsIfSmoothDisplayIsOff() { 944 DisplayModeDirector director = 945 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 946 setPeakRefreshRate(60); // set smooth display OFF 947 director.getSettingsObserver().setDefaultRefreshRate(90); 948 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 949 950 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 951 config.setRefreshRateInLowZone(90); 952 config.setLowDisplayBrightnessThresholds(new int[] { 10 }); 953 config.setLowAmbientBrightnessThresholds(new int[] { 20 }); 954 955 director.start(createMockSensorManager(createLightSensor())); 956 957 ArgumentCaptor<DisplayListener> displayListenerCaptor = 958 ArgumentCaptor.forClass(DisplayListener.class); 959 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 960 any(Handler.class), 961 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 962 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 963 DisplayListener displayListener = displayListenerCaptor.getValue(); 964 965 setBrightness(10, 10, displayListener); 966 967 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 968 assertThat(vote).isNull(); 969 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 970 assertThat(vote).isNull(); 971 } 972 973 @Test 974 public void setBrightness_locksFpsIfSmoothDisplayIsOn() { 975 DisplayModeDirector director = 976 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 977 setPeakRefreshRate(90); // set smooth display ON 978 director.getSettingsObserver().setDefaultRefreshRate(90); 979 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 980 981 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 982 config.setRefreshRateInLowZone(90); 983 config.setLowDisplayBrightnessThresholds(new int[] { 10 }); 984 config.setLowAmbientBrightnessThresholds(new int[] { 20 }); 985 986 director.start(createMockSensorManager(createLightSensor())); 987 988 ArgumentCaptor<DisplayListener> displayListenerCaptor = 989 ArgumentCaptor.forClass(DisplayListener.class); 990 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 991 any(Handler.class), 992 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 993 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 994 DisplayListener displayListener = displayListenerCaptor.getValue(); 995 996 setBrightness(10, 10, displayListener); 997 998 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 999 assertVoteForPhysicalRefreshRate(vote, 90 /*fps*/); 1000 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1001 assertThat(vote).isNotNull(); 1002 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1003 } 1004 1005 @Test 1006 public void setBrightness_doesNotLockFpsIfSmoothDisplayIsOnAndLowPowerMode() { 1007 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.LOW_POWER_MODE, 1); 1008 DisplayModeDirector director = 1009 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 1010 setPeakRefreshRate(90); // set smooth display ON 1011 director.getSettingsObserver().setDefaultRefreshRate(90); 1012 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1013 1014 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1015 config.setRefreshRateInLowZone(90); 1016 config.setLowDisplayBrightnessThresholds(new int[] { 10 }); 1017 config.setLowAmbientBrightnessThresholds(new int[] { 20 }); 1018 1019 director.start(createMockSensorManager(createLightSensor())); 1020 1021 ArgumentCaptor<DisplayListener> displayListenerCaptor = 1022 ArgumentCaptor.forClass(DisplayListener.class); 1023 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 1024 any(Handler.class), 1025 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 1026 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 1027 DisplayListener displayListener = displayListenerCaptor.getValue(); 1028 1029 setBrightness(10, 10, displayListener); 1030 1031 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1032 assertThat(vote).isNull(); 1033 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1034 assertThat(vote).isNull(); 1035 } 1036 1037 @Test 1038 public void testLockFpsForLowZone() throws Exception { 1039 DisplayModeDirector director = 1040 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 1041 setPeakRefreshRate(90); 1042 director.getSettingsObserver().setDefaultRefreshRate(90); 1043 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1044 1045 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1046 config.setRefreshRateInLowZone(90); 1047 config.setLowDisplayBrightnessThresholds(new int[] { 10 }); 1048 config.setLowAmbientBrightnessThresholds(new int[] { 20 }); 1049 1050 Sensor lightSensor = createLightSensor(); 1051 SensorManager sensorManager = createMockSensorManager(lightSensor); 1052 1053 director.start(sensorManager); 1054 1055 ArgumentCaptor<DisplayListener> displayListenerCaptor = 1056 ArgumentCaptor.forClass(DisplayListener.class); 1057 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 1058 any(Handler.class), 1059 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 1060 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 1061 DisplayListener displayListener = displayListenerCaptor.getValue(); 1062 1063 ArgumentCaptor<SensorEventListener> sensorListenerCaptor = 1064 ArgumentCaptor.forClass(SensorEventListener.class); 1065 Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 1066 .registerListener( 1067 sensorListenerCaptor.capture(), 1068 eq(lightSensor), 1069 anyInt(), 1070 any(Handler.class)); 1071 SensorEventListener sensorListener = sensorListenerCaptor.getValue(); 1072 1073 setBrightness(10, 10, displayListener); 1074 // Sensor reads 20 lux, 1075 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/)); 1076 1077 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1078 assertVoteForPhysicalRefreshRate(vote, 90 /*fps*/); 1079 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1080 assertThat(vote).isNotNull(); 1081 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1082 1083 // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this 1084 // parameter to the necessary threshold 1085 setBrightness(10, 125, displayListener); 1086 // Sensor reads 1000 lux, 1087 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/)); 1088 1089 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1090 assertThat(vote).isNull(); 1091 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1092 assertThat(vote).isNull(); 1093 } 1094 1095 @Test 1096 public void testLockFpsForHighZone() throws Exception { 1097 DisplayModeDirector director = 1098 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 1099 setPeakRefreshRate(90 /*fps*/); 1100 director.getSettingsObserver().setDefaultRefreshRate(90); 1101 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1102 1103 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1104 config.setRefreshRateInHighZone(60); 1105 config.setHighDisplayBrightnessThresholds(new int[] { 255 }); 1106 config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); 1107 1108 Sensor lightSensor = createLightSensor(); 1109 SensorManager sensorManager = createMockSensorManager(lightSensor); 1110 1111 director.start(sensorManager); 1112 1113 ArgumentCaptor<DisplayListener> displayListenerCaptor = 1114 ArgumentCaptor.forClass(DisplayListener.class); 1115 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 1116 any(Handler.class), 1117 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 1118 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 1119 DisplayListener displayListener = displayListenerCaptor.getValue(); 1120 1121 ArgumentCaptor<SensorEventListener> listenerCaptor = 1122 ArgumentCaptor.forClass(SensorEventListener.class); 1123 verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 1124 .registerListener( 1125 listenerCaptor.capture(), 1126 eq(lightSensor), 1127 anyInt(), 1128 any(Handler.class)); 1129 SensorEventListener sensorListener = listenerCaptor.getValue(); 1130 1131 setBrightness(100, 100, displayListener); 1132 // Sensor reads 2000 lux, 1133 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); 1134 1135 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1136 assertThat(vote).isNull(); 1137 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1138 assertThat(vote).isNull(); 1139 1140 // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this 1141 // parameter to the necessary threshold 1142 setBrightness(100, 255, displayListener); 1143 // Sensor reads 9000 lux, 1144 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); 1145 1146 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1147 assertVoteForPhysicalRefreshRate(vote, 60 /*fps*/); 1148 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1149 assertThat(vote).isNotNull(); 1150 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1151 } 1152 1153 @Test 1154 public void testLockFpsForHighZoneWithThermalCondition() throws Exception { 1155 // First, configure brightness zones or DMD won't register for sensor data. 1156 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1157 config.setHighDisplayBrightnessThresholds(new int[] { 200 }); 1158 config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); 1159 1160 DisplayModeDirector director = 1161 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 120.f}, 0); 1162 setPeakRefreshRate(120 /*fps*/); 1163 director.getSettingsObserver().setDefaultRefreshRate(120); 1164 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1165 1166 // Set the thresholds for High Zone 1167 DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class); 1168 when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(90); 1169 when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[] { 200 }); 1170 when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[] { 8000 }); 1171 when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(90); 1172 when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new float[] {}); 1173 when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new float[] {}); 1174 1175 // Set the thermal condition for refresh rate range 1176 when(ddcMock.getHighBlockingZoneThermalMap()).thenReturn( 1177 new SparseArray<RefreshRateRange>() {{ 1178 put(Temperature.THROTTLING_CRITICAL, new RefreshRateRange(60, 60)); 1179 }} 1180 ); 1181 director.defaultDisplayDeviceUpdated(ddcMock); // set the ddc 1182 1183 Sensor lightSensor = createLightSensor(); 1184 SensorManager sensorManager = createMockSensorManager(lightSensor); 1185 director.start(sensorManager); 1186 1187 // Get the display listener so that we can send it new brightness events 1188 ArgumentCaptor<DisplayListener> displayListenerCaptor = 1189 ArgumentCaptor.forClass(DisplayListener.class); 1190 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 1191 any(Handler.class), 1192 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 1193 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 1194 DisplayListener displayListener = displayListenerCaptor.getValue(); 1195 1196 // Get the sensor listener so that we can give it new light sensor events 1197 ArgumentCaptor<SensorEventListener> listenerCaptor = 1198 ArgumentCaptor.forClass(SensorEventListener.class); 1199 verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 1200 .registerListener( 1201 listenerCaptor.capture(), 1202 eq(lightSensor), 1203 anyInt(), 1204 any(Handler.class)); 1205 SensorEventListener sensorListener = listenerCaptor.getValue(); 1206 1207 // Get the thermal listener so that we can give it new thermal conditions 1208 ArgumentCaptor<IThermalEventListener> thermalListenerCaptor = 1209 ArgumentCaptor.forClass(IThermalEventListener.class); 1210 verify(mInjector, atLeastOnce()).registerThermalServiceListener( 1211 thermalListenerCaptor.capture()); 1212 List<IThermalEventListener> thermalListeners = thermalListenerCaptor.getAllValues(); 1213 1214 setBrightness(100, 100, displayListener); 1215 // Sensor reads 2000 lux, 1216 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); 1217 1218 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1219 assertThat(vote).isNull(); 1220 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1221 assertThat(vote).isNull(); 1222 1223 // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this 1224 // parameter to the necessary threshold 1225 setBrightness(255, 255, displayListener); 1226 // Sensor reads 9000 lux, 1227 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); 1228 1229 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1230 assertVoteForPhysicalRefreshRate(vote, 90 /*fps*/); 1231 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1232 assertThat(vote).isNotNull(); 1233 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1234 1235 // Set critical and check new refresh rate 1236 Temperature temp = getSkinTemp(Temperature.THROTTLING_CRITICAL); 1237 for (var listener : thermalListeners) { 1238 listener.notifyThrottling(temp); 1239 } 1240 1241 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1242 assertVoteForPhysicalRefreshRate(vote, 60 /*fps*/); 1243 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1244 assertThat(vote).isNotNull(); 1245 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1246 } 1247 1248 @Test 1249 public void testLockFpsForLowZoneWithThermalCondition() throws Exception { 1250 // First, configure brightness zones or DMD won't register for sensor data. 1251 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1252 config.setHighDisplayBrightnessThresholds(new int[] { 200 }); 1253 config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); 1254 1255 DisplayModeDirector director = 1256 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 120.f}, 0); 1257 setPeakRefreshRate(120 /*fps*/); 1258 director.getSettingsObserver().setDefaultRefreshRate(120); 1259 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1260 1261 // Set the thresholds for Low Zone 1262 DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class); 1263 when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(90); 1264 when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[] { 200 }); 1265 when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[] { 8000 }); 1266 when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(90); 1267 when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new float[] { 10 }); 1268 when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new float[] { 10 }); 1269 1270 // Set the thermal condition for refresh rate range 1271 when(ddcMock.getLowBlockingZoneThermalMap()).thenReturn( 1272 new SparseArray<RefreshRateRange>() {{ 1273 put(Temperature.THROTTLING_CRITICAL, new RefreshRateRange(60, 60)); 1274 }} 1275 ); 1276 director.defaultDisplayDeviceUpdated(ddcMock); // set the ddc 1277 1278 Sensor lightSensor = createLightSensor(); 1279 SensorManager sensorManager = createMockSensorManager(lightSensor); 1280 director.start(sensorManager); 1281 1282 // Get the display listener so that we can send it new brightness events 1283 ArgumentCaptor<DisplayListener> displayListenerCaptor = 1284 ArgumentCaptor.forClass(DisplayListener.class); 1285 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 1286 any(Handler.class), 1287 eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 1288 | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); 1289 DisplayListener displayListener = displayListenerCaptor.getValue(); 1290 1291 // Get the sensor listener so that we can give it new light sensor events 1292 ArgumentCaptor<SensorEventListener> listenerCaptor = 1293 ArgumentCaptor.forClass(SensorEventListener.class); 1294 verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 1295 .registerListener( 1296 listenerCaptor.capture(), 1297 eq(lightSensor), 1298 anyInt(), 1299 any(Handler.class)); 1300 SensorEventListener sensorListener = listenerCaptor.getValue(); 1301 1302 // Get the thermal listener so that we can give it new thermal conditions 1303 ArgumentCaptor<IThermalEventListener> thermalListenerCaptor = 1304 ArgumentCaptor.forClass(IThermalEventListener.class); 1305 verify(mInjector, atLeastOnce()).registerThermalServiceListener( 1306 thermalListenerCaptor.capture()); 1307 List<IThermalEventListener> thermalListeners = thermalListenerCaptor.getAllValues(); 1308 1309 setBrightness(100, 100, displayListener); 1310 // Sensor reads 2000 lux, 1311 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); 1312 1313 Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1314 assertThat(vote).isNull(); 1315 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1316 assertThat(vote).isNull(); 1317 1318 // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this 1319 // parameter to the necessary threshold 1320 setBrightness(5, 5, displayListener); 1321 // Sensor reads 9 lux, 1322 sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9)); 1323 1324 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1325 assertVoteForPhysicalRefreshRate(vote, 90 /*fps*/); 1326 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1327 assertThat(vote).isNotNull(); 1328 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1329 1330 // Set critical and check new refresh rate 1331 Temperature temp = getSkinTemp(Temperature.THROTTLING_CRITICAL); 1332 for (var listener : thermalListeners) { 1333 listener.notifyThrottling(temp); 1334 } 1335 1336 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); 1337 assertVoteForPhysicalRefreshRate(vote, 60 /*fps*/); 1338 vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); 1339 assertThat(vote).isNotNull(); 1340 assertThat(vote.disableRefreshRateSwitching).isTrue(); 1341 } 1342 1343 @Test 1344 public void testSensorRegistration() { 1345 // First, configure brightness zones or DMD won't register for sensor data. 1346 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 1347 config.setRefreshRateInHighZone(60); 1348 config.setHighDisplayBrightnessThresholds(new int[] { 255 }); 1349 config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); 1350 1351 DisplayModeDirector director = 1352 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 1353 setPeakRefreshRate(90 /*fps*/); 1354 director.getSettingsObserver().setDefaultRefreshRate(90); 1355 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1356 1357 Sensor lightSensor = createLightSensor(); 1358 SensorManager sensorManager = createMockSensorManager(lightSensor); 1359 1360 director.start(sensorManager); 1361 ArgumentCaptor<SensorEventListener> listenerCaptor = 1362 ArgumentCaptor.forClass(SensorEventListener.class); 1363 verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 1364 .registerListener( 1365 listenerCaptor.capture(), 1366 eq(lightSensor), 1367 anyInt(), 1368 any(Handler.class)); 1369 1370 // Display state changed from On to Doze 1371 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_DOZE); 1372 verify(sensorManager) 1373 .unregisterListener(listenerCaptor.capture()); 1374 1375 // Display state changed from Doze to On 1376 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 1377 verify(sensorManager, times(2)) 1378 .registerListener( 1379 listenerCaptor.capture(), 1380 eq(lightSensor), 1381 anyInt(), 1382 any(Handler.class)); 1383 1384 } 1385 1386 @Test 1387 public void testUdfpsListenerGetsRegistered() { 1388 DisplayModeDirector director = 1389 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0); 1390 verify(mStatusBarMock, never()).setUdfpsRefreshRateCallback(any()); 1391 1392 director.onBootCompleted(); 1393 verify(mStatusBarMock).setUdfpsRefreshRateCallback(eq(director.getUdpfsObserver())); 1394 } 1395 1396 @Test 1397 public void testGbhmVotesFor60hz() throws Exception { 1398 DisplayModeDirector director = 1399 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0); 1400 director.start(createMockSensorManager()); 1401 director.onBootCompleted(); 1402 ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor = 1403 ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class); 1404 verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture()); 1405 1406 // Should be no vote initially 1407 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); 1408 assertNull(vote); 1409 } 1410 1411 @Test 1412 public void testAppRequestMinRefreshRate() { 1413 // Confirm that the app min request range doesn't include flicker or min refresh rate 1414 // settings but does include everything else. 1415 assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE 1416 >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF); 1417 1418 Display.Mode[] modes = new Display.Mode[3]; 1419 modes[0] = new Display.Mode( 1420 /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60); 1421 modes[1] = new Display.Mode( 1422 /*modeId=*/75, /*width=*/1000, /*height=*/1000, 75); 1423 modes[2] = new Display.Mode( 1424 /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90); 1425 1426 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]); 1427 SparseArray<Vote> votes = new SparseArray<>(); 1428 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1429 votesByDisplay.put(DISPLAY_ID, votes); 1430 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 1431 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60)); 1432 director.injectVotesByDisplay(votesByDisplay); 1433 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1434 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 1435 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 1436 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 1437 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1438 1439 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1440 Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY)); 1441 director.injectVotesByDisplay(votesByDisplay); 1442 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1443 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1444 assertThat(desiredSpecs.primary.physical.max).isAtLeast(90f); 1445 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 1446 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1447 1448 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 1449 Vote.forRenderFrameRates(75, Float.POSITIVE_INFINITY)); 1450 director.injectVotesByDisplay(votesByDisplay); 1451 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1452 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1453 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 1454 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(75); 1455 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1456 } 1457 1458 @Test testAppRequestMaxRefreshRate()1459 public void testAppRequestMaxRefreshRate() { 1460 // Confirm that the app max request range doesn't include flicker or min refresh rate 1461 // settings but does include everything else. 1462 assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE 1463 >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF); 1464 1465 Display.Mode[] modes = new Display.Mode[3]; 1466 modes[0] = new Display.Mode( 1467 /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60); 1468 modes[1] = new Display.Mode( 1469 /*modeId=*/75, /*width=*/1000, /*height=*/1000, 75); 1470 modes[2] = new Display.Mode( 1471 /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90); 1472 1473 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]); 1474 SparseArray<Vote> votes = new SparseArray<>(); 1475 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1476 votesByDisplay.put(DISPLAY_ID, votes); 1477 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 1478 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60)); 1479 director.injectVotesByDisplay(votesByDisplay); 1480 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1481 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 1482 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60); 1483 assertThat(desiredSpecs.primary.render.min).isZero(); 1484 assertThat(desiredSpecs.primary.render.max).isAtMost(60); 1485 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 1486 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1487 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1488 assertThat(desiredSpecs.appRequest.render.max).isAtLeast(90f); 1489 1490 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1491 Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY)); 1492 director.injectVotesByDisplay(votesByDisplay); 1493 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1494 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1495 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 1496 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90); 1497 assertThat(desiredSpecs.primary.render.max).isAtLeast(90f); 1498 assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f); 1499 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1500 assertThat(desiredSpecs.appRequest.render.min).isAtMost(60f); 1501 assertThat(desiredSpecs.appRequest.render.max).isAtLeast(90f); 1502 1503 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 1504 Vote.forRenderFrameRates(0, 75)); 1505 director.injectVotesByDisplay(votesByDisplay); 1506 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1507 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(75); 1508 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(75); 1509 assertThat(desiredSpecs.primary.render.min).isZero(); 1510 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(75); 1511 assertThat(desiredSpecs.appRequest.physical.min).isZero(); 1512 assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f); 1513 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1514 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(75); 1515 } 1516 1517 @Test testAppRequestObserver_modeId()1518 public void testAppRequestObserver_modeId() { 1519 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 1520 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 0, 0); 1521 1522 Vote appRequestRefreshRate = 1523 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1524 assertNotNull(appRequestRefreshRate); 1525 assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero(); 1526 assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity(); 1527 assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero(); 1528 assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity(); 1529 assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse(); 1530 assertThat(appRequestRefreshRate.appRequestBaseModeRefreshRate) 1531 .isWithin(FLOAT_TOLERANCE).of(60); 1532 assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE); 1533 assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE); 1534 1535 Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1536 assertNotNull(appRequestSize); 1537 assertThat(appRequestSize.refreshRateRanges.physical.min).isZero(); 1538 assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity(); 1539 assertThat(appRequestSize.refreshRateRanges.render.min).isZero(); 1540 assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity(); 1541 assertThat(appRequestSize.disableRefreshRateSwitching).isFalse(); 1542 assertThat(appRequestSize.appRequestBaseModeRefreshRate).isZero(); 1543 assertThat(appRequestSize.height).isEqualTo(1000); 1544 assertThat(appRequestSize.width).isEqualTo(1000); 1545 1546 Vote appRequestRefreshRateRange = 1547 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1548 assertNull(appRequestRefreshRateRange); 1549 1550 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 90, 0, 0); 1551 1552 appRequestRefreshRate = 1553 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1554 assertNotNull(appRequestRefreshRate); 1555 assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero(); 1556 assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity(); 1557 assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero(); 1558 assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity(); 1559 assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse(); 1560 assertThat(appRequestRefreshRate.appRequestBaseModeRefreshRate) 1561 .isWithin(FLOAT_TOLERANCE).of(90); 1562 assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE); 1563 assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE); 1564 1565 appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1566 assertNotNull(appRequestSize); 1567 assertThat(appRequestSize.refreshRateRanges.physical.min).isZero(); 1568 assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity(); 1569 assertThat(appRequestSize.refreshRateRanges.render.min).isZero(); 1570 assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity(); 1571 assertThat(appRequestSize.height).isEqualTo(1000); 1572 assertThat(appRequestSize.width).isEqualTo(1000); 1573 1574 appRequestRefreshRateRange = 1575 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1576 assertNull(appRequestRefreshRateRange); 1577 } 1578 1579 @Test testAppRequestObserver_minRefreshRate()1580 public void testAppRequestObserver_minRefreshRate() { 1581 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 1582 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 60, 0); 1583 Vote appRequestRefreshRate = 1584 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1585 assertNull(appRequestRefreshRate); 1586 1587 Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1588 assertNull(appRequestSize); 1589 1590 Vote appRequestRefreshRateRange = 1591 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1592 assertNotNull(appRequestRefreshRateRange); 1593 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero(); 1594 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max) 1595 .isPositiveInfinity(); 1596 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min) 1597 .isWithin(FLOAT_TOLERANCE).of(60); 1598 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max).isAtLeast(90); 1599 assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE); 1600 assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE); 1601 1602 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 90, 0); 1603 appRequestRefreshRate = 1604 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1605 assertNull(appRequestRefreshRate); 1606 1607 appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1608 assertNull(appRequestSize); 1609 1610 appRequestRefreshRateRange = 1611 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1612 assertNotNull(appRequestRefreshRateRange); 1613 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero(); 1614 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max) 1615 .isPositiveInfinity(); 1616 1617 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min) 1618 .isWithin(FLOAT_TOLERANCE).of(90); 1619 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max).isAtLeast(90); 1620 assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE); 1621 assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE); 1622 } 1623 1624 @Test testAppRequestObserver_maxRefreshRate()1625 public void testAppRequestObserver_maxRefreshRate() { 1626 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 1627 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 90); 1628 Vote appRequestRefreshRate = 1629 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1630 assertNull(appRequestRefreshRate); 1631 1632 Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1633 assertNull(appRequestSize); 1634 1635 Vote appRequestRefreshRateRange = 1636 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1637 assertNotNull(appRequestRefreshRateRange); 1638 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero(); 1639 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max) 1640 .isPositiveInfinity(); 1641 1642 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero(); 1643 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max) 1644 .isWithin(FLOAT_TOLERANCE).of(90); 1645 assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE); 1646 assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE); 1647 1648 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 60); 1649 appRequestRefreshRate = 1650 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1651 assertNull(appRequestRefreshRate); 1652 1653 appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1654 assertNull(appRequestSize); 1655 1656 appRequestRefreshRateRange = 1657 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1658 assertNotNull(appRequestRefreshRateRange); 1659 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero(); 1660 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max) 1661 .isPositiveInfinity(); 1662 1663 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero(); 1664 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max) 1665 .isWithin(FLOAT_TOLERANCE).of(60); 1666 assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE); 1667 assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE); 1668 } 1669 1670 @Test testAppRequestObserver_invalidRefreshRateRange()1671 public void testAppRequestObserver_invalidRefreshRateRange() { 1672 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 1673 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 90, 60); 1674 Vote appRequestRefreshRate = 1675 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1676 assertNull(appRequestRefreshRate); 1677 1678 Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1679 assertNull(appRequestSize); 1680 1681 Vote appRequestRefreshRateRange = 1682 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1683 assertNull(appRequestRefreshRateRange); 1684 } 1685 1686 @Test testAppRequestObserver_modeIdAndRefreshRateRange()1687 public void testAppRequestObserver_modeIdAndRefreshRateRange() { 1688 DisplayModeDirector director = createDirectorFromFpsRange(60, 90); 1689 director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 90, 90); 1690 1691 Vote appRequestRefreshRate = 1692 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE); 1693 assertNotNull(appRequestRefreshRate); 1694 assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero(); 1695 assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity(); 1696 assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero(); 1697 assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity(); 1698 assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse(); 1699 assertThat(appRequestRefreshRate.appRequestBaseModeRefreshRate) 1700 .isWithin(FLOAT_TOLERANCE).of(60); 1701 assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE); 1702 assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE); 1703 1704 Vote appRequestSize = 1705 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE); 1706 assertNotNull(appRequestSize); 1707 assertThat(appRequestSize.refreshRateRanges.physical.min).isZero(); 1708 assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity(); 1709 assertThat(appRequestSize.refreshRateRanges.render.min).isZero(); 1710 assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity(); 1711 assertThat(appRequestSize.height).isEqualTo(1000); 1712 assertThat(appRequestSize.width).isEqualTo(1000); 1713 1714 Vote appRequestRefreshRateRange = 1715 director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE); 1716 assertNotNull(appRequestRefreshRateRange); 1717 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero(); 1718 assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max) 1719 .isPositiveInfinity(); 1720 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min) 1721 .isWithin(FLOAT_TOLERANCE).of(90); 1722 assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max) 1723 .isWithin(FLOAT_TOLERANCE).of(90); 1724 assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE); 1725 assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE); 1726 } 1727 1728 @Test testAppRequestsIsTheDefaultMode()1729 public void testAppRequestsIsTheDefaultMode() { 1730 Display.Mode[] modes = new Display.Mode[2]; 1731 modes[0] = new Display.Mode( 1732 /*modeId=*/1, /*width=*/1000, /*height=*/1000, 60); 1733 modes[1] = new Display.Mode( 1734 /*modeId=*/2, /*width=*/1000, /*height=*/1000, 90); 1735 1736 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 1737 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1738 assertThat(desiredSpecs.baseModeId).isEqualTo(1); 1739 assertThat(desiredSpecs.primary.physical.min).isAtMost(60); 1740 assertThat(desiredSpecs.primary.physical.max).isAtLeast(90); 1741 1742 SparseArray<Vote> votes = new SparseArray<>(); 1743 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1744 votesByDisplay.put(DISPLAY_ID, votes); 1745 Display.Mode appRequestedMode = modes[1]; 1746 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1747 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 1748 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 1749 appRequestedMode.getPhysicalHeight())); 1750 director.injectVotesByDisplay(votesByDisplay); 1751 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1752 assertThat(desiredSpecs.baseModeId).isEqualTo(2); 1753 assertThat(desiredSpecs.primary.physical.min).isAtMost(60); 1754 assertThat(desiredSpecs.primary.physical.max).isAtLeast(90); 1755 } 1756 1757 @Test testDisableRefreshRateSwitchingVote()1758 public void testDisableRefreshRateSwitchingVote() { 1759 DisplayModeDirector director = createDirectorFromFpsRange(50, 90); 1760 SparseArray<Vote> votes = new SparseArray<>(); 1761 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1762 votesByDisplay.put(DISPLAY_ID, votes); 1763 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1764 Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY)); 1765 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 1766 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 1767 director.injectVotesByDisplay(votesByDisplay); 1768 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1769 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(50); 1770 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(50); 1771 assertThat(desiredSpecs.baseModeId).isEqualTo(50); 1772 1773 votes.clear(); 1774 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, 1775 Vote.forPhysicalRefreshRates(70, Float.POSITIVE_INFINITY)); 1776 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1777 Vote.forRenderFrameRates(80, Float.POSITIVE_INFINITY)); 1778 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 1779 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 90)); 1780 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1781 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(80); 1782 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(80); 1783 assertThat(desiredSpecs.baseModeId).isEqualTo(80); 1784 1785 votes.clear(); 1786 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, 1787 Vote.forPhysicalRefreshRates(90, Float.POSITIVE_INFINITY)); 1788 votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, 1789 Vote.forRenderFrameRates(80, Float.POSITIVE_INFINITY)); 1790 votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching()); 1791 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 90)); 1792 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1793 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1794 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 1795 assertThat(desiredSpecs.baseModeId).isEqualTo(90); 1796 } 1797 1798 @Test 1799 @Parameters({ 1800 "true", 1801 "false" 1802 }) testBaseModeIdInPrimaryRange(boolean supportsFrameRateOverride)1803 public void testBaseModeIdInPrimaryRange(boolean supportsFrameRateOverride) { 1804 when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride); 1805 DisplayModeDirector director = createDirectorFromFpsRange(50, 90); 1806 SparseArray<Vote> votes = new SparseArray<>(); 1807 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1808 votesByDisplay.put(DISPLAY_ID, votes); 1809 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1810 Vote.forBaseModeRefreshRate(70)); 1811 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 1812 director.injectVotesByDisplay(votesByDisplay); 1813 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1814 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 1815 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 1816 if (supportsFrameRateOverride) { 1817 assertThat(desiredSpecs.baseModeId).isEqualTo(70); 1818 } else { 1819 assertThat(desiredSpecs.baseModeId).isEqualTo(50); 1820 1821 } 1822 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0); 1823 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 1824 1825 votes.clear(); 1826 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1827 Vote.forBaseModeRefreshRate(55)); 1828 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 1829 director.injectVotesByDisplay(votesByDisplay); 1830 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1831 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 1832 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 1833 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0); 1834 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 1835 assertThat(desiredSpecs.baseModeId).isEqualTo(55); 1836 1837 votes.clear(); 1838 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 1839 Vote.forRenderFrameRates(0, 52)); 1840 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1841 Vote.forBaseModeRefreshRate(55)); 1842 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 1843 director.injectVotesByDisplay(votesByDisplay); 1844 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1845 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 1846 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 1847 if (supportsFrameRateOverride) { 1848 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(52); 1849 } else { 1850 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60); 1851 } 1852 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0); 1853 assertThat(desiredSpecs.baseModeId).isEqualTo(55); 1854 1855 votes.clear(); 1856 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 1857 Vote.forRenderFrameRates(0, 58)); 1858 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1859 Vote.forBaseModeRefreshRate(55)); 1860 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 1861 director.injectVotesByDisplay(votesByDisplay); 1862 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1863 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0); 1864 assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity(); 1865 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0); 1866 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(58); 1867 assertThat(desiredSpecs.baseModeId).isEqualTo(55); 1868 } 1869 1870 @Test testStaleAppVote()1871 public void testStaleAppVote() { 1872 Display.Mode[] modes = new Display.Mode[4]; 1873 modes[0] = new Display.Mode( 1874 /*modeId=*/1, /*width=*/1000, /*height=*/1000, 60); 1875 modes[1] = new Display.Mode( 1876 /*modeId=*/2, /*width=*/2000, /*height=*/2000, 60); 1877 modes[2] = new Display.Mode( 1878 /*modeId=*/3, /*width=*/1000, /*height=*/1000, 90); 1879 modes[3] = new Display.Mode( 1880 /*modeId=*/4, /*width=*/2000, /*height=*/2000, 90); 1881 1882 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]); 1883 SparseArray<Vote> votes = new SparseArray<>(); 1884 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1885 votesByDisplay.put(DISPLAY_ID, votes); 1886 Display.Mode appRequestedMode = modes[3]; 1887 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 1888 Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate())); 1889 votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(), 1890 appRequestedMode.getPhysicalHeight())); 1891 director.injectVotesByDisplay(votesByDisplay); 1892 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1893 assertThat(desiredSpecs.baseModeId).isEqualTo(4); 1894 1895 // Change mode Id's to simulate that a hotplug has occurred. 1896 Display.Mode[] newModes = new Display.Mode[4]; 1897 newModes[0] = new Display.Mode( 1898 /*modeId=*/5, /*width=*/1000, /*height=*/1000, 60); 1899 newModes[1] = new Display.Mode( 1900 /*modeId=*/6, /*width=*/2000, /*height=*/2000, 60); 1901 newModes[2] = new Display.Mode( 1902 /*modeId=*/7, /*width=*/1000, /*height=*/1000, 90); 1903 newModes[3] = new Display.Mode( 1904 /*modeId=*/8, /*width=*/2000, /*height=*/2000, 90); 1905 1906 SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); 1907 supportedModesByDisplay.put(DISPLAY_ID, newModes); 1908 director.injectSupportedModesByDisplay(supportedModesByDisplay); 1909 SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>(); 1910 defaultModesByDisplay.put(DISPLAY_ID, newModes[0]); 1911 director.injectDefaultModeByDisplay(defaultModesByDisplay); 1912 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1913 assertThat(desiredSpecs.baseModeId).isEqualTo(8); 1914 } 1915 1916 @Test 1917 @Parameters({ 1918 "true", 1919 "false" 1920 }) testRefreshRateIsSubsetOfFrameRate(boolean supportsFrameRateOverride)1921 public void testRefreshRateIsSubsetOfFrameRate(boolean supportsFrameRateOverride) { 1922 when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride); 1923 DisplayModeDirector director = createDirectorFromFpsRange(60, 120); 1924 SparseArray<Vote> votes = new SparseArray<>(); 1925 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1926 votesByDisplay.put(DISPLAY_ID, votes); 1927 1928 1929 votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120)); 1930 director.injectVotesByDisplay(votesByDisplay); 1931 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1932 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1933 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 1934 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1935 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120); 1936 1937 votes.clear(); 1938 votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120)); 1939 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 1940 Vote.forRenderFrameRates(0, 60)); 1941 director.injectVotesByDisplay(votesByDisplay); 1942 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1943 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1944 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 1945 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1946 if (supportsFrameRateOverride) { 1947 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 1948 } else { 1949 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120); 1950 } 1951 1952 votes.clear(); 1953 votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120)); 1954 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 1955 Vote.forRenderFrameRates(60, 60)); 1956 director.injectVotesByDisplay(votesByDisplay); 1957 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1958 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1959 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 1960 if (supportsFrameRateOverride) { 1961 assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(60); 1962 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 1963 } else { 1964 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1965 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120); 1966 } 1967 1968 votes.clear(); 1969 votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120)); 1970 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 1971 Vote.forRenderFrameRates(140, 140)); 1972 director.injectVotesByDisplay(votesByDisplay); 1973 desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1974 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 1975 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 1976 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1977 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120); 1978 } 1979 1980 @Test testRenderFrameRateIsAchievableByPhysicalRefreshRate()1981 public void testRenderFrameRateIsAchievableByPhysicalRefreshRate() { 1982 DisplayModeDirector director = createDirectorFromFpsRange(60, 120); 1983 SparseArray<Vote> votes = new SparseArray<>(); 1984 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 1985 votesByDisplay.put(DISPLAY_ID, votes); 1986 1987 1988 votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(120, 120)); 1989 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90)); 1990 director.injectVotesByDisplay(votesByDisplay); 1991 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 1992 assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(120); 1993 assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 1994 assertThat(desiredSpecs.appRequest.render.min).isZero(); 1995 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120); 1996 } 1997 1998 @Test 1999 @Parameters({ 2000 "true", 2001 "false" 2002 }) testRenderFrameRateIncludesPhysicalRefreshRate(boolean supportsFrameRateOverride)2003 public void testRenderFrameRateIncludesPhysicalRefreshRate(boolean supportsFrameRateOverride) { 2004 when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride); 2005 DisplayModeDirector director = createDirectorFromFpsRange(60, 120); 2006 SparseArray<Vote> votes = new SparseArray<>(); 2007 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 2008 votesByDisplay.put(DISPLAY_ID, votes); 2009 2010 votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60)); 2011 votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, 2012 Vote.forRenderFrameRates(0, 30)); 2013 director.injectVotesByDisplay(votesByDisplay); 2014 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 2015 assertThat(desiredSpecs.appRequest.physical.min).isZero(); 2016 assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity(); 2017 assertThat(desiredSpecs.appRequest.render.min).isZero(); 2018 if (supportsFrameRateOverride) { 2019 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30); 2020 } else { 2021 assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60); 2022 } 2023 } 2024 2025 @Test testRenderFrameRateIsDroppedIfLowerPriorityThenBaseModeRefreshRate()2026 public void testRenderFrameRateIsDroppedIfLowerPriorityThenBaseModeRefreshRate() { 2027 DisplayModeDirector director = createDirectorFromFpsRange(60, 120); 2028 SparseArray<Vote> votes = new SparseArray<>(); 2029 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 2030 votesByDisplay.put(DISPLAY_ID, votes); 2031 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 2032 Vote.forRenderFrameRates(120, 120)); 2033 votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE, 2034 Vote.forBaseModeRefreshRate(90)); 2035 votes.put(Vote.PRIORITY_PROXIMITY, Vote.forPhysicalRefreshRates(60, 120)); 2036 director.injectVotesByDisplay(votesByDisplay); 2037 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 2038 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60); 2039 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(120); 2040 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0); 2041 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(120); 2042 assertThat(desiredSpecs.baseModeId).isEqualTo(90); 2043 } 2044 2045 @Test testRenderFrameRateIsAchievableWhenSwitchingTypeNone()2046 public void testRenderFrameRateIsAchievableWhenSwitchingTypeNone() { 2047 Display.Mode[] modes = new Display.Mode[2]; 2048 modes[0] = new Display.Mode( 2049 /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60); 2050 modes[1] = new Display.Mode( 2051 /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90); 2052 2053 DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]); 2054 director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_NONE); 2055 2056 SparseArray<Vote> votes = new SparseArray<>(); 2057 SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); 2058 votesByDisplay.put(DISPLAY_ID, votes); 2059 votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE, 2060 Vote.forRenderFrameRates(0, 60)); 2061 director.injectVotesByDisplay(votesByDisplay); 2062 DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID); 2063 assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 2064 assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 2065 assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90); 2066 assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90); 2067 assertThat(desiredSpecs.baseModeId).isEqualTo(90); 2068 } 2069 2070 @Test testProximitySensorVoting()2071 public void testProximitySensorVoting() { 2072 DisplayModeDirector director = 2073 createDirectorFromRefreshRateArray(new float[]{60.f, 90.f}, 0); 2074 director.start(createMockSensorManager()); 2075 2076 ArgumentCaptor<ProximityActiveListener> ProximityCaptor = 2077 ArgumentCaptor.forClass(ProximityActiveListener.class); 2078 verify(mSensorManagerInternalMock).addProximityActiveListener(any(Executor.class), 2079 ProximityCaptor.capture()); 2080 ProximityActiveListener proximityListener = ProximityCaptor.getValue(); 2081 2082 ArgumentCaptor<DisplayListener> DisplayCaptor = 2083 ArgumentCaptor.forClass(DisplayListener.class); 2084 verify(mInjector, times(2)).registerDisplayListener(DisplayCaptor.capture(), 2085 any(Handler.class), 2086 eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED 2087 | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 2088 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2089 DisplayListener displayListener = DisplayCaptor.getAllValues().get(0); 2090 2091 // Verify that there is no proximity vote initially 2092 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2093 assertNull(vote); 2094 2095 when(mDisplayManagerInternalMock.getRefreshRateForDisplayAndSensor(eq(DISPLAY_ID), eq(null), 2096 eq(Sensor.STRING_TYPE_PROXIMITY))).thenReturn(new RefreshRateRange(60, 60)); 2097 2098 when(mInjector.isDozeState(any(Display.class))).thenReturn(false); 2099 2100 // Set the proximity to active and verify that we added a vote. 2101 proximityListener.onProximityActive(true); 2102 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2103 assertVoteForPhysicalRefreshRate(vote, 60.f); 2104 2105 // Set the display state to doze and verify that the vote is gone 2106 when(mInjector.isDozeState(any(Display.class))).thenReturn(true); 2107 displayListener.onDisplayAdded(DISPLAY_ID); 2108 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2109 assertNull(vote); 2110 2111 // Set the display state to on and verify that we added the vote back. 2112 when(mInjector.isDozeState(any(Display.class))).thenReturn(false); 2113 displayListener.onDisplayChanged(DISPLAY_ID); 2114 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2115 assertVoteForPhysicalRefreshRate(vote, 60.f); 2116 2117 // Set the display state to doze and verify that the vote is gone 2118 when(mInjector.isDozeState(any(Display.class))).thenReturn(true); 2119 displayListener.onDisplayAdded(DISPLAY_ID); 2120 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2121 assertNull(vote); 2122 2123 // Remove the display to cause the doze state to be removed 2124 displayListener.onDisplayRemoved(DISPLAY_ID); 2125 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2126 assertVoteForPhysicalRefreshRate(vote, 60.f); 2127 2128 // Turn prox off and verify vote is gone. 2129 proximityListener.onProximityActive(false); 2130 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY); 2131 assertNull(vote); 2132 } 2133 2134 @Test testHbmVoting_forHdr()2135 public void testHbmVoting_forHdr() { 2136 DisplayModeDirector director = 2137 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2138 final int hbmRefreshRate = 72; 2139 2140 // Specify limitation before starting DisplayModeDirector to avoid waiting on property 2141 // propagation 2142 mInjector.getDeviceConfig().setRefreshRateInHbmHdr(hbmRefreshRate); 2143 2144 director.start(createMockSensorManager()); 2145 2146 ArgumentCaptor<DisplayListener> captor = 2147 ArgumentCaptor.forClass(DisplayListener.class); 2148 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2149 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2150 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2151 DisplayListener listener = captor.getValue(); 2152 2153 // Specify Limitation 2154 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( 2155 List.of(new RefreshRateLimitation( 2156 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, 2157 60.f, 60.f))); 2158 2159 // Verify that there is no HBM vote initially 2160 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2161 assertNull(vote); 2162 2163 // Turn on HBM, with brightness in the HBM range 2164 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2165 new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, 2166 BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT, 2167 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2168 listener.onDisplayChanged(DISPLAY_ID); 2169 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2170 assertVoteForPhysicalRefreshRate(vote, hbmRefreshRate); 2171 2172 // Turn on HBM, with brightness below the HBM range 2173 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2174 new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, 2175 BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT, 2176 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2177 listener.onDisplayChanged(DISPLAY_ID); 2178 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2179 assertNull(vote); 2180 2181 // Turn off HBM 2182 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2183 new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2184 TRANSITION_POINT, 2185 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2186 listener.onDisplayChanged(DISPLAY_ID); 2187 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2188 assertNull(vote); 2189 2190 // Turn on HBM, with brightness in the HBM range 2191 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2192 new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, 2193 BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT, 2194 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2195 listener.onDisplayChanged(DISPLAY_ID); 2196 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2197 assertVoteForPhysicalRefreshRate(vote, hbmRefreshRate); 2198 2199 // Turn off HBM 2200 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2201 new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2202 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2203 listener.onDisplayChanged(DISPLAY_ID); 2204 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2205 assertNull(vote); 2206 2207 // Turn on HBM, with brightness below the HBM range 2208 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2209 new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, 2210 BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT, 2211 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2212 listener.onDisplayChanged(DISPLAY_ID); 2213 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2214 assertNull(vote); 2215 2216 // Turn off HBM 2217 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2218 new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2219 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2220 listener.onDisplayChanged(DISPLAY_ID); 2221 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2222 assertNull(vote); 2223 } 2224 2225 @Test testHbmObserverGetsUpdatedRefreshRateInHbmSunlight()2226 public void testHbmObserverGetsUpdatedRefreshRateInHbmSunlight() { 2227 DisplayModeDirector director = 2228 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0); 2229 2230 final int initialRefreshRate = 60; 2231 mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(initialRefreshRate); 2232 director.start(createMockSensorManager()); 2233 assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()) 2234 .isEqualTo(initialRefreshRate); 2235 2236 final int updatedRefreshRate = 90; 2237 mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(updatedRefreshRate); 2238 // Need to wait for the property change to propagate to the main thread. 2239 waitForIdleSync(); 2240 assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()) 2241 .isEqualTo(updatedRefreshRate); 2242 } 2243 2244 @Test testHbmObserverGetsUpdatedRefreshRateInHbmHdr()2245 public void testHbmObserverGetsUpdatedRefreshRateInHbmHdr() { 2246 DisplayModeDirector director = 2247 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0); 2248 2249 final int initialRefreshRate = 60; 2250 mInjector.getDeviceConfig().setRefreshRateInHbmHdr(initialRefreshRate); 2251 director.start(createMockSensorManager()); 2252 assertThat(director.getHbmObserver().getRefreshRateInHbmHdr()) 2253 .isEqualTo(initialRefreshRate); 2254 2255 final int updatedRefreshRate = 90; 2256 mInjector.getDeviceConfig().setRefreshRateInHbmHdr(updatedRefreshRate); 2257 // Need to wait for the property change to propagate to the main thread. 2258 waitForIdleSync(); 2259 assertThat(director.getHbmObserver().getRefreshRateInHbmHdr()) 2260 .isEqualTo(updatedRefreshRate); 2261 } 2262 2263 @Test testHbmVoting_forSunlight()2264 public void testHbmVoting_forSunlight() { 2265 DisplayModeDirector director = 2266 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2267 director.start(createMockSensorManager()); 2268 2269 ArgumentCaptor<DisplayListener> captor = 2270 ArgumentCaptor.forClass(DisplayListener.class); 2271 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2272 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2273 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2274 DisplayListener listener = captor.getValue(); 2275 2276 final int initialRefreshRate = 60; 2277 // Specify Limitation 2278 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( 2279 List.of(new RefreshRateLimitation( 2280 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, 2281 initialRefreshRate, initialRefreshRate))); 2282 2283 // Verify that there is no HBM vote initially 2284 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2285 assertNull(vote); 2286 2287 // Turn on HBM 2288 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2289 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2290 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2291 listener.onDisplayChanged(DISPLAY_ID); 2292 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2293 assertVoteForPhysicalRefreshRate(vote, initialRefreshRate); 2294 2295 // Change refresh rate vote value through DeviceConfig, ensure it takes precedence 2296 final int updatedRefreshRate = 90; 2297 mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(updatedRefreshRate); 2298 // Need to wait for the property change to propagate to the main thread. 2299 waitForIdleSync(); 2300 assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()) 2301 .isEqualTo(updatedRefreshRate); 2302 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2303 assertVoteForPhysicalRefreshRate(vote, updatedRefreshRate); 2304 2305 // Turn off HBM 2306 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2307 new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2308 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2309 listener.onDisplayChanged(DISPLAY_ID); 2310 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2311 assertNull(vote); 2312 2313 // Turn HBM on again and ensure the updated vote value stuck 2314 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2315 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2316 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2317 listener.onDisplayChanged(DISPLAY_ID); 2318 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2319 assertVoteForPhysicalRefreshRate(vote, updatedRefreshRate); 2320 2321 // Reset DeviceConfig refresh rate, ensure vote falls back to the initial value 2322 mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(0); 2323 // Need to wait for the property change to propagate to the main thread. 2324 waitForIdleSync(); 2325 assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()).isEqualTo(0); 2326 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2327 assertVoteForPhysicalRefreshRate(vote, initialRefreshRate); 2328 2329 // Turn off HBM 2330 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2331 new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2332 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2333 listener.onDisplayChanged(DISPLAY_ID); 2334 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2335 assertNull(vote); 2336 } 2337 2338 @Test testHbmVoting_forSunlight_NoLimitation()2339 public void testHbmVoting_forSunlight_NoLimitation() { 2340 DisplayModeDirector director = 2341 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2342 director.start(createMockSensorManager()); 2343 2344 ArgumentCaptor<DisplayListener> captor = 2345 ArgumentCaptor.forClass(DisplayListener.class); 2346 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2347 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2348 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2349 DisplayListener listener = captor.getValue(); 2350 2351 // Specify Limitation for different display 2352 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID + 1)).thenReturn( 2353 List.of(new RefreshRateLimitation( 2354 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, 2355 60.f, 60.f))); 2356 2357 // Verify that there is no HBM vote initially 2358 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2359 assertNull(vote); 2360 2361 // Turn on HBM 2362 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2363 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2364 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2365 listener.onDisplayChanged(DISPLAY_ID); 2366 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2367 assertNull(vote); 2368 2369 // Turn off HBM 2370 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2371 new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2372 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2373 listener.onDisplayChanged(DISPLAY_ID); 2374 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2375 assertNull(vote); 2376 } 2377 2378 @Test testHbmVoting_HbmUnsupported()2379 public void testHbmVoting_HbmUnsupported() { 2380 DisplayModeDirector director = 2381 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2382 director.start(createMockSensorManager()); 2383 2384 ArgumentCaptor<DisplayListener> captor = 2385 ArgumentCaptor.forClass(DisplayListener.class); 2386 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2387 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2388 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2389 DisplayListener listener = captor.getValue(); 2390 2391 // Specify Limitation 2392 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( 2393 List.of(new RefreshRateLimitation( 2394 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, 2395 60.0f, 60.0f))); 2396 2397 // Verify that there is no HBM vote initially 2398 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2399 assertNull(vote); 2400 2401 // Turn on HBM when HBM is supported; expect a valid transition point and a vote. 2402 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2403 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2404 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2405 listener.onDisplayChanged(DISPLAY_ID); 2406 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2407 assertVoteForPhysicalRefreshRate(vote, 60.0f); 2408 2409 // Turn off HBM 2410 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2411 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2412 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2413 listener.onDisplayChanged(DISPLAY_ID); 2414 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2415 assertNull(vote); 2416 2417 // Turn on Sunlight HBM when HBM is unsupported; expect an invalid transition point and 2418 // no vote. 2419 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2420 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2421 HBM_TRANSITION_POINT_INVALID, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2422 listener.onDisplayChanged(DISPLAY_ID); 2423 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2424 assertNull(vote); 2425 2426 // Turn on HDR HBM when HBM is unsupported; expect an invalid transition point and 2427 // no vote. 2428 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2429 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, 2430 HBM_TRANSITION_POINT_INVALID, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2431 listener.onDisplayChanged(DISPLAY_ID); 2432 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2433 assertNull(vote); 2434 2435 // Turn off HBM 2436 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2437 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, 2438 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2439 listener.onDisplayChanged(DISPLAY_ID); 2440 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2441 assertNull(vote); 2442 } 2443 setHbmAndAssertRefreshRate( DisplayModeDirector director, DisplayListener listener, int mode, float rr)2444 private void setHbmAndAssertRefreshRate( 2445 DisplayModeDirector director, DisplayListener listener, int mode, float rr) { 2446 when(mInjector.getBrightnessInfo(DISPLAY_ID)) 2447 .thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT, 2448 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2449 listener.onDisplayChanged(DISPLAY_ID); 2450 2451 final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2452 if (Float.isNaN(rr)) { 2453 assertNull(vote); 2454 } else { 2455 assertVoteForPhysicalRefreshRate(vote, rr); 2456 } 2457 } 2458 2459 @Test testHbmVoting_forSunlightAndHdr()2460 public void testHbmVoting_forSunlightAndHdr() { 2461 DisplayModeDirector director = 2462 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2463 2464 // Specify HDR limitation before starting DisplayModeDirector to avoid waiting on property 2465 // propagation 2466 final int hdrRr = 60; 2467 mInjector.getDeviceConfig().setRefreshRateInHbmHdr(hdrRr); 2468 director.start(createMockSensorManager()); 2469 2470 ArgumentCaptor<DisplayListener> captor = ArgumentCaptor.forClass(DisplayListener.class); 2471 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2472 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2473 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2474 DisplayListener listener = captor.getValue(); 2475 2476 // Specify Sunlight limitations 2477 final float sunlightRr = 90.0f; 2478 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)) 2479 .thenReturn(List.of(new RefreshRateLimitation( 2480 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, sunlightRr, 2481 sunlightRr))); 2482 2483 // Verify that there is no HBM vote initially 2484 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2485 assertNull(vote); 2486 2487 // Verify all state transitions 2488 setHbmAndAssertRefreshRate( 2489 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, sunlightRr); 2490 setHbmAndAssertRefreshRate( 2491 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, hdrRr); 2492 setHbmAndAssertRefreshRate( 2493 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, Float.NaN); 2494 setHbmAndAssertRefreshRate( 2495 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, hdrRr); 2496 setHbmAndAssertRefreshRate( 2497 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, sunlightRr); 2498 setHbmAndAssertRefreshRate( 2499 director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, Float.NaN); 2500 } 2501 2502 @Test testHbmVoting_RemovedDisplay()2503 public void testHbmVoting_RemovedDisplay() { 2504 DisplayModeDirector director = 2505 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2506 director.start(createMockSensorManager()); 2507 2508 ArgumentCaptor<DisplayListener> captor = 2509 ArgumentCaptor.forClass(DisplayListener.class); 2510 verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), 2511 eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS 2512 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); 2513 DisplayListener listener = captor.getValue(); 2514 2515 // Specify Limitation for different display 2516 when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( 2517 List.of(new RefreshRateLimitation( 2518 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, 2519 60.f, 60.f))); 2520 2521 // Verify that there is no HBM vote initially 2522 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2523 assertNull(vote); 2524 2525 // Turn on HBM 2526 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 2527 new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, 2528 TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 2529 listener.onDisplayChanged(DISPLAY_ID); 2530 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2531 assertVoteForPhysicalRefreshRate(vote, 60.f); 2532 2533 // Turn off HBM 2534 listener.onDisplayRemoved(DISPLAY_ID); 2535 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); 2536 assertNull(vote); 2537 } 2538 2539 @Test testSkinTemperature()2540 public void testSkinTemperature() throws RemoteException { 2541 DisplayModeDirector director = 2542 createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); 2543 director.start(createMockSensorManager()); 2544 2545 ArgumentCaptor<IThermalEventListener> thermalEventListener = 2546 ArgumentCaptor.forClass(IThermalEventListener.class); 2547 2548 verify(mInjector).registerThermalServiceListener(thermalEventListener.capture()); 2549 final IThermalEventListener listener = thermalEventListener.getValue(); 2550 2551 // Verify that there is no skin temperature vote initially. 2552 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE); 2553 assertNull(vote); 2554 2555 // Set the skin temperature to critical and verify that we added a vote. 2556 listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL)); 2557 BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/); 2558 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE); 2559 assertVoteForRenderFrameRateRange(vote, 0f, 60.f); 2560 2561 // Set the skin temperature to severe and verify that the vote is gone. 2562 listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE)); 2563 BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/); 2564 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE); 2565 assertNull(vote); 2566 } 2567 2568 @Test testNotifyDefaultDisplayDeviceUpdated()2569 public void testNotifyDefaultDisplayDeviceUpdated() { 2570 Resources resources = mock(Resources.class); 2571 when(mContext.getResources()).thenReturn(resources); 2572 when(resources.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate)) 2573 .thenReturn(75); 2574 when(resources.getInteger(R.integer.config_defaultRefreshRate)) 2575 .thenReturn(45); 2576 when(resources.getInteger(R.integer.config_fixedRefreshRateInHighZone)) 2577 .thenReturn(65); 2578 when(resources.getInteger(R.integer.config_defaultRefreshRateInZone)) 2579 .thenReturn(85); 2580 when(resources.getInteger(R.integer.config_defaultRefreshRateInHbmHdr)) 2581 .thenReturn(95); 2582 when(resources.getInteger(R.integer.config_defaultRefreshRateInHbmSunlight)) 2583 .thenReturn(100); 2584 when(resources.getIntArray(R.array.config_brightnessThresholdsOfPeakRefreshRate)) 2585 .thenReturn(new int[]{5}); 2586 when(resources.getIntArray(R.array.config_ambientThresholdsOfPeakRefreshRate)) 2587 .thenReturn(new int[]{10}); 2588 when( 2589 resources.getIntArray(R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate)) 2590 .thenReturn(new int[]{250}); 2591 when( 2592 resources.getIntArray(R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate)) 2593 .thenReturn(new int[]{7000}); 2594 when(resources.getInteger( 2595 com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon)) 2596 .thenReturn(3); 2597 ArgumentCaptor<TypedValue> valueArgumentCaptor = ArgumentCaptor.forClass(TypedValue.class); 2598 doAnswer((Answer<Void>) invocation -> { 2599 valueArgumentCaptor.getValue().type = 4; 2600 valueArgumentCaptor.getValue().data = 13; 2601 return null; 2602 }).when(resources).getValue(eq(com.android.internal.R.dimen 2603 .config_displayWhiteBalanceBrightnessFilterIntercept), 2604 valueArgumentCaptor.capture(), eq(true)); 2605 DisplayModeDirector director = 2606 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2607 SensorManager sensorManager = createMockSensorManager(createLightSensor()); 2608 director.start(sensorManager); 2609 // We don't expect any interaction with DeviceConfig when the director is initialized 2610 // because we explicitly avoid doing this as this can lead to a latency spike in the 2611 // startup of DisplayManagerService 2612 // Verify all the loaded values are from config.xml 2613 assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 45, 0.0); 2614 assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 75, 2615 0.0); 2616 assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 65); 2617 assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 85); 2618 assertEquals(director.getHbmObserver().getRefreshRateInHbmHdr(), 95); 2619 assertEquals(director.getHbmObserver().getRefreshRateInHbmSunlight(), 100); 2620 assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThresholds(), 2621 new float[]{ BrightnessSynchronizer.brightnessIntToFloat(250) }, /* delta= */ 0); 2622 assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThresholds(), 2623 new float[]{7000}, /* delta= */ 0); 2624 assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThresholds(), 2625 new float[]{ BrightnessSynchronizer.brightnessIntToFloat(5) }, /* delta= */ 0); 2626 assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThresholds(), 2627 new float[]{10}, /* delta= */ 0); 2628 2629 2630 // Notify that the default display is updated, such that DisplayDeviceConfig has new values 2631 DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class); 2632 when(displayDeviceConfig.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50); 2633 when(displayDeviceConfig.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55); 2634 when(displayDeviceConfig.getDefaultRefreshRate()).thenReturn(60); 2635 when(displayDeviceConfig.getDefaultPeakRefreshRate()).thenReturn(65); 2636 when(displayDeviceConfig.getLowDisplayBrightnessThresholds()) 2637 .thenReturn(new float[]{0.025f}); 2638 when(displayDeviceConfig.getLowAmbientBrightnessThresholds()) 2639 .thenReturn(new float[]{30}); 2640 when(displayDeviceConfig.getHighDisplayBrightnessThresholds()) 2641 .thenReturn(new float[]{0.21f}); 2642 when(displayDeviceConfig.getHighAmbientBrightnessThresholds()) 2643 .thenReturn(new float[]{2100}); 2644 when(displayDeviceConfig.getDefaultRefreshRateInHbmHdr()).thenReturn(65); 2645 when(displayDeviceConfig.getDefaultRefreshRateInHbmSunlight()).thenReturn(75); 2646 director.defaultDisplayDeviceUpdated(displayDeviceConfig); 2647 2648 // Verify the new values are from the freshly loaded DisplayDeviceConfig. 2649 assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 60, 0.0); 2650 assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 65, 2651 0.0); 2652 assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 55); 2653 assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 50); 2654 assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThresholds(), 2655 new float[]{0.21f}, /* delta= */ 0); 2656 assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThresholds(), 2657 new float[]{2100}, /* delta= */ 0); 2658 assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThresholds(), 2659 new float[]{0.025f}, /* delta= */ 0); 2660 assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThresholds(), 2661 new float[]{30}, /* delta= */ 0); 2662 assertEquals(director.getHbmObserver().getRefreshRateInHbmHdr(), 65); 2663 assertEquals(director.getHbmObserver().getRefreshRateInHbmSunlight(), 75); 2664 2665 // Notify that the default display is updated, such that DeviceConfig has new values 2666 FakeDeviceConfig config = mInjector.getDeviceConfig(); 2667 config.setDefaultPeakRefreshRate(60); 2668 config.setRefreshRateInHighZone(65); 2669 config.setRefreshRateInLowZone(70); 2670 config.setLowAmbientBrightnessThresholds(new int[]{20}); 2671 config.setLowDisplayBrightnessThresholds(new int[]{10}); 2672 config.setHighDisplayBrightnessThresholds(new int[]{255}); 2673 config.setHighAmbientBrightnessThresholds(new int[]{8000}); 2674 config.setRefreshRateInHbmHdr(70); 2675 config.setRefreshRateInHbmSunlight(80); 2676 // Need to wait for the property change to propagate to the main thread. 2677 waitForIdleSync(); 2678 2679 // Verify the values are loaded from the DeviceConfig. 2680 assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 60, 0.0); 2681 assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 60, 2682 0.0); 2683 assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 65); 2684 assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 70); 2685 assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThresholds(), 2686 new float[]{ BrightnessSynchronizer.brightnessIntToFloat(255) }, /* delta= */ 0); 2687 assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThresholds(), 2688 new float[]{8000}, /* delta= */ 0); 2689 assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThresholds(), 2690 new float[]{ BrightnessSynchronizer.brightnessIntToFloat(10) }, /* delta= */ 0); 2691 assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThresholds(), 2692 new float[]{20}, /* delta= */ 0); 2693 assertEquals(director.getHbmObserver().getRefreshRateInHbmHdr(), 70); 2694 assertEquals(director.getHbmObserver().getRefreshRateInHbmSunlight(), 80); 2695 2696 // Reset the DeviceConfig 2697 config.setDefaultPeakRefreshRate(null); 2698 config.setRefreshRateInHighZone(null); 2699 config.setRefreshRateInLowZone(null); 2700 config.setLowAmbientBrightnessThresholds(new int[]{}); 2701 config.setLowDisplayBrightnessThresholds(new int[]{}); 2702 config.setHighDisplayBrightnessThresholds(new int[]{}); 2703 config.setHighAmbientBrightnessThresholds(new int[]{}); 2704 config.setRefreshRateInHbmHdr(null); 2705 config.setRefreshRateInHbmSunlight(null); 2706 waitForIdleSync(); 2707 2708 // verify the new values now fallback to DisplayDeviceConfig 2709 assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 60, 0.0); 2710 assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 65, 2711 0.0); 2712 assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 55); 2713 assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 50); 2714 assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThresholds(), 2715 new float[]{0.21f}, /* delta= */ 0); 2716 assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThresholds(), 2717 new float[]{2100}, /* delta= */ 0); 2718 assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThresholds(), 2719 new float[]{0.025f}, /* delta= */ 0); 2720 assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThresholds(), 2721 new float[]{30}, /* delta= */ 0); 2722 assertEquals(director.getHbmObserver().getRefreshRateInHbmHdr(), 65); 2723 assertEquals(director.getHbmObserver().getRefreshRateInHbmSunlight(), 75); 2724 } 2725 2726 @Test testSensorReloadOnDeviceSwitch()2727 public void testSensorReloadOnDeviceSwitch() throws Exception { 2728 // First, configure brightness zones or DMD won't register for sensor data. 2729 final FakeDeviceConfig config = mInjector.getDeviceConfig(); 2730 config.setRefreshRateInHighZone(60); 2731 config.setHighDisplayBrightnessThresholds(new int[] { 255 }); 2732 config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); 2733 2734 DisplayModeDirector director = 2735 createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); 2736 setPeakRefreshRate(90 /*fps*/); 2737 director.getSettingsObserver().setDefaultRefreshRate(90); 2738 director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); 2739 2740 Sensor lightSensorOne = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT); 2741 Sensor lightSensorTwo = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT); 2742 SensorManager sensorManager = createMockSensorManager(lightSensorOne, lightSensorTwo); 2743 when(sensorManager.getDefaultSensor(5)).thenReturn(lightSensorOne, lightSensorTwo); 2744 director.start(sensorManager); 2745 ArgumentCaptor<SensorEventListener> listenerCaptor = 2746 ArgumentCaptor.forClass(SensorEventListener.class); 2747 verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) 2748 .registerListener( 2749 listenerCaptor.capture(), 2750 eq(lightSensorOne), 2751 anyInt(), 2752 any(Handler.class)); 2753 2754 DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class); 2755 when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50); 2756 when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55); 2757 when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new float[]{0.025f}); 2758 when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new float[]{30}); 2759 when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[]{0.21f}); 2760 when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[]{2100}); 2761 2762 Resources resMock = mock(Resources.class); 2763 when(resMock.getInteger( 2764 com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon)) 2765 .thenReturn(3); 2766 ArgumentCaptor<TypedValue> valueArgumentCaptor = ArgumentCaptor.forClass(TypedValue.class); 2767 doAnswer((Answer<Void>) invocation -> { 2768 valueArgumentCaptor.getValue().type = 4; 2769 valueArgumentCaptor.getValue().data = 13; 2770 return null; 2771 }).when(resMock).getValue(anyInt(), valueArgumentCaptor.capture(), eq(true)); 2772 when(mContext.getResources()).thenReturn(resMock); 2773 2774 director.defaultDisplayDeviceUpdated(ddcMock); 2775 2776 verify(sensorManager).unregisterListener(any(SensorEventListener.class)); 2777 verify(sensorManager).registerListener(any(SensorEventListener.class), 2778 eq(lightSensorTwo), anyInt(), any(Handler.class)); 2779 } 2780 2781 @Test testAuthenticationPossibleSetsPhysicalRateRangesToMax()2782 public void testAuthenticationPossibleSetsPhysicalRateRangesToMax() throws RemoteException { 2783 DisplayModeDirector director = 2784 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2785 // don't call director.start(createMockSensorManager()); 2786 // DisplayObserver will reset mSupportedModesByDisplay 2787 director.onBootCompleted(); 2788 ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor = 2789 ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class); 2790 verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture()); 2791 2792 captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); 2793 2794 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); 2795 assertThat(vote.refreshRateRanges.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 2796 assertThat(vote.refreshRateRanges.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 2797 } 2798 2799 @Test testAuthenticationPossibleUnsetsVote()2800 public void testAuthenticationPossibleUnsetsVote() throws RemoteException { 2801 DisplayModeDirector director = 2802 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2803 director.start(createMockSensorManager()); 2804 director.onBootCompleted(); 2805 ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor = 2806 ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class); 2807 verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture()); 2808 captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); 2809 captor.getValue().onAuthenticationPossible(DISPLAY_ID, false); 2810 2811 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); 2812 assertNull(vote); 2813 } 2814 2815 @Test testUdfpsRequestSetsPhysicalRateRangesToMax()2816 public void testUdfpsRequestSetsPhysicalRateRangesToMax() throws RemoteException { 2817 DisplayModeDirector director = 2818 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2819 // don't call director.start(createMockSensorManager()); 2820 // DisplayObserver will reset mSupportedModesByDisplay 2821 director.onBootCompleted(); 2822 ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor = 2823 ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class); 2824 verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture()); 2825 2826 captor.getValue().onRequestEnabled(DISPLAY_ID); 2827 2828 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); 2829 assertThat(vote.refreshRateRanges.physical.min).isWithin(FLOAT_TOLERANCE).of(90); 2830 assertThat(vote.refreshRateRanges.physical.max).isWithin(FLOAT_TOLERANCE).of(90); 2831 } 2832 2833 @Test testUdfpsRequestUnsetsUnsetsVote()2834 public void testUdfpsRequestUnsetsUnsetsVote() throws RemoteException { 2835 DisplayModeDirector director = 2836 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2837 director.start(createMockSensorManager()); 2838 director.onBootCompleted(); 2839 ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor = 2840 ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class); 2841 verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture()); 2842 captor.getValue().onRequestEnabled(DISPLAY_ID); 2843 captor.getValue().onRequestDisabled(DISPLAY_ID); 2844 2845 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); 2846 assertNull(vote); 2847 } 2848 2849 @Test testUpdateLayoutLimitedRefreshRate_validDisplayInfo()2850 public void testUpdateLayoutLimitedRefreshRate_validDisplayInfo() { 2851 DisplayModeDirector director = 2852 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2853 director.start(createMockSensorManager()); 2854 2855 ArgumentCaptor<DisplayListener> displayListenerCaptor = 2856 ArgumentCaptor.forClass(DisplayListener.class); 2857 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 2858 any(Handler.class)); 2859 DisplayListener displayListener = displayListenerCaptor.getValue(); 2860 2861 float refreshRate = 60; 2862 mInjector.mDisplayInfo.layoutLimitedRefreshRate = 2863 new RefreshRateRange(refreshRate, refreshRate); 2864 displayListener.onDisplayChanged(DISPLAY_ID); 2865 2866 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE); 2867 assertVoteForPhysicalRefreshRate(vote, /* refreshRate= */ refreshRate); 2868 2869 mInjector.mDisplayInfo.layoutLimitedRefreshRate = null; 2870 displayListener.onDisplayChanged(DISPLAY_ID); 2871 2872 vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE); 2873 assertNull(vote); 2874 } 2875 2876 @Test testUpdateLayoutLimitedRefreshRate_invalidDisplayInfo()2877 public void testUpdateLayoutLimitedRefreshRate_invalidDisplayInfo() { 2878 DisplayModeDirector director = 2879 createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); 2880 director.start(createMockSensorManager()); 2881 2882 ArgumentCaptor<DisplayListener> displayListenerCaptor = 2883 ArgumentCaptor.forClass(DisplayListener.class); 2884 verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), 2885 any(Handler.class)); 2886 DisplayListener displayListener = displayListenerCaptor.getValue(); 2887 2888 mInjector.mDisplayInfo.layoutLimitedRefreshRate = new RefreshRateRange(10, 10); 2889 mInjector.mDisplayInfoValid = false; 2890 displayListener.onDisplayChanged(DISPLAY_ID); 2891 2892 Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE); 2893 assertNull(vote); 2894 } 2895 getSkinTemp(@emperature.ThrottlingStatus int status)2896 private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) { 2897 return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); 2898 } 2899 assertVoteForPhysicalRefreshRate(Vote vote, float refreshRate)2900 private void assertVoteForPhysicalRefreshRate(Vote vote, float refreshRate) { 2901 assertThat(vote).isNotNull(); 2902 final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate); 2903 assertThat(vote.refreshRateRanges.physical).isEqualTo(expectedRange); 2904 } 2905 assertVoteForRenderFrameRateRange( Vote vote, float frameRateLow, float frameRateHigh)2906 private void assertVoteForRenderFrameRateRange( 2907 Vote vote, float frameRateLow, float frameRateHigh) { 2908 assertThat(vote).isNotNull(); 2909 final RefreshRateRange expectedRange = 2910 new RefreshRateRange(frameRateLow, frameRateHigh); 2911 assertThat(vote.refreshRateRanges.render).isEqualTo(expectedRange); 2912 } 2913 2914 public static class FakeDeviceConfig extends FakeDeviceConfigInterface { 2915 @Override getProperty(String namespace, String name)2916 public String getProperty(String namespace, String name) { 2917 Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)); 2918 return super.getProperty(namespace, name); 2919 } 2920 2921 @Override addOnPropertiesChangedListener( String namespace, Executor executor, DeviceConfig.OnPropertiesChangedListener listener)2922 public void addOnPropertiesChangedListener( 2923 String namespace, 2924 Executor executor, 2925 DeviceConfig.OnPropertiesChangedListener listener) { 2926 Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)); 2927 super.addOnPropertiesChangedListener(namespace, executor, listener); 2928 } 2929 setRefreshRateInLowZone(Integer fps)2930 void setRefreshRateInLowZone(Integer fps) { 2931 putPropertyAndNotify( 2932 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_LOW_ZONE, 2933 String.valueOf(fps)); 2934 } 2935 setRefreshRateInHbmSunlight(Integer fps)2936 void setRefreshRateInHbmSunlight(Integer fps) { 2937 putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2938 KEY_REFRESH_RATE_IN_HBM_SUNLIGHT, String.valueOf(fps)); 2939 } 2940 setRefreshRateInHbmHdr(Integer fps)2941 void setRefreshRateInHbmHdr(Integer fps) { 2942 putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2943 KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps)); 2944 } 2945 setThermalBrightnessThrottlingData(String brightnessThrottlingData)2946 public void setThermalBrightnessThrottlingData(String brightnessThrottlingData) { 2947 putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2948 KEY_BRIGHTNESS_THROTTLING_DATA, brightnessThrottlingData); 2949 } 2950 setLowDisplayBrightnessThresholds(int[] brightnessThresholds)2951 void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) { 2952 String thresholds = toPropertyValue(brightnessThresholds); 2953 2954 if (DEBUG) { 2955 Slog.e(TAG, "Brightness Thresholds = " + thresholds); 2956 } 2957 2958 putPropertyAndNotify( 2959 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2960 KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS, 2961 thresholds); 2962 } 2963 setLowAmbientBrightnessThresholds(int[] ambientThresholds)2964 void setLowAmbientBrightnessThresholds(int[] ambientThresholds) { 2965 String thresholds = toPropertyValue(ambientThresholds); 2966 2967 if (DEBUG) { 2968 Slog.e(TAG, "Ambient Thresholds = " + thresholds); 2969 } 2970 2971 putPropertyAndNotify( 2972 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2973 KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS, 2974 thresholds); 2975 } 2976 setRefreshRateInHighZone(Integer fps)2977 void setRefreshRateInHighZone(Integer fps) { 2978 putPropertyAndNotify( 2979 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_HIGH_ZONE, 2980 String.valueOf(fps)); 2981 } 2982 setDefaultPeakRefreshRate(Integer fps)2983 void setDefaultPeakRefreshRate(Integer fps) { 2984 putPropertyAndNotify( 2985 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_PEAK_REFRESH_RATE_DEFAULT, 2986 String.valueOf(fps)); 2987 } 2988 setHighDisplayBrightnessThresholds(int[] brightnessThresholds)2989 void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) { 2990 String thresholds = toPropertyValue(brightnessThresholds); 2991 2992 if (DEBUG) { 2993 Slog.e(TAG, "Brightness Thresholds = " + thresholds); 2994 } 2995 2996 putPropertyAndNotify( 2997 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 2998 KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS, 2999 thresholds); 3000 } 3001 setHighAmbientBrightnessThresholds(int[] ambientThresholds)3002 void setHighAmbientBrightnessThresholds(int[] ambientThresholds) { 3003 String thresholds = toPropertyValue(ambientThresholds); 3004 3005 if (DEBUG) { 3006 Slog.e(TAG, "Ambient Thresholds = " + thresholds); 3007 } 3008 3009 putPropertyAndNotify( 3010 DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 3011 KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS, 3012 thresholds); 3013 } 3014 3015 @NonNull toPropertyValue(@onNull int[] intArray)3016 private static String toPropertyValue(@NonNull int[] intArray) { 3017 return Arrays.stream(intArray) 3018 .mapToObj(Integer::toString) 3019 .collect(Collectors.joining(",")); 3020 } 3021 } 3022 setBrightness(int brightness, int adjustedBrightness, DisplayListener listener)3023 private void setBrightness(int brightness, int adjustedBrightness, DisplayListener listener) { 3024 float floatBri = BrightnessSynchronizer.brightnessIntToFloat(brightness); 3025 float floatAdjBri = BrightnessSynchronizer.brightnessIntToFloat(adjustedBrightness); 3026 3027 when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( 3028 new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f, 3029 BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT, 3030 BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE)); 3031 listener.onDisplayChanged(DISPLAY_ID); 3032 } 3033 setPeakRefreshRate(float fps)3034 private void setPeakRefreshRate(float fps) { 3035 Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, 3036 fps); 3037 mInjector.notifyPeakRefreshRateChanged(); 3038 waitForIdleSync(); 3039 } 3040 createMockSensorManager(Sensor... sensors)3041 private static SensorManager createMockSensorManager(Sensor... sensors) { 3042 SensorManager sensorManager = mock(SensorManager.class); 3043 when(sensorManager.getSensorList(anyInt())).then((invocation) -> { 3044 List<Sensor> requestedSensors = new ArrayList<>(); 3045 int type = invocation.getArgument(0); 3046 for (Sensor sensor : sensors) { 3047 if (sensor.getType() == type || type == Sensor.TYPE_ALL) { 3048 requestedSensors.add(sensor); 3049 } 3050 } 3051 return requestedSensors; 3052 }); 3053 3054 when(sensorManager.getDefaultSensor(anyInt())).then((invocation) -> { 3055 int type = invocation.getArgument(0); 3056 for (Sensor sensor : sensors) { 3057 if (sensor.getType() == type) { 3058 return sensor; 3059 } 3060 } 3061 return null; 3062 }); 3063 return sensorManager; 3064 } 3065 createLightSensor()3066 private static Sensor createLightSensor() { 3067 try { 3068 return TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT); 3069 } catch (Exception e) { 3070 // There's nothing we can do if this fails, just throw a RuntimeException so that we 3071 // don't have to mark every function that might call this as throwing Exception 3072 throw new RuntimeException("Failed to create a light sensor", e); 3073 } 3074 } 3075 waitForIdleSync()3076 private void waitForIdleSync() { 3077 mHandler.runWithScissors(() -> { }, 500 /*timeout*/); 3078 } 3079 3080 public static class FakesInjector implements DisplayModeDirector.Injector { 3081 private final FakeDeviceConfig mDeviceConfig; 3082 private final DisplayInfo mDisplayInfo; 3083 private final Display mDisplay; 3084 private boolean mDisplayInfoValid = true; 3085 private ContentObserver mBrightnessObserver; 3086 private ContentObserver mPeakRefreshRateObserver; 3087 FakesInjector()3088 FakesInjector() { 3089 mDeviceConfig = new FakeDeviceConfig(); 3090 mDisplayInfo = new DisplayInfo(); 3091 mDisplayInfo.defaultModeId = MODE_ID; 3092 mDisplayInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID, 3093 800, 600, /* refreshRate= */ 60)}; 3094 mDisplay = createDisplay(DISPLAY_ID); 3095 } 3096 3097 @NonNull getDeviceConfig()3098 public FakeDeviceConfig getDeviceConfig() { 3099 return mDeviceConfig; 3100 } 3101 3102 @Override registerPeakRefreshRateObserver(@onNull ContentResolver cr, @NonNull ContentObserver observer)3103 public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, 3104 @NonNull ContentObserver observer) { 3105 mPeakRefreshRateObserver = observer; 3106 } 3107 3108 @Override registerDisplayListener(DisplayListener listener, Handler handler)3109 public void registerDisplayListener(DisplayListener listener, Handler handler) {} 3110 3111 @Override registerDisplayListener(DisplayListener listener, Handler handler, long flag)3112 public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {} 3113 3114 @Override getDisplay(int displayId)3115 public Display getDisplay(int displayId) { 3116 return mDisplay; 3117 } 3118 3119 @Override getDisplays()3120 public Display[] getDisplays() { 3121 return new Display[] { mDisplay }; 3122 } 3123 3124 @Override getDisplayInfo(int displayId, DisplayInfo displayInfo)3125 public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) { 3126 displayInfo.copyFrom(mDisplayInfo); 3127 return mDisplayInfoValid; 3128 } 3129 3130 @Override getBrightnessInfo(int displayId)3131 public BrightnessInfo getBrightnessInfo(int displayId) { 3132 return null; 3133 } 3134 3135 @Override isDozeState(Display d)3136 public boolean isDozeState(Display d) { 3137 return false; 3138 } 3139 3140 @Override registerThermalServiceListener(IThermalEventListener listener)3141 public boolean registerThermalServiceListener(IThermalEventListener listener) { 3142 return true; 3143 } 3144 3145 @Override unregisterThermalServiceListener(IThermalEventListener listener)3146 public void unregisterThermalServiceListener(IThermalEventListener listener) { 3147 } 3148 3149 @Override supportsFrameRateOverride()3150 public boolean supportsFrameRateOverride() { 3151 return true; 3152 } 3153 createDisplay(int id)3154 protected Display createDisplay(int id) { 3155 return new Display(DisplayManagerGlobal.getInstance(), id, mDisplayInfo, 3156 ApplicationProvider.getApplicationContext().getResources()); 3157 } 3158 notifyPeakRefreshRateChanged()3159 void notifyPeakRefreshRateChanged() { 3160 if (mPeakRefreshRateObserver != null) { 3161 mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/, 3162 PEAK_REFRESH_RATE_URI); 3163 } 3164 } 3165 } 3166 } 3167