1 /*
2  * Copyright (C) 2018 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.wm;
18 
19 import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
20 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
21 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
22 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
23 import static android.view.Surface.ROTATION_0;
24 import static android.view.Surface.ROTATION_180;
25 import static android.view.Surface.ROTATION_270;
26 import static android.view.Surface.ROTATION_90;
27 
28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
30 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
31 
32 import static org.junit.Assert.assertEquals;
33 
34 import android.graphics.Matrix;
35 import android.graphics.RectF;
36 import android.os.Binder;
37 import android.view.DisplayCutout;
38 import android.view.DisplayInfo;
39 import android.view.WindowManagerGlobal;
40 
41 import org.junit.Before;
42 
43 public class DisplayPolicyTestsBase extends WindowTestsBase {
44 
45     static final int DISPLAY_WIDTH = 500;
46     static final int DISPLAY_HEIGHT = 1000;
47 
48     static final int DISPLAY_CUTOUT_HEIGHT = 8;
49     static final int IME_HEIGHT = 415;
50 
51     DisplayPolicy mDisplayPolicy;
52 
53     @Before
setUpDisplayPolicy()54     public void setUpDisplayPolicy() {
55         // Disable surface placement because it has no direct relation to layout policy and it also
56         // avoids some noises such as the display info is modified, screen frozen, config change.
57         mWm.mWindowPlacerLocked.deferLayout();
58 
59         mDisplayPolicy = mDisplayContent.getDisplayPolicy();
60         spyOn(mDisplayPolicy);
61         doReturn(true).when(mDisplayPolicy).hasNavigationBar();
62         doReturn(true).when(mDisplayPolicy).hasStatusBar();
63         addWindow(mStatusBarWindow);
64         addWindow(mNavBarWindow);
65 
66         // Update source frame and visibility of insets providers.
67         mDisplayContent.getInsetsStateController().onPostLayout();
68     }
69 
addWindow(WindowState win)70     void addWindow(WindowState win) {
71         mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs);
72         assertEquals(WindowManagerGlobal.ADD_OKAY, mDisplayPolicy.validateAddingWindowLw(
73                 win.mAttrs, Binder.getCallingPid(), Binder.getCallingUid()));
74         mDisplayPolicy.addWindowLw(win, win.mAttrs);
75         win.mHasSurface = true;
76     }
77 
displayInfoAndCutoutForRotation(int rotation, boolean withDisplayCutout, boolean isLongEdgeCutout)78     DisplayInfo displayInfoAndCutoutForRotation(int rotation, boolean withDisplayCutout,
79             boolean isLongEdgeCutout) {
80         final DisplayInfo info = mDisplayContent.getDisplayInfo();
81         final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
82         info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
83         info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
84         info.rotation = rotation;
85         mDisplayContent.mInitialDisplayCutout = withDisplayCutout
86                 ? displayCutoutForRotation(ROTATION_0, isLongEdgeCutout)
87                 : DisplayCutout.NO_CUTOUT;
88         info.displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(rotation);
89         mDisplayContent.updateBaseDisplayMetrics(DISPLAY_WIDTH, DISPLAY_HEIGHT,
90                 info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi);
91         return info;
92     }
93 
displayCutoutForRotation(int rotation, boolean isLongEdgeCutout)94     private static DisplayCutout displayCutoutForRotation(int rotation, boolean isLongEdgeCutout) {
95         RectF rectF = new RectF();
96         if (isLongEdgeCutout) {
97             rectF.set(0, DISPLAY_HEIGHT / 4, DISPLAY_CUTOUT_HEIGHT, DISPLAY_HEIGHT * 3 / 4);
98         } else {
99             rectF.set(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT);
100         }
101 
102         final Matrix m = new Matrix();
103         transformPhysicalToLogicalCoordinates(rotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, m);
104         m.mapRect(rectF);
105 
106         int pos = -1;
107         switch (rotation) {
108             case ROTATION_0:
109                 pos = isLongEdgeCutout ? BOUNDS_POSITION_LEFT : BOUNDS_POSITION_TOP;
110                 break;
111             case ROTATION_90:
112                 pos = isLongEdgeCutout ? BOUNDS_POSITION_BOTTOM : BOUNDS_POSITION_LEFT;
113                 break;
114             case ROTATION_180:
115                 pos = isLongEdgeCutout ? BOUNDS_POSITION_RIGHT : BOUNDS_POSITION_BOTTOM;
116                 break;
117             case ROTATION_270:
118                 pos = isLongEdgeCutout ? BOUNDS_POSITION_TOP : BOUNDS_POSITION_RIGHT;
119                 break;
120         }
121 
122         return DisplayCutout.fromBoundingRect((int) rectF.left, (int) rectF.top,
123                 (int) rectF.right, (int) rectF.bottom, pos);
124     }
125 }
126