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