blob: 63ac4af4720794ebc90ff15f20e05b011d46c671 [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
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
17package com.android.server.wm;
18
Wale Ogunwale68278562017-09-23 17:13:55 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Andrii Kulian92c9a942017-10-10 00:41:41 -070021import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
22import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwale34247952017-02-19 11:57:53 -080024import static android.view.Display.DEFAULT_DISPLAY;
25import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
26import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
27import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070028import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080029import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
David Stevens46939562017-03-24 13:04:00 -070030import static com.android.server.wm.WindowContainer.POSITION_TOP;
chaviwebcbc342018-02-07 13:19:00 -080031
Wale Ogunwale34247952017-02-19 11:57:53 -080032import static org.junit.Assert.assertEquals;
33import static org.junit.Assert.assertTrue;
34
Wale Ogunwale42bab782017-05-02 13:16:39 -070035import org.junit.Ignore;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070036import org.junit.Test;
37import org.junit.runner.RunWith;
38
Andrii Kulian92c9a942017-10-10 00:41:41 -070039import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080040import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010041import android.graphics.Path;
Adrian Roos1cf585052018-01-03 18:43:27 +010042import android.graphics.Rect;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070043import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070044import android.platform.test.annotations.Presubmit;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070045import android.support.test.filters.SmallTest;
46import android.support.test.runner.AndroidJUnit4;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070047import android.util.DisplayMetrics;
Andrii Kulian0214ed92017-05-16 13:44:05 -070048import android.util.SparseIntArray;
Adrian Roos1cf585052018-01-03 18:43:27 +010049import android.view.DisplayCutout;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070050import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010051import android.view.Surface;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070052
Wale Ogunwale34247952017-02-19 11:57:53 -080053import java.util.Arrays;
54import java.util.LinkedList;
55import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070056
57/**
58 * Tests for the {@link DisplayContent} class.
59 *
60 * Build/Install/Run:
Adrian Roos1cf585052018-01-03 18:43:27 +010061 * atest com.android.server.wm.DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070062 */
63@SmallTest
64@Presubmit
65@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080066public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070067
68 @Test
69 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080070 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070071 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070072 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
73 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080074 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070075
Wale Ogunwale34247952017-02-19 11:57:53 -080076 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070077 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080078 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070079 mChildAppWindowBelow,
80 mAppWindow,
81 mChildAppWindowAbove,
82 mDockedDividerWindow,
83 mStatusBarWindow,
84 mNavBarWindow,
85 mImeWindow,
86 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080087 }
88
89 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080090 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080091 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -070092 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080093
94 sWm.mInputMethodTarget = imeAppTarget;
95
Wale Ogunwale34247952017-02-19 11:57:53 -080096 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070097 mWallpaperWindow,
98 mChildAppWindowBelow,
99 mAppWindow,
100 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800101 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700102 mImeWindow,
103 mImeDialogWindow,
104 mDockedDividerWindow,
105 mStatusBarWindow,
106 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800107 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800108
Wale Ogunwale34247952017-02-19 11:57:53 -0800109 @Test
110 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700111 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800112
Wale Ogunwale34247952017-02-19 11:57:53 -0800113 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700114 mWallpaperWindow,
115 mChildAppWindowBelow,
116 mAppWindow,
117 mChildAppWindowAbove,
118 mImeWindow,
119 mImeDialogWindow,
120 mDockedDividerWindow,
121 mStatusBarWindow,
122 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700123 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800124
125 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800126 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700127 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800128
Wale Ogunwale34247952017-02-19 11:57:53 -0800129 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700130 mWallpaperWindow,
131 mChildAppWindowBelow,
132 mAppWindow,
133 mChildAppWindowAbove,
134 mDockedDividerWindow,
135 mStatusBarWindow,
136 mImeWindow,
137 mImeDialogWindow,
138 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800139 }
140
141 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800142 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
143 // This window is set-up to be z-ordered between some windows that go in the same token like
144 // the nav bar and status bar.
145 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700146 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800147
Wale Ogunwale34247952017-02-19 11:57:53 -0800148 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700149 mWallpaperWindow,
150 mChildAppWindowBelow,
151 mAppWindow,
152 mChildAppWindowAbove,
153 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800154 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700155 mStatusBarWindow,
156 mNavBarWindow,
157 mImeWindow,
158 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800159 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800160
Wale Ogunwale34247952017-02-19 11:57:53 -0800161 @Test
162 public void testComputeImeTarget() throws Exception {
163 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700164 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800165 appWin.setHasSurface(true);
166 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700167 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800168 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800169 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800170
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 // Verify that an child window can be an ime target.
172 final WindowState childWin = createWindow(appWin,
173 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
174 childWin.setHasSurface(true);
175 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700176 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800177 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800178 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800179
Andrii Kuliand68501e2017-01-10 22:57:27 -0800180 /**
181 * This tests stack movement between displays and proper stack's, task's and app token's display
182 * container references updates.
183 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800184 @Test
185 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800186 // Create a second display.
187 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800188
189 // Add stack with activity.
190 final TaskStack stack = createTaskStackOnDisplay(dc);
191 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
192 assertEquals(dc, stack.getParent().getParent());
193 assertEquals(dc, stack.getDisplayContent());
194
195 final Task task = createTaskInStack(stack, 0 /* userId */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700196 final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800197 task.addChild(token, 0);
198 assertEquals(dc, task.getDisplayContent());
199 assertEquals(dc, token.getDisplayContent());
200
201 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700202 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
203 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
204 assertEquals(mDisplayContent, stack.getParent().getParent());
205 assertEquals(mDisplayContent, stack.getDisplayContent());
206 assertEquals(mDisplayContent, task.getDisplayContent());
207 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800208 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800209
210 /**
211 * This tests override configuration updates for display content.
212 */
213 @Test
214 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700215 final int displayId = mDisplayContent.getDisplayId();
216 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800217
218 // Create new, slightly changed override configuration and apply it to the display.
219 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
220 newOverrideConfig.densityDpi += 120;
221 newOverrideConfig.fontScale += 0.3;
222
223 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
224
225 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700226 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800227 }
228
229 /**
230 * This tests global configuration updates when default display config is updated.
231 */
232 @Test
233 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700234 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800235
236 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700237 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800238 newOverrideConfig.densityDpi += 120;
239 newOverrideConfig.fontScale += 0.3;
240
241 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800242
243 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800244 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800245 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
246 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800247
248 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700249 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800250 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700251 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
252 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800253 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800254
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700255 /**
256 * Tests tapping on a stack in different display results in window gaining focus.
257 */
258 @Test
259 public void testInputEventBringsCorrectDisplayInFocus() throws Exception {
260 DisplayContent dc0 = sWm.getDefaultDisplayContentLocked();
261 // Create a second display
262 final DisplayContent dc1 = createNewDisplay();
263
264 // Add stack with activity.
265 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
266 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
267 final WindowTestUtils.TestAppWindowToken token =
268 new WindowTestUtils.TestAppWindowToken(dc0);
269 task0.addChild(token, 0);
270 dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
271 sWm.registerPointerEventListener(dc0.mTapDetector);
272 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
273 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
274 final WindowTestUtils.TestAppWindowToken token1 =
275 new WindowTestUtils.TestAppWindowToken(dc0);
276 task1.addChild(token1, 0);
277 dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
278 sWm.registerPointerEventListener(dc1.mTapDetector);
279
280 // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
281 DisplayMetrics dm0 = dc0.getDisplayMetrics();
282 dc0.mTapDetector.onPointerEvent(
283 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
284 dc0.mTapDetector.onPointerEvent(
285 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
286
287 // Check focus is on primary display.
288 assertEquals(sWm.mCurrentFocus, dc0.findFocusedWindow());
289
290 // Tap on secondary display
291 DisplayMetrics dm1 = dc1.getDisplayMetrics();
292 dc1.mTapDetector.onPointerEvent(
293 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
294 dc1.mTapDetector.onPointerEvent(
295 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
296
297 // Check focus is on secondary.
298 assertEquals(sWm.mCurrentFocus, dc1.findFocusedWindow());
299 }
300
David Stevens46939562017-03-24 13:04:00 -0700301 @Test
Wale Ogunwale42bab782017-05-02 13:16:39 -0700302 @Ignore
David Stevens46939562017-03-24 13:04:00 -0700303 public void testFocusedWindowMultipleDisplays() throws Exception {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700304 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700305 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700306 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700307 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
308
309 // Check that a new display doesn't affect focus
310 final DisplayContent dc = createNewDisplay();
311 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
312
313 // Add a window to the second display, and it should be focused
314 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
315 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
316
317 // Move the first window to the to including parents, and make sure focus is updated
318 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
319 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
320 }
321
Bryce Lee27cec322017-03-21 09:41:37 -0700322 /**
323 * This tests setting the maximum ui width on a display.
324 */
325 @Test
326 public void testMaxUiWidth() throws Exception {
327 final int baseWidth = 1440;
328 final int baseHeight = 2560;
329 final int baseDensity = 300;
330
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700331 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700332
333 final int maxWidth = 300;
334 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
335 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
336
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700337 mDisplayContent.setMaxUiWidth(maxWidth);
338 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700339
340 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700341 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
342 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700343
344 final int smallerWidth = 200;
345 final int smallerHeight = 400;
346 final int smallerDensity = 100;
347
348 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700349 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
350 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700351
352 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700353 mDisplayContent.setMaxUiWidth(maxWidth);
354 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700355 }
356
Bryce Lee48f4b572017-04-10 10:54:15 -0700357 /**
358 * This test enforces that the pinned stack is always kept as the top stack.
359 */
360 @Test
361 public void testPinnedStackLocation() {
Wale Ogunwale61911492017-10-11 08:50:50 -0700362 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
363 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
364 // Ensure that the pinned stack is the top stack
365 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
366 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700367 // By default, this should try to create a new stack on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700368 final TaskStack otherStack = createTaskStackOnDisplay(mDisplayContent);
369 // Ensure that the other stack is on the display.
370 assertEquals(mDisplayContent, otherStack.getDisplayContent());
Bryce Lee48f4b572017-04-10 10:54:15 -0700371 // Ensure that the pinned stack is still on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700372 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700373 }
374
Andrii Kulian0214ed92017-05-16 13:44:05 -0700375 /**
376 * Test that WM does not report displays to AM that are pending to be removed.
377 */
378 @Test
379 public void testDontReportDeferredRemoval() {
380 // Create a display and add an animating window to it.
381 final DisplayContent dc = createNewDisplay();
382 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
383 window.mAnimatingExit = true;
384 // Request display removal, it should be deferred.
385 dc.removeIfPossible();
386 // Request ordered display ids from WM.
387 final SparseIntArray orderedDisplayIds = new SparseIntArray();
388 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
389 // Make sure that display that is marked for removal is not reported.
390 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
391 }
392
Andrii Kulian92c9a942017-10-10 00:41:41 -0700393 @Test
Adrian Roos1cf585052018-01-03 18:43:27 +0100394 public void testDisplayCutout_rot0() throws Exception {
395 synchronized (sWm.getWindowManagerLock()) {
396 final DisplayContent dc = createNewDisplay();
397 dc.mInitialDisplayWidth = 200;
398 dc.mInitialDisplayHeight = 400;
399 final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
400
401 dc.mInitialDisplayCutout = cutout;
402 dc.setRotation(Surface.ROTATION_0);
403 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
404
405 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
406 }
407 }
408
409 @Test
410 public void testDisplayCutout_rot90() throws Exception {
411 synchronized (sWm.getWindowManagerLock()) {
412 final DisplayContent dc = createNewDisplay();
413 dc.mInitialDisplayWidth = 200;
414 dc.mInitialDisplayHeight = 400;
415 final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
416
417 dc.mInitialDisplayCutout = cutout;
418 dc.setRotation(Surface.ROTATION_90);
419 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
420
421 assertEquals(createCutout(new Rect(0, 80, 10, 120)), dc.getDisplayInfo().displayCutout);
422 }
423 }
424
425 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700426 @SuppressLint("InlinedApi")
427 public void testOrientationDefinedByKeyguard() {
428 final DisplayContent dc = createNewDisplay();
429 // Create a window that requests landscape orientation. It will define device orientation
430 // by default.
431 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
432 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
433
434 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
435 keyguard.mHasSurface = true;
436 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
437
438 assertEquals("Screen orientation must be defined by the app window by default",
439 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
440
441 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
442 assertEquals("Visible keyguard must influence device orientation",
443 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
444
445 sWm.setKeyguardGoingAway(true);
446 assertEquals("Keyguard that is going away must not influence device orientation",
447 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
448 }
449
Bryce Lee27cec322017-03-21 09:41:37 -0700450 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
451 int expectedBaseHeight, int expectedBaseDensity) {
452 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
453 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
454 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
455 }
456
Wale Ogunwale34247952017-02-19 11:57:53 -0800457 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
458 final LinkedList<WindowState> actualWindows = new LinkedList();
459
460 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700461 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800462 assertEquals(expectedWindows.size(), actualWindows.size());
463 for (WindowState w : expectedWindows) {
464 assertEquals(w, actualWindows.pollFirst());
465 }
466 assertTrue(actualWindows.isEmpty());
467
468 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700469 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800470 assertEquals(expectedWindows.size(), actualWindows.size());
471 for (WindowState w : expectedWindows) {
472 assertEquals(w, actualWindows.pollLast());
473 }
474 assertTrue(actualWindows.isEmpty());
475 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700476
477 private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
478 final long downTime = SystemClock.uptimeMillis();
479 final long eventTime = SystemClock.uptimeMillis() + 100;
480 final int metaState = 0;
481
482 return MotionEvent.obtain(
483 downTime,
484 eventTime,
485 isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
486 x,
487 y,
488 metaState);
489 }
Adrian Roos1cf585052018-01-03 18:43:27 +0100490
491 private DisplayCutout createCutout(Rect r) {
492 Path p = new Path();
493 p.addRect(r.left, r.top, r.right, r.bottom, Path.Direction.CCW);
494 return DisplayCutout.fromBounds(p);
495 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700496}