• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.util.DisplayMetrics.DENSITY_DEFAULT;
20 import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
21 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
22 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
23 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
24 import static android.view.Surface.ROTATION_0;
25 import static android.view.Surface.ROTATION_180;
26 import static android.view.Surface.ROTATION_270;
27 import static android.view.Surface.ROTATION_90;
28 
29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
31 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
32 
33 import static org.junit.Assert.assertEquals;
34 
35 import android.content.Context;
36 import android.content.ContextWrapper;
37 import android.content.pm.PackageManager;
38 import android.content.res.Resources;
39 import android.graphics.Matrix;
40 import android.graphics.RectF;
41 import android.os.Binder;
42 import android.os.IBinder;
43 import android.testing.TestableResources;
44 import android.util.Pair;
45 import android.view.DisplayCutout;
46 import android.view.DisplayInfo;
47 import android.view.Gravity;
48 import android.view.WindowManagerGlobal;
49 
50 import com.android.internal.R;
51 import com.android.server.wm.utils.WmDisplayCutout;
52 
53 import org.junit.Before;
54 
55 public class DisplayPolicyTestsBase extends WindowTestsBase {
56 
57     static final int DISPLAY_WIDTH = 500;
58     static final int DISPLAY_HEIGHT = 1000;
59     static final int DISPLAY_DENSITY = 320;
60 
61     static final int STATUS_BAR_HEIGHT = 10;
62     static final int NAV_BAR_HEIGHT = 15;
63     static final int DISPLAY_CUTOUT_HEIGHT = 8;
64     static final int IME_HEIGHT = 415;
65 
66     DisplayPolicy mDisplayPolicy;
67 
68     @Before
setUpDisplayPolicy()69     public void setUpDisplayPolicy() {
70         // Disable surface placement because it has no direct relation to layout policy and it also
71         // avoids some noises such as the display info is modified, screen frozen, config change.
72         mWm.mWindowPlacerLocked.deferLayout();
73 
74         mDisplayPolicy = mDisplayContent.getDisplayPolicy();
75         spyOn(mDisplayPolicy);
76 
77         final TestContextWrapper context = new TestContextWrapper(
78                 mDisplayPolicy.getContext(), mDisplayPolicy.getCurrentUserResources());
79         final TestableResources resources = context.getResourceMocker();
80         resources.addOverride(R.dimen.status_bar_height_portrait, STATUS_BAR_HEIGHT);
81         resources.addOverride(R.dimen.status_bar_height_landscape, STATUS_BAR_HEIGHT);
82         resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT);
83         resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT);
84         resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT);
85         resources.addOverride(R.dimen.navigation_bar_frame_height_landscape, NAV_BAR_HEIGHT);
86         resources.addOverride(R.dimen.navigation_bar_frame_height, NAV_BAR_HEIGHT);
87         doReturn(resources.getResources()).when(mDisplayPolicy).getCurrentUserResources();
88         doReturn(true).when(mDisplayPolicy).hasNavigationBar();
89         doReturn(true).when(mDisplayPolicy).hasStatusBar();
90 
91         final int shortSizeDp =
92                 Math.min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * DENSITY_DEFAULT / DISPLAY_DENSITY;
93         final int longSizeDp =
94                 Math.min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * DENSITY_DEFAULT / DISPLAY_DENSITY;
95         mDisplayContent.getDisplayRotation().configure(
96                 DISPLAY_WIDTH, DISPLAY_HEIGHT, shortSizeDp, longSizeDp);
97         mDisplayPolicy.onConfigurationChanged();
98 
99         mStatusBarWindow.mAttrs.gravity = Gravity.TOP;
100         addWindow(mStatusBarWindow);
101 
102         mNavBarWindow.mAttrs.gravity = Gravity.BOTTOM;
103         addWindow(mNavBarWindow);
104 
105         // Update source frame and visibility of insets providers.
106         mDisplayContent.getInsetsStateController().onPostLayout();
107     }
108 
addWindow(WindowState win)109     void addWindow(WindowState win) {
110         mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs);
111         assertEquals(WindowManagerGlobal.ADD_OKAY, mDisplayPolicy.validateAddingWindowLw(
112                 win.mAttrs, Binder.getCallingPid(), Binder.getCallingUid()));
113         mDisplayPolicy.addWindowLw(win, win.mAttrs);
114         win.mHasSurface = true;
115     }
116 
displayInfoAndCutoutForRotation(int rotation, boolean withDisplayCutout, boolean isLongEdgeCutout)117     static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation,
118             boolean withDisplayCutout, boolean isLongEdgeCutout) {
119         final DisplayInfo info = new DisplayInfo();
120         WmDisplayCutout cutout = WmDisplayCutout.NO_CUTOUT;
121 
122         final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
123         info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
124         info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
125         info.rotation = rotation;
126         if (withDisplayCutout) {
127             cutout = WmDisplayCutout.computeSafeInsets(
128                     displayCutoutForRotation(rotation, isLongEdgeCutout), info.logicalWidth,
129                     info.logicalHeight);
130             info.displayCutout = cutout.getDisplayCutout();
131         } else {
132             info.displayCutout = null;
133         }
134         return Pair.create(info, cutout);
135     }
136 
displayCutoutForRotation(int rotation, boolean isLongEdgeCutout)137     private static DisplayCutout displayCutoutForRotation(int rotation, boolean isLongEdgeCutout) {
138         RectF rectF = new RectF();
139         if (isLongEdgeCutout) {
140             rectF.set(0, DISPLAY_HEIGHT / 4, DISPLAY_CUTOUT_HEIGHT, DISPLAY_HEIGHT * 3 / 4);
141         } else {
142             rectF.set(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT);
143         }
144 
145         final Matrix m = new Matrix();
146         transformPhysicalToLogicalCoordinates(rotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, m);
147         m.mapRect(rectF);
148 
149         int pos = -1;
150         switch (rotation) {
151             case ROTATION_0:
152                 pos = isLongEdgeCutout ? BOUNDS_POSITION_LEFT : BOUNDS_POSITION_TOP;
153                 break;
154             case ROTATION_90:
155                 pos = isLongEdgeCutout ? BOUNDS_POSITION_BOTTOM : BOUNDS_POSITION_LEFT;
156                 break;
157             case ROTATION_180:
158                 pos = isLongEdgeCutout ? BOUNDS_POSITION_RIGHT : BOUNDS_POSITION_BOTTOM;
159                 break;
160             case ROTATION_270:
161                 pos = isLongEdgeCutout ? BOUNDS_POSITION_TOP : BOUNDS_POSITION_RIGHT;
162                 break;
163         }
164 
165         return DisplayCutout.fromBoundingRect((int) rectF.left, (int) rectF.top,
166                 (int) rectF.right, (int) rectF.bottom, pos);
167     }
168 
169     static class TestContextWrapper extends ContextWrapper {
170         private final TestableResources mResourceMocker;
171 
TestContextWrapper(Context targetContext, Resources targetResources)172         TestContextWrapper(Context targetContext, Resources targetResources) {
173             super(targetContext);
174             mResourceMocker = new TestableResources(targetResources);
175         }
176 
177         @Override
checkPermission(String permission, int pid, int uid)178         public int checkPermission(String permission, int pid, int uid) {
179             return PackageManager.PERMISSION_GRANTED;
180         }
181 
182         @Override
checkPermission(String permission, int pid, int uid, IBinder callerToken)183         public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
184             return PackageManager.PERMISSION_GRANTED;
185         }
186 
187         @Override
getResources()188         public Resources getResources() {
189             return mResourceMocker.getResources();
190         }
191 
getResourceMocker()192         TestableResources getResourceMocker() {
193             return mResourceMocker;
194         }
195     }
196 
197 }
198