1 /* 2 * Copyright (C) 2021 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 android.view; 18 19 import static android.view.Display.DEFAULT_DISPLAY; 20 import static android.view.Surface.ROTATION_0; 21 import static android.view.Surface.ROTATION_90; 22 23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; 24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 26 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 27 28 import static com.google.common.truth.Truth.assertThat; 29 30 import android.content.Context; 31 import android.content.res.Resources; 32 import android.graphics.Point; 33 import android.graphics.Rect; 34 import android.hardware.display.DisplayManagerGlobal; 35 import android.platform.test.annotations.Presubmit; 36 import android.util.DisplayMetrics; 37 import android.view.DisplayAdjustments.FixedRotationAdjustments; 38 39 import androidx.test.core.app.ApplicationProvider; 40 import androidx.test.ext.junit.runners.AndroidJUnit4; 41 import androidx.test.filters.SmallTest; 42 43 import com.android.dx.mockito.inline.extended.StaticMockitoSession; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.Mockito; 50 import org.mockito.quality.Strictness; 51 52 import java.util.function.Consumer; 53 54 /** 55 * Tests for {@link Display}. 56 * 57 * <p>Build/Install/Run: 58 * 59 * atest FrameworksMockingCoreTests:android.view.DisplayTest 60 * 61 * <p>This test class is a part of Window Manager Service tests and specified in 62 * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. 63 */ 64 @RunWith(AndroidJUnit4.class) 65 @SmallTest 66 @Presubmit 67 public class DisplayTest { 68 69 private static final int APP_WIDTH = 272; 70 private static final int APP_HEIGHT = 700; 71 // Tablet size device, ROTATION_0 corresponds to portrait. 72 private static final int LOGICAL_WIDTH = 700; 73 private static final int LOGICAL_HEIGHT = 1800; 74 75 // Bounds of the app when the device is in portrait mode. 76 private static Rect sAppBoundsPortrait = buildAppBounds(LOGICAL_WIDTH, LOGICAL_HEIGHT); 77 private static Rect sAppBoundsLandscape = buildAppBounds(LOGICAL_HEIGHT, LOGICAL_WIDTH); 78 79 // Bounds of the device. 80 private static Rect sDeviceBoundsPortrait = new Rect(0, 0, LOGICAL_WIDTH, LOGICAL_HEIGHT); 81 private static Rect sDeviceBoundsLandscape = new Rect(0, 0, LOGICAL_HEIGHT, LOGICAL_WIDTH); 82 83 84 private StaticMockitoSession mMockitoSession; 85 86 private DisplayManagerGlobal mDisplayManagerGlobal; 87 private Context mApplicationContext; 88 private DisplayInfo mDisplayInfo = new DisplayInfo(); 89 90 @Before setupTests()91 public void setupTests() { 92 mMockitoSession = mockitoSession() 93 .mockStatic(DisplayManagerGlobal.class) 94 .strictness(Strictness.LENIENT) 95 .startMocking(); 96 97 // Ensure no adjustments are set before each test. 98 mApplicationContext = ApplicationProvider.getApplicationContext(); 99 DisplayAdjustments displayAdjustments = 100 mApplicationContext.getResources().getDisplayAdjustments(); 101 displayAdjustments.setFixedRotationAdjustments(null); 102 mApplicationContext.getResources().overrideDisplayAdjustments(null); 103 mApplicationContext.getResources().getConfiguration().windowConfiguration.setAppBounds( 104 null); 105 mApplicationContext.getResources().getConfiguration().windowConfiguration.setMaxBounds( 106 null); 107 mDisplayInfo.rotation = ROTATION_0; 108 109 mDisplayManagerGlobal = mock(DisplayManagerGlobal.class); 110 doReturn(mDisplayInfo).when(mDisplayManagerGlobal).getDisplayInfo(anyInt()); 111 } 112 113 @After teardownTests()114 public void teardownTests() { 115 if (mMockitoSession != null) { 116 mMockitoSession.finishMocking(); 117 } 118 Mockito.framework().clearInlineMocks(); 119 } 120 121 @Test testConstructor_defaultDisplayAdjustments_matchesDisplayInfo()122 public void testConstructor_defaultDisplayAdjustments_matchesDisplayInfo() { 123 setDisplayInfoPortrait(mDisplayInfo); 124 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 125 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 126 assertThat(display.getDisplayAdjustments()).isEqualTo( 127 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 128 DisplayInfo actualDisplayInfo = new DisplayInfo(); 129 display.getDisplayInfo(actualDisplayInfo); 130 verifyDisplayInfo(actualDisplayInfo, mDisplayInfo); 131 } 132 133 @Test testConstructor_defaultResources_matchesDisplayInfo()134 public void testConstructor_defaultResources_matchesDisplayInfo() { 135 setDisplayInfoPortrait(mDisplayInfo); 136 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 137 mApplicationContext.getResources()); 138 assertThat(display.getDisplayAdjustments()).isEqualTo( 139 mApplicationContext.getResources().getDisplayAdjustments()); 140 DisplayInfo actualDisplayInfo = new DisplayInfo(); 141 display.getDisplayInfo(actualDisplayInfo); 142 verifyDisplayInfo(actualDisplayInfo, mDisplayInfo); 143 } 144 145 @Test testGetRotation_defaultDisplayAdjustments_rotationNotAdjusted()146 public void testGetRotation_defaultDisplayAdjustments_rotationNotAdjusted() { 147 setDisplayInfoPortrait(mDisplayInfo); 148 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 149 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 150 assertThat(display.getRotation()).isEqualTo(ROTATION_0); 151 } 152 153 @Test testGetRotation_displayAdjustmentsWithoutOverride_rotationNotAdjusted()154 public void testGetRotation_displayAdjustmentsWithoutOverride_rotationNotAdjusted() { 155 // GIVEN display is not rotated. 156 setDisplayInfoPortrait(mDisplayInfo); 157 // GIVEN fixed rotation adjustments are rotated, but no override is set. 158 DisplayAdjustments displayAdjustments = DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; 159 final FixedRotationAdjustments fixedRotationAdjustments = 160 new FixedRotationAdjustments(ROTATION_90, APP_WIDTH, APP_HEIGHT, 161 DisplayCutout.NO_CUTOUT); 162 displayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments); 163 // GIVEN display is constructed with display adjustments. 164 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 165 displayAdjustments); 166 // THEN rotation is not adjusted since no override was set. 167 assertThat(display.getRotation()).isEqualTo(ROTATION_0); 168 } 169 170 @Test testGetRotation_resourcesWithoutOverride_rotationNotAdjusted()171 public void testGetRotation_resourcesWithoutOverride_rotationNotAdjusted() { 172 // GIVEN display is not rotated. 173 setDisplayInfoPortrait(mDisplayInfo); 174 // GIVEN fixed rotation adjustments are rotated, but no override is set. 175 setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 176 // GIVEN display is constructed with default resources. 177 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 178 mApplicationContext.getResources()); 179 // THEN rotation is not adjusted since no override is set. 180 assertThat(display.getRotation()).isEqualTo(ROTATION_0); 181 } 182 183 @Test testGetRotation_resourcesWithOverrideDisplayAdjustments_rotationAdjusted()184 public void testGetRotation_resourcesWithOverrideDisplayAdjustments_rotationAdjusted() { 185 // GIVEN display is not rotated. 186 setDisplayInfoPortrait(mDisplayInfo); 187 // GIVEN fixed rotation adjustments are rotated, and an override is set. 188 setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 189 // GIVEN display is constructed with default resources. 190 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 191 mApplicationContext.getResources()); 192 // THEN rotation is adjusted since an override is set. 193 assertThat(display.getRotation()).isEqualTo(ROTATION_90); 194 } 195 196 @Test testGetRealSize_defaultResourcesPortrait_matchesLogicalSize()197 public void testGetRealSize_defaultResourcesPortrait_matchesLogicalSize() { 198 // GIVEN display is not rotated. 199 setDisplayInfoPortrait(mDisplayInfo); 200 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 201 mApplicationContext.getResources()); 202 // THEN real size matches display orientation. 203 verifyRealSizeIsPortrait(display); 204 } 205 206 @Test testGetRealSize_defaultResourcesLandscape_matchesRotatedLogicalSize()207 public void testGetRealSize_defaultResourcesLandscape_matchesRotatedLogicalSize() { 208 // GIVEN display is rotated. 209 setDisplayInfoLandscape(mDisplayInfo); 210 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 211 mApplicationContext.getResources()); 212 // THEN real size matches display orientation. 213 verifyRealSizeIsLandscape(display); 214 } 215 216 @Test testGetRealSize_defaultDisplayAdjustmentsPortrait_matchesLogicalSize()217 public void testGetRealSize_defaultDisplayAdjustmentsPortrait_matchesLogicalSize() { 218 // GIVEN display is not rotated. 219 setDisplayInfoPortrait(mDisplayInfo); 220 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 221 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 222 // THEN real size matches display orientation. 223 verifyRealSizeIsPortrait(display); 224 } 225 226 @Test testGetRealSize_defaultDisplayAdjustmentsLandscape_matchesLogicalSize()227 public void testGetRealSize_defaultDisplayAdjustmentsLandscape_matchesLogicalSize() { 228 // GIVEN display is rotated. 229 setDisplayInfoLandscape(mDisplayInfo); 230 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 231 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 232 // THEN real size matches display orientation. 233 verifyRealSizeIsLandscape(display); 234 } 235 236 @Test testGetRealSize_resourcesPortraitWithFixedRotation_notRotatedLogicalSize()237 public void testGetRealSize_resourcesPortraitWithFixedRotation_notRotatedLogicalSize() { 238 // GIVEN display is rotated. 239 setDisplayInfoLandscape(mDisplayInfo); 240 // GIVEN fixed rotation adjustments are rotated. 241 setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0); 242 // GIVEN display is constructed with default resources. 243 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 244 mApplicationContext.getResources()); 245 // THEN real size matches display orientation. 246 verifyRealSizeIsLandscape(display); 247 } 248 249 @Test testGetRealSize_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize()250 public void testGetRealSize_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize() { 251 // GIVEN display is not rotated. 252 setDisplayInfoPortrait(mDisplayInfo); 253 // GIVEN fixed rotation adjustments are rotated. 254 setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 255 // GIVEN display is constructed with default resources. 256 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 257 mApplicationContext.getResources()); 258 // THEN real size matches display orientation. 259 verifyRealSizeIsPortrait(display); 260 } 261 262 @Test testGetRealSize_resourcesWithPortraitOverrideRotation_rotatedLogicalSize()263 public void testGetRealSize_resourcesWithPortraitOverrideRotation_rotatedLogicalSize() { 264 // GIVEN display is rotated. 265 setDisplayInfoLandscape(mDisplayInfo); 266 // GIVEN fixed rotation adjustments are rotated, and an override is set. 267 setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0); 268 // GIVEN display is constructed with default resources. 269 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 270 mApplicationContext.getResources()); 271 // THEN real size matches app orientation. 272 verifyRealSizeIsPortrait(display); 273 } 274 275 @Test testGetRealSize_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize()276 public void testGetRealSize_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize() { 277 // GIVEN display is not rotated. 278 setDisplayInfoPortrait(mDisplayInfo); 279 // GIVEN fixed rotation adjustments are rotated, and an override is set. 280 setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 281 // GIVEN display is constructed with default resources. 282 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 283 mApplicationContext.getResources()); 284 // THEN real size matches app orientation. 285 verifyRealSizeIsLandscape(display); 286 } 287 288 @Test testGetRealSize_resourcesPortraitSandboxed_matchesAppSandboxBounds()289 public void testGetRealSize_resourcesPortraitSandboxed_matchesAppSandboxBounds() { 290 // GIVEN display is not rotated. 291 setDisplayInfoPortrait(mDisplayInfo); 292 // GIVEN app is letterboxed. 293 setMaxBoundsSandboxed(mApplicationContext.getResources(), sAppBoundsPortrait); 294 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 295 mApplicationContext.getResources()); 296 // THEN real size matches app bounds. 297 verifyRealSizeMatchesBounds(display, sAppBoundsPortrait); 298 } 299 300 @Test testGetRealSize_resourcesPortraitSandboxed_matchesDisplayAreaSandboxBounds()301 public void testGetRealSize_resourcesPortraitSandboxed_matchesDisplayAreaSandboxBounds() { 302 // GIVEN display is not rotated. 303 setDisplayInfoPortrait(mDisplayInfo); 304 // GIVEN max bounds reflect DisplayArea size, which is the same size as the display. 305 setMaxBoundsSandboxed(mApplicationContext.getResources(), sDeviceBoundsPortrait); 306 // GIVEN app bounds do not stretch to include the full DisplayArea. 307 mApplicationContext.getResources().getConfiguration().windowConfiguration 308 .setAppBounds(buildAppBounds(LOGICAL_WIDTH, LOGICAL_HEIGHT - 10)); 309 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 310 mApplicationContext.getResources()); 311 // THEN real metrics matches max bounds for the DisplayArea. 312 verifyRealSizeMatchesBounds(display, sDeviceBoundsPortrait); 313 } 314 315 @Test testGetRealSize_resourcesLandscapeSandboxed_matchesAppSandboxBounds()316 public void testGetRealSize_resourcesLandscapeSandboxed_matchesAppSandboxBounds() { 317 // GIVEN display is rotated. 318 setDisplayInfoLandscape(mDisplayInfo); 319 // GIVEN app is letterboxed. 320 setMaxBoundsSandboxed(mApplicationContext.getResources(), sAppBoundsLandscape); 321 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 322 mApplicationContext.getResources()); 323 // THEN real size matches app bounds. 324 verifyRealSizeMatchesBounds(display, sAppBoundsLandscape); 325 } 326 327 @Test testGetRealSize_resourcesLandscapeSandboxed_matchesDisplayAreaSandboxBounds()328 public void testGetRealSize_resourcesLandscapeSandboxed_matchesDisplayAreaSandboxBounds() { 329 // GIVEN display is rotated. 330 setDisplayInfoLandscape(mDisplayInfo); 331 // GIVEN max bounds reflect DisplayArea size, which is the same size as the display. 332 setMaxBoundsSandboxed(mApplicationContext.getResources(), sDeviceBoundsLandscape); 333 // GIVEN app bounds do not stretch to include the full DisplayArea. 334 mApplicationContext.getResources().getConfiguration().windowConfiguration 335 .setAppBounds(buildAppBounds(LOGICAL_HEIGHT, LOGICAL_WIDTH - 10)); 336 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 337 mApplicationContext.getResources()); 338 // THEN real metrics matches max bounds for the DisplayArea. 339 verifyRealSizeMatchesBounds(display, sDeviceBoundsLandscape); 340 } 341 342 @Test testGetRealMetrics_defaultResourcesPortrait_matchesLogicalSize()343 public void testGetRealMetrics_defaultResourcesPortrait_matchesLogicalSize() { 344 // GIVEN display is not rotated. 345 setDisplayInfoPortrait(mDisplayInfo); 346 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 347 mApplicationContext.getResources()); 348 // THEN real metrics matches display orientation. 349 verifyRealMetricsIsPortrait(display); 350 } 351 352 @Test testGetRealMetrics_defaultResourcesLandscape_matchesRotatedLogicalSize()353 public void testGetRealMetrics_defaultResourcesLandscape_matchesRotatedLogicalSize() { 354 // GIVEN display is rotated. 355 setDisplayInfoLandscape(mDisplayInfo); 356 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 357 mApplicationContext.getResources()); 358 // THEN real metrics matches display orientation. 359 verifyRealMetricsIsLandscape(display); 360 } 361 362 @Test testGetRealMetrics_defaultDisplayAdjustmentsPortrait_matchesLogicalSize()363 public void testGetRealMetrics_defaultDisplayAdjustmentsPortrait_matchesLogicalSize() { 364 // GIVEN display is not rotated. 365 setDisplayInfoPortrait(mDisplayInfo); 366 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 367 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 368 // THEN real metrics matches display orientation. 369 verifyRealMetricsIsPortrait(display); 370 } 371 372 @Test testGetRealMetrics_defaultDisplayAdjustmentsLandscape_matchesLogicalSize()373 public void testGetRealMetrics_defaultDisplayAdjustmentsLandscape_matchesLogicalSize() { 374 // GIVEN display is rotated. 375 setDisplayInfoLandscape(mDisplayInfo); 376 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 377 DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 378 // THEN real metrics matches display orientation. 379 verifyRealMetricsIsLandscape(display); 380 } 381 382 @Test testGetRealMetrics_resourcesPortraitWithFixedRotation_notRotatedLogicalSize()383 public void testGetRealMetrics_resourcesPortraitWithFixedRotation_notRotatedLogicalSize() { 384 // GIVEN display is rotated. 385 setDisplayInfoLandscape(mDisplayInfo); 386 // GIVEN fixed rotation adjustments are rotated. 387 setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0); 388 // GIVEN display is constructed with default resources. 389 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 390 mApplicationContext.getResources()); 391 // THEN real metrics matches display orientation. 392 verifyRealMetricsIsLandscape(display); 393 } 394 395 @Test testGetRealMetrics_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize()396 public void testGetRealMetrics_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize() { 397 // GIVEN display is not rotated. 398 setDisplayInfoPortrait(mDisplayInfo); 399 // GIVEN fixed rotation adjustments are rotated. 400 setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 401 // GIVEN display is constructed with default resources. 402 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 403 mApplicationContext.getResources()); 404 // THEN real metrics matches display orientation. 405 verifyRealMetricsIsPortrait(display); 406 } 407 408 @Test testGetRealMetrics_resourcesWithPortraitOverrideRotation_rotatedLogicalSize()409 public void testGetRealMetrics_resourcesWithPortraitOverrideRotation_rotatedLogicalSize() { 410 // GIVEN display is rotated. 411 setDisplayInfoLandscape(mDisplayInfo); 412 // GIVEN fixed rotation adjustments are rotated with an override. 413 setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0); 414 // GIVEN display is constructed with default resources. 415 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 416 mApplicationContext.getResources()); 417 // THEN real metrics matches app orientation. 418 verifyRealMetricsIsPortrait(display); 419 } 420 421 @Test testGetRealMetrics_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize()422 public void testGetRealMetrics_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize() { 423 // GIVEN display is not rotated. 424 setDisplayInfoPortrait(mDisplayInfo); 425 // GIVEN fixed rotation adjustments are rotated. 426 setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90); 427 // GIVEN display is constructed with default resources. 428 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 429 mApplicationContext.getResources()); 430 // THEN real metrics matches app orientation. 431 verifyRealMetricsIsLandscape(display); 432 } 433 434 @Test testGetRealMetrics_resourcesPortraitSandboxed_matchesAppSandboxBounds()435 public void testGetRealMetrics_resourcesPortraitSandboxed_matchesAppSandboxBounds() { 436 // GIVEN display is not rotated. 437 setDisplayInfoPortrait(mDisplayInfo); 438 // GIVEN app is letterboxed. 439 setMaxBoundsSandboxed(mApplicationContext.getResources(), sAppBoundsPortrait); 440 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 441 mApplicationContext.getResources()); 442 // THEN real metrics matches app bounds. 443 verifyRealMetricsMatchesBounds(display, sAppBoundsPortrait); 444 } 445 446 @Test testGetRealMetrics_resourcesPortraitSandboxed_matchesDisplayAreaSandboxBounds()447 public void testGetRealMetrics_resourcesPortraitSandboxed_matchesDisplayAreaSandboxBounds() { 448 // GIVEN display is not rotated. 449 setDisplayInfoPortrait(mDisplayInfo); 450 // GIVEN max bounds reflect DisplayArea size, which is the same size as the display. 451 setMaxBoundsSandboxed(mApplicationContext.getResources(), sDeviceBoundsPortrait); 452 // GIVEN app bounds do not stretch to include the full DisplayArea. 453 mApplicationContext.getResources().getConfiguration().windowConfiguration 454 .setAppBounds(buildAppBounds(LOGICAL_WIDTH, LOGICAL_HEIGHT - 10)); 455 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 456 mApplicationContext.getResources()); 457 // THEN real metrics matches max bounds for the DisplayArea. 458 verifyRealMetricsMatchesBounds(display, sDeviceBoundsPortrait); 459 } 460 461 @Test testGetRealMetrics_resourcesLandscapeSandboxed_matchesAppSandboxBounds()462 public void testGetRealMetrics_resourcesLandscapeSandboxed_matchesAppSandboxBounds() { 463 // GIVEN display is rotated. 464 setDisplayInfoLandscape(mDisplayInfo); 465 // GIVEN app is letterboxed. 466 setMaxBoundsSandboxed(mApplicationContext.getResources(), sAppBoundsLandscape); 467 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 468 mApplicationContext.getResources()); 469 // THEN real metrics matches app bounds. 470 verifyRealMetricsMatchesBounds(display, sAppBoundsLandscape); 471 } 472 473 @Test testGetRealMetrics_resourcesLandscapeSandboxed_matchesDisplayAreaSandboxBounds()474 public void testGetRealMetrics_resourcesLandscapeSandboxed_matchesDisplayAreaSandboxBounds() { 475 // GIVEN display is rotated. 476 setDisplayInfoLandscape(mDisplayInfo); 477 // GIVEN max bounds reflect DisplayArea size, which is the same size as the display. 478 setMaxBoundsSandboxed(mApplicationContext.getResources(), sDeviceBoundsLandscape); 479 // GIVEN app bounds do not stretch to include the full DisplayArea. 480 mApplicationContext.getResources().getConfiguration().windowConfiguration 481 .setAppBounds(buildAppBounds(LOGICAL_HEIGHT, LOGICAL_WIDTH - 10)); 482 final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo, 483 mApplicationContext.getResources()); 484 // THEN real metrics matches max bounds for the DisplayArea. 485 verifyRealMetricsMatchesBounds(display, sDeviceBoundsLandscape); 486 } 487 488 // Given rotated display dimensions, calculate the letterboxed app bounds. buildAppBounds(int displayWidth, int displayHeight)489 private static Rect buildAppBounds(int displayWidth, int displayHeight) { 490 final int midWidth = displayWidth / 2; 491 final int left = midWidth - (APP_WIDTH / 2); 492 final int right = midWidth + (APP_WIDTH / 2); 493 final int midHeight = displayHeight / 2; 494 // Coordinate system starts at top left. 495 final int top = midHeight - (APP_HEIGHT / 2); 496 final int bottom = midHeight + (APP_HEIGHT / 2); 497 return new Rect(left, top, right, bottom); 498 } 499 setDisplayInfoLandscape(DisplayInfo displayInfo)500 private static void setDisplayInfoLandscape(DisplayInfo displayInfo) { 501 displayInfo.rotation = ROTATION_90; 502 // Flip width & height assignment since the device is rotated. 503 displayInfo.logicalWidth = LOGICAL_HEIGHT; 504 displayInfo.logicalHeight = LOGICAL_WIDTH; 505 } 506 setDisplayInfoPortrait(DisplayInfo displayInfo)507 private static void setDisplayInfoPortrait(DisplayInfo displayInfo) { 508 displayInfo.rotation = ROTATION_0; 509 displayInfo.logicalWidth = LOGICAL_WIDTH; 510 displayInfo.logicalHeight = LOGICAL_HEIGHT; 511 } 512 513 /** 514 * Set max bounds to be sandboxed to the app bounds, indicating the app is in 515 * size compat mode or letterbox. 516 */ setMaxBoundsSandboxed(Resources resources, Rect bounds)517 private static void setMaxBoundsSandboxed(Resources resources, Rect bounds) { 518 resources.getConfiguration().windowConfiguration.setMaxBounds(bounds); 519 } 520 521 /** 522 * Do not compare entire display info, since it is updated to match display the test is run on. 523 */ verifyDisplayInfo(DisplayInfo actual, DisplayInfo expected)524 private static void verifyDisplayInfo(DisplayInfo actual, DisplayInfo expected) { 525 assertThat(actual.displayId).isEqualTo(expected.displayId); 526 assertThat(actual.rotation).isEqualTo(expected.rotation); 527 assertThat(actual.logicalWidth).isEqualTo(LOGICAL_WIDTH); 528 assertThat(actual.logicalHeight).isEqualTo(LOGICAL_HEIGHT); 529 } 530 verifyRealSizeIsLandscape(Display display)531 private static void verifyRealSizeIsLandscape(Display display) { 532 Point size = new Point(); 533 display.getRealSize(size); 534 // Flip the width and height check since the device is rotated. 535 assertThat(size).isEqualTo(new Point(LOGICAL_HEIGHT, LOGICAL_WIDTH)); 536 } 537 verifyRealMetricsIsLandscape(Display display)538 private static void verifyRealMetricsIsLandscape(Display display) { 539 DisplayMetrics metrics = new DisplayMetrics(); 540 display.getRealMetrics(metrics); 541 // Flip the width and height check since the device is rotated. 542 assertThat(metrics.widthPixels).isEqualTo(LOGICAL_HEIGHT); 543 assertThat(metrics.heightPixels).isEqualTo(LOGICAL_WIDTH); 544 } 545 verifyRealSizeIsPortrait(Display display)546 private static void verifyRealSizeIsPortrait(Display display) { 547 Point size = new Point(); 548 display.getRealSize(size); 549 assertThat(size).isEqualTo(new Point(LOGICAL_WIDTH, LOGICAL_HEIGHT)); 550 } 551 verifyRealMetricsIsPortrait(Display display)552 private static void verifyRealMetricsIsPortrait(Display display) { 553 DisplayMetrics metrics = new DisplayMetrics(); 554 display.getRealMetrics(metrics); 555 assertThat(metrics.widthPixels).isEqualTo(LOGICAL_WIDTH); 556 assertThat(metrics.heightPixels).isEqualTo(LOGICAL_HEIGHT); 557 } 558 verifyRealSizeMatchesBounds(Display display, Rect bounds)559 private static void verifyRealSizeMatchesBounds(Display display, Rect bounds) { 560 Point size = new Point(); 561 display.getRealSize(size); 562 assertThat(size).isEqualTo(new Point(bounds.width(), bounds.height())); 563 } 564 verifyRealMetricsMatchesBounds(Display display, Rect bounds)565 private static void verifyRealMetricsMatchesBounds(Display display, Rect bounds) { 566 DisplayMetrics metrics = new DisplayMetrics(); 567 display.getRealMetrics(metrics); 568 assertThat(metrics.widthPixels).isEqualTo(bounds.width()); 569 assertThat(metrics.heightPixels).isEqualTo(bounds.height()); 570 } 571 setOverrideFixedRotationAdjustments( Resources resources, @Surface.Rotation int rotation)572 private static FixedRotationAdjustments setOverrideFixedRotationAdjustments( 573 Resources resources, @Surface.Rotation int rotation) { 574 FixedRotationAdjustments fixedRotationAdjustments = 575 setFixedRotationAdjustments(resources, rotation); 576 resources.overrideDisplayAdjustments( 577 buildOverrideRotationAdjustments(fixedRotationAdjustments)); 578 return fixedRotationAdjustments; 579 } 580 setFixedRotationAdjustments(Resources resources, @Surface.Rotation int rotation)581 private static FixedRotationAdjustments setFixedRotationAdjustments(Resources resources, 582 @Surface.Rotation int rotation) { 583 final FixedRotationAdjustments fixedRotationAdjustments = 584 new FixedRotationAdjustments(rotation, APP_WIDTH, APP_HEIGHT, 585 DisplayCutout.NO_CUTOUT); 586 resources.getDisplayAdjustments().setFixedRotationAdjustments(fixedRotationAdjustments); 587 return fixedRotationAdjustments; 588 } 589 buildOverrideRotationAdjustments( FixedRotationAdjustments fixedRotationAdjustments)590 private static Consumer<DisplayAdjustments> buildOverrideRotationAdjustments( 591 FixedRotationAdjustments fixedRotationAdjustments) { 592 return consumedDisplayAdjustments 593 -> consumedDisplayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments); 594 } 595 } 596