1 /* 2 * Copyright (C) 2016 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.server.wm; 18 19 import static android.server.am.ComponentNameUtils.getWindowName; 20 import static android.server.wm.DialogFrameTestActivity.DIALOG_WINDOW_NAME; 21 import static android.server.wm.DialogFrameTestActivity.TEST_EXPLICIT_POSITION_MATCH_PARENT; 22 import static android.server.wm.DialogFrameTestActivity.TEST_EXPLICIT_POSITION_MATCH_PARENT_NO_LIMITS; 23 import static android.server.wm.DialogFrameTestActivity.TEST_EXPLICIT_SIZE; 24 import static android.server.wm.DialogFrameTestActivity.TEST_EXPLICIT_SIZE_BOTTOM_RIGHT_GRAVITY; 25 import static android.server.wm.DialogFrameTestActivity.TEST_EXPLICIT_SIZE_TOP_LEFT_GRAVITY; 26 import static android.server.wm.DialogFrameTestActivity.TEST_MATCH_PARENT; 27 import static android.server.wm.DialogFrameTestActivity.TEST_MATCH_PARENT_LAYOUT_IN_OVERSCAN; 28 import static android.server.wm.DialogFrameTestActivity.TEST_NO_FOCUS; 29 import static android.server.wm.DialogFrameTestActivity.TEST_OVER_SIZED_DIMENSIONS; 30 import static android.server.wm.DialogFrameTestActivity.TEST_OVER_SIZED_DIMENSIONS_NO_LIMITS; 31 import static android.server.wm.DialogFrameTestActivity.TEST_WITH_MARGINS; 32 33 import static org.hamcrest.MatcherAssert.assertThat; 34 import static org.hamcrest.Matchers.greaterThan; 35 import static org.junit.Assert.assertEquals; 36 37 import android.content.ComponentName; 38 import android.graphics.Rect; 39 import android.platform.test.annotations.AppModeFull; 40 import android.server.am.WaitForValidActivityState; 41 import android.server.am.WindowManagerState; 42 import android.server.am.WindowManagerState.WindowState; 43 import android.support.test.InstrumentationRegistry; 44 import android.support.test.rule.ActivityTestRule; 45 46 import org.junit.Ignore; 47 import org.junit.Rule; 48 import org.junit.Test; 49 50 import java.util.List; 51 52 /** 53 * Build/Install/Run: 54 * atest CtsWindowManagerDeviceTestCases:DialogFrameTests 55 * 56 * TODO: Consolidate this class with {@link ParentChildTestBase}. 57 */ 58 @AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_STACKS") 59 public class DialogFrameTests extends ParentChildTestBase<DialogFrameTestActivity> { 60 61 private static final ComponentName DIALOG_FRAME_TEST_ACTIVITY = new ComponentName( 62 InstrumentationRegistry.getContext(), DialogFrameTestActivity.class); 63 64 @Rule 65 public final ActivityTestRule<DialogFrameTestActivity> mDialogTestActivity = 66 new ActivityTestRule<>(DialogFrameTestActivity.class, false /* initialTOuchMode */, 67 false /* launchActivity */); 68 69 @Override activityName()70 ComponentName activityName() { 71 return DIALOG_FRAME_TEST_ACTIVITY; 72 } 73 74 @Override activityRule()75 ActivityTestRule<DialogFrameTestActivity> activityRule() { 76 return mDialogTestActivity; 77 } 78 getSingleWindow(final String windowName)79 private WindowState getSingleWindow(final String windowName) { 80 final List<WindowState> windowList = 81 mAmWmState.getWmState().getMatchingVisibleWindowState(windowName); 82 assertThat(windowList.size(), greaterThan(0)); 83 return windowList.get(0); 84 } 85 86 @Override doSingleTest(ParentChildTest t)87 void doSingleTest(ParentChildTest t) throws Exception { 88 mAmWmState.computeState(WaitForValidActivityState.forWindow(DIALOG_WINDOW_NAME)); 89 WindowState dialog = getSingleWindow(DIALOG_WINDOW_NAME); 90 WindowState parent = getSingleWindow(getWindowName(activityName())); 91 92 t.doTest(parent, dialog); 93 } 94 95 // With Width and Height as MATCH_PARENT we should fill 96 // the same content frame as the main activity window 97 @Test testMatchParentDialog()98 public void testMatchParentDialog() throws Exception { 99 doParentChildTest(TEST_MATCH_PARENT, (parent, dialog) -> 100 assertEquals(parent.getContentFrame(), dialog.getFrame()) 101 ); 102 } 103 104 // If we have LAYOUT_IN_SCREEN and LAYOUT_IN_OVERSCAN with MATCH_PARENT, 105 // we will not be constrained to the insets and so we will be the same size 106 // as the main window main frame. 107 @Test testMatchParentDialogLayoutInOverscan()108 public void testMatchParentDialogLayoutInOverscan() throws Exception { 109 doParentChildTest(TEST_MATCH_PARENT_LAYOUT_IN_OVERSCAN, (parent, dialog) -> 110 assertEquals(parent.getFrame(), dialog.getFrame()) 111 ); 112 } 113 114 private static final int explicitDimension = 200; 115 116 // The default gravity for dialogs should center them. 117 @Test testExplicitSizeDefaultGravity()118 public void testExplicitSizeDefaultGravity() throws Exception { 119 doParentChildTest(TEST_EXPLICIT_SIZE, (parent, dialog) -> { 120 Rect contentFrame = parent.getContentFrame(); 121 Rect expectedFrame = new Rect( 122 contentFrame.left + (contentFrame.width() - explicitDimension) / 2, 123 contentFrame.top + (contentFrame.height() - explicitDimension) / 2, 124 contentFrame.left + (contentFrame.width() + explicitDimension) / 2, 125 contentFrame.top + (contentFrame.height() + explicitDimension) / 2); 126 assertEquals(expectedFrame, dialog.getFrame()); 127 }); 128 } 129 130 @Test testExplicitSizeTopLeftGravity()131 public void testExplicitSizeTopLeftGravity() throws Exception { 132 doParentChildTest(TEST_EXPLICIT_SIZE_TOP_LEFT_GRAVITY, (parent, dialog) -> { 133 Rect contentFrame = parent.getContentFrame(); 134 Rect expectedFrame = new Rect( 135 contentFrame.left, 136 contentFrame.top, 137 contentFrame.left + explicitDimension, 138 contentFrame.top + explicitDimension); 139 assertEquals(expectedFrame, dialog.getFrame()); 140 }); 141 } 142 143 @Test testExplicitSizeBottomRightGravity()144 public void testExplicitSizeBottomRightGravity() throws Exception { 145 doParentChildTest(TEST_EXPLICIT_SIZE_BOTTOM_RIGHT_GRAVITY, (parent, dialog) -> { 146 Rect contentFrame = parent.getContentFrame(); 147 Rect expectedFrame = new Rect( 148 contentFrame.left + contentFrame.width() - explicitDimension, 149 contentFrame.top + contentFrame.height() - explicitDimension, 150 contentFrame.left + contentFrame.width(), 151 contentFrame.top + contentFrame.height()); 152 assertEquals(expectedFrame, dialog.getFrame()); 153 }); 154 } 155 156 // TODO(b/30127373): Commented out for now because it doesn't work. We end up insetting the 157 // decor on the bottom. I think this is a bug probably in the default dialog flags: 158 @Ignore 159 @Test testOversizedDimensions()160 public void testOversizedDimensions() throws Exception { 161 doParentChildTest(TEST_OVER_SIZED_DIMENSIONS, (parent, dialog) -> 162 // With the default flags oversize should result in clipping to 163 // parent frame. 164 assertEquals(parent.getContentFrame(), dialog.getFrame()) 165 ); 166 } 167 168 // TODO(b/63993863) : Disabled pending public API to fetch maximum surface size. 169 static final int oversizedDimension = 5000; 170 // With FLAG_LAYOUT_NO_LIMITS we should get the size we request, even if its much larger than 171 // the screen. 172 @Ignore 173 @Test testOversizedDimensionsNoLimits()174 public void testOversizedDimensionsNoLimits() throws Exception { 175 // TODO(b/36890978): We only run this in fullscreen because of the 176 // unclear status of NO_LIMITS for non-child surfaces in MW modes 177 doFullscreenTest(TEST_OVER_SIZED_DIMENSIONS_NO_LIMITS, (parent, dialog) -> { 178 Rect contentFrame = parent.getContentFrame(); 179 Rect expectedFrame = new Rect(contentFrame.left, contentFrame.top, 180 contentFrame.left + oversizedDimension, 181 contentFrame.top + oversizedDimension); 182 assertEquals(expectedFrame, dialog.getFrame()); 183 }); 184 } 185 186 // If we request the MATCH_PARENT and a non-zero position, we wouldn't be 187 // able to fit all of our content, so we should be adjusted to just fit the 188 // content frame. 189 @Test testExplicitPositionMatchParent()190 public void testExplicitPositionMatchParent() throws Exception { 191 doParentChildTest(TEST_EXPLICIT_POSITION_MATCH_PARENT, (parent, dialog) -> 192 assertEquals(parent.getContentFrame(), dialog.getFrame()) 193 ); 194 } 195 196 // Unless we pass NO_LIMITS in which case our requested position should 197 // be honored. 198 @Test testExplicitPositionMatchParentNoLimits()199 public void testExplicitPositionMatchParentNoLimits() throws Exception { 200 final int explicitPosition = 100; 201 doParentChildTest(TEST_EXPLICIT_POSITION_MATCH_PARENT_NO_LIMITS, (parent, dialog) -> { 202 Rect contentFrame = parent.getContentFrame(); 203 Rect expectedFrame = new Rect(contentFrame); 204 expectedFrame.offset(explicitPosition, explicitPosition); 205 assertEquals(expectedFrame, dialog.getFrame()); 206 }); 207 } 208 209 // We run the two focus tests fullscreen only because switching to the 210 // docked stack will strip away focus from the task anyway. 211 @Test testDialogReceivesFocus()212 public void testDialogReceivesFocus() throws Exception { 213 doFullscreenTest(TEST_MATCH_PARENT, (parent, dialog) -> 214 assertEquals(dialog.getName(), mAmWmState.getWmState().getFocusedWindow()) 215 ); 216 } 217 218 @Test testNoFocusDialog()219 public void testNoFocusDialog() throws Exception { 220 doFullscreenTest(TEST_NO_FOCUS, (parent, dialog) -> 221 assertEquals(parent.getName(), mAmWmState.getWmState().getFocusedWindow()) 222 ); 223 } 224 225 @Test testMarginsArePercentagesOfContentFrame()226 public void testMarginsArePercentagesOfContentFrame() throws Exception { 227 float horizontalMargin = .25f; 228 float verticalMargin = .35f; 229 doParentChildTest(TEST_WITH_MARGINS, (parent, dialog) -> { 230 Rect frame = parent.getContentFrame(); 231 Rect expectedFrame = new Rect( 232 (int) (horizontalMargin * frame.width() + frame.left), 233 (int) (verticalMargin * frame.height() + frame.top), 234 (int) (horizontalMargin * frame.width() + frame.left) + explicitDimension, 235 (int) (verticalMargin * frame.height() + frame.top) + explicitDimension); 236 assertEquals(expectedFrame, dialog.getFrame()); 237 }); 238 } 239 240 @Test testDialogPlacedAboveParent()241 public void testDialogPlacedAboveParent() throws Exception { 242 final WindowManagerState wmState = mAmWmState.getWmState(); 243 doParentChildTest(TEST_MATCH_PARENT, (parent, dialog) -> 244 // Not only should the dialog be higher, but it should be leave multiple layers of 245 // space in between for DimLayers, etc... 246 assertThat(wmState.getZOrder(dialog), greaterThan(wmState.getZOrder(parent))) 247 ); 248 } 249 } 250