• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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