blob: ccde049b99caa3029598b913aeefc703a350829f [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;
Adrian Roos24264212018-02-19 16:26:15 +010025import static android.view.DisplayCutout.fromBoundingRect;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
27import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
28import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070029import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080030import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
David Stevens46939562017-03-24 13:04:00 -070031import static com.android.server.wm.WindowContainer.POSITION_TOP;
chaviwebcbc342018-02-07 13:19:00 -080032
Wale Ogunwale34247952017-02-19 11:57:53 -080033import static org.junit.Assert.assertEquals;
34import static org.junit.Assert.assertTrue;
35
Wale Ogunwalef89f3212018-03-08 17:01:08 -080036import android.support.test.filters.FlakyTest;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070037import org.junit.Test;
38import org.junit.runner.RunWith;
39
Andrii Kulian92c9a942017-10-10 00:41:41 -070040import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080041import android.content.res.Configuration;
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
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010053import com.android.server.wm.utils.WmDisplayCutout;
54
Wale Ogunwale34247952017-02-19 11:57:53 -080055import java.util.Arrays;
56import java.util.LinkedList;
57import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070058
59/**
60 * Tests for the {@link DisplayContent} class.
61 *
62 * Build/Install/Run:
Adrian Roos1cf585052018-01-03 18:43:27 +010063 * atest com.android.server.wm.DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070064 */
65@SmallTest
66@Presubmit
67@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080068public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070069
70 @Test
71 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080072 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070073 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070074 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
75 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080076 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070077
Wale Ogunwale34247952017-02-19 11:57:53 -080078 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070079 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080080 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070081 mChildAppWindowBelow,
82 mAppWindow,
83 mChildAppWindowAbove,
84 mDockedDividerWindow,
85 mStatusBarWindow,
86 mNavBarWindow,
87 mImeWindow,
88 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080089 }
90
91 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080092 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080093 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -070094 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080095
96 sWm.mInputMethodTarget = imeAppTarget;
97
Wale Ogunwale34247952017-02-19 11:57:53 -080098 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070099 mWallpaperWindow,
100 mChildAppWindowBelow,
101 mAppWindow,
102 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800103 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700104 mImeWindow,
105 mImeDialogWindow,
106 mDockedDividerWindow,
107 mStatusBarWindow,
108 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800109 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800110
Wale Ogunwale34247952017-02-19 11:57:53 -0800111 @Test
112 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700113 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800114
Wale Ogunwale34247952017-02-19 11:57:53 -0800115 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700116 mWallpaperWindow,
117 mChildAppWindowBelow,
118 mAppWindow,
119 mChildAppWindowAbove,
120 mImeWindow,
121 mImeDialogWindow,
122 mDockedDividerWindow,
123 mStatusBarWindow,
124 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700125 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800126
127 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800128 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700129 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800130
Wale Ogunwale34247952017-02-19 11:57:53 -0800131 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700132 mWallpaperWindow,
133 mChildAppWindowBelow,
134 mAppWindow,
135 mChildAppWindowAbove,
136 mDockedDividerWindow,
137 mStatusBarWindow,
138 mImeWindow,
139 mImeDialogWindow,
140 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800141 }
142
143 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800144 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
145 // This window is set-up to be z-ordered between some windows that go in the same token like
146 // the nav bar and status bar.
147 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700148 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800149
Wale Ogunwale34247952017-02-19 11:57:53 -0800150 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700151 mWallpaperWindow,
152 mChildAppWindowBelow,
153 mAppWindow,
154 mChildAppWindowAbove,
155 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800156 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700157 mStatusBarWindow,
158 mNavBarWindow,
159 mImeWindow,
160 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800161 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800162
Wale Ogunwale34247952017-02-19 11:57:53 -0800163 @Test
164 public void testComputeImeTarget() throws Exception {
165 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700166 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800167 appWin.setHasSurface(true);
168 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700169 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800170 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800171 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800172
Wale Ogunwale34247952017-02-19 11:57:53 -0800173 // Verify that an child window can be an ime target.
174 final WindowState childWin = createWindow(appWin,
175 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
176 childWin.setHasSurface(true);
177 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700178 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800179 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800180 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800181
Andrii Kuliand68501e2017-01-10 22:57:27 -0800182 /**
183 * This tests stack movement between displays and proper stack's, task's and app token's display
184 * container references updates.
185 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800186 @Test
187 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800188 // Create a second display.
189 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800190
191 // Add stack with activity.
192 final TaskStack stack = createTaskStackOnDisplay(dc);
193 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
194 assertEquals(dc, stack.getParent().getParent());
195 assertEquals(dc, stack.getDisplayContent());
196
197 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800198 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
199 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800200 task.addChild(token, 0);
201 assertEquals(dc, task.getDisplayContent());
202 assertEquals(dc, token.getDisplayContent());
203
204 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700205 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
206 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
207 assertEquals(mDisplayContent, stack.getParent().getParent());
208 assertEquals(mDisplayContent, stack.getDisplayContent());
209 assertEquals(mDisplayContent, task.getDisplayContent());
210 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800211 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800212
213 /**
214 * This tests override configuration updates for display content.
215 */
216 @Test
217 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700218 final int displayId = mDisplayContent.getDisplayId();
219 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800220
221 // Create new, slightly changed override configuration and apply it to the display.
222 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
223 newOverrideConfig.densityDpi += 120;
224 newOverrideConfig.fontScale += 0.3;
225
226 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
227
228 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700229 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800230 }
231
232 /**
233 * This tests global configuration updates when default display config is updated.
234 */
235 @Test
236 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700237 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800238
239 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700240 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800241 newOverrideConfig.densityDpi += 120;
242 newOverrideConfig.fontScale += 0.3;
243
244 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800245
246 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800247 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800248 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
249 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800250
251 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700252 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800253 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700254 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
255 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800256 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800257
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700258 /**
259 * Tests tapping on a stack in different display results in window gaining focus.
260 */
261 @Test
262 public void testInputEventBringsCorrectDisplayInFocus() throws Exception {
263 DisplayContent dc0 = sWm.getDefaultDisplayContentLocked();
264 // Create a second display
265 final DisplayContent dc1 = createNewDisplay();
266
267 // Add stack with activity.
268 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
269 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
270 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800271 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700272 task0.addChild(token, 0);
273 dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
274 sWm.registerPointerEventListener(dc0.mTapDetector);
275 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
276 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
277 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800278 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700279 task1.addChild(token1, 0);
280 dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
281 sWm.registerPointerEventListener(dc1.mTapDetector);
282
283 // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
284 DisplayMetrics dm0 = dc0.getDisplayMetrics();
285 dc0.mTapDetector.onPointerEvent(
286 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
287 dc0.mTapDetector.onPointerEvent(
288 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
289
290 // Check focus is on primary display.
291 assertEquals(sWm.mCurrentFocus, dc0.findFocusedWindow());
292
293 // Tap on secondary display
294 DisplayMetrics dm1 = dc1.getDisplayMetrics();
295 dc1.mTapDetector.onPointerEvent(
296 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
297 dc1.mTapDetector.onPointerEvent(
298 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
299
300 // Check focus is on secondary.
301 assertEquals(sWm.mCurrentFocus, dc1.findFocusedWindow());
302 }
303
David Stevens46939562017-03-24 13:04:00 -0700304 @Test
Wale Ogunwalef89f3212018-03-08 17:01:08 -0800305 @FlakyTest(bugId = 37908381)
David Stevens46939562017-03-24 13:04:00 -0700306 public void testFocusedWindowMultipleDisplays() throws Exception {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700307 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700308 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700309 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700310 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
311
312 // Check that a new display doesn't affect focus
313 final DisplayContent dc = createNewDisplay();
314 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
315
316 // Add a window to the second display, and it should be focused
317 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
318 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
319
320 // Move the first window to the to including parents, and make sure focus is updated
321 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
322 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
323 }
324
Bryce Lee27cec322017-03-21 09:41:37 -0700325 /**
326 * This tests setting the maximum ui width on a display.
327 */
328 @Test
329 public void testMaxUiWidth() throws Exception {
330 final int baseWidth = 1440;
331 final int baseHeight = 2560;
332 final int baseDensity = 300;
333
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700334 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700335
336 final int maxWidth = 300;
337 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
338 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
339
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700340 mDisplayContent.setMaxUiWidth(maxWidth);
341 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700342
343 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700344 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
345 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700346
347 final int smallerWidth = 200;
348 final int smallerHeight = 400;
349 final int smallerDensity = 100;
350
351 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700352 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
353 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700354
355 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700356 mDisplayContent.setMaxUiWidth(maxWidth);
357 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700358 }
359
Bryce Lee48f4b572017-04-10 10:54:15 -0700360 /**
361 * This test enforces that the pinned stack is always kept as the top stack.
362 */
363 @Test
364 public void testPinnedStackLocation() {
Wale Ogunwale61911492017-10-11 08:50:50 -0700365 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
366 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
367 // Ensure that the pinned stack is the top stack
368 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
369 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700370 // By default, this should try to create a new stack on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700371 final TaskStack otherStack = createTaskStackOnDisplay(mDisplayContent);
372 // Ensure that the other stack is on the display.
373 assertEquals(mDisplayContent, otherStack.getDisplayContent());
Bryce Lee48f4b572017-04-10 10:54:15 -0700374 // Ensure that the pinned stack is still on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700375 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700376 }
377
Andrii Kulian0214ed92017-05-16 13:44:05 -0700378 /**
379 * Test that WM does not report displays to AM that are pending to be removed.
380 */
381 @Test
382 public void testDontReportDeferredRemoval() {
383 // Create a display and add an animating window to it.
384 final DisplayContent dc = createNewDisplay();
385 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
386 window.mAnimatingExit = true;
387 // Request display removal, it should be deferred.
388 dc.removeIfPossible();
389 // Request ordered display ids from WM.
390 final SparseIntArray orderedDisplayIds = new SparseIntArray();
391 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
392 // Make sure that display that is marked for removal is not reported.
393 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
394 }
395
Andrii Kulian92c9a942017-10-10 00:41:41 -0700396 @Test
Adrian Roos1cf585052018-01-03 18:43:27 +0100397 public void testDisplayCutout_rot0() throws Exception {
398 synchronized (sWm.getWindowManagerLock()) {
399 final DisplayContent dc = createNewDisplay();
400 dc.mInitialDisplayWidth = 200;
401 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100402 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100403 final DisplayCutout cutout = new WmDisplayCutout(
404 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
405 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100406
407 dc.mInitialDisplayCutout = cutout;
408 dc.setRotation(Surface.ROTATION_0);
409 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
410
411 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
412 }
413 }
414
415 @Test
416 public void testDisplayCutout_rot90() throws Exception {
417 synchronized (sWm.getWindowManagerLock()) {
418 final DisplayContent dc = createNewDisplay();
419 dc.mInitialDisplayWidth = 200;
420 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100421 Rect r1 = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100422 final DisplayCutout cutout = new WmDisplayCutout(
423 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
424 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100425
426 dc.mInitialDisplayCutout = cutout;
427 dc.setRotation(Surface.ROTATION_90);
428 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
429
Adrian Roos24264212018-02-19 16:26:15 +0100430 final Rect r = new Rect(0, 80, 10, 120);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100431 assertEquals(new WmDisplayCutout(
432 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
433 .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100434 }
435 }
436
437 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700438 @SuppressLint("InlinedApi")
439 public void testOrientationDefinedByKeyguard() {
440 final DisplayContent dc = createNewDisplay();
441 // Create a window that requests landscape orientation. It will define device orientation
442 // by default.
443 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
444 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
445
446 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
447 keyguard.mHasSurface = true;
448 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
449
450 assertEquals("Screen orientation must be defined by the app window by default",
451 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
452
453 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
454 assertEquals("Visible keyguard must influence device orientation",
455 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
456
457 sWm.setKeyguardGoingAway(true);
458 assertEquals("Keyguard that is going away must not influence device orientation",
459 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
460 }
461
Bryce Lee27cec322017-03-21 09:41:37 -0700462 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
463 int expectedBaseHeight, int expectedBaseDensity) {
464 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
465 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
466 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
467 }
468
Wale Ogunwale34247952017-02-19 11:57:53 -0800469 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
470 final LinkedList<WindowState> actualWindows = new LinkedList();
471
472 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700473 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800474 assertEquals(expectedWindows.size(), actualWindows.size());
475 for (WindowState w : expectedWindows) {
476 assertEquals(w, actualWindows.pollFirst());
477 }
478 assertTrue(actualWindows.isEmpty());
479
480 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700481 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800482 assertEquals(expectedWindows.size(), actualWindows.size());
483 for (WindowState w : expectedWindows) {
484 assertEquals(w, actualWindows.pollLast());
485 }
486 assertTrue(actualWindows.isEmpty());
487 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700488
489 private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
490 final long downTime = SystemClock.uptimeMillis();
491 final long eventTime = SystemClock.uptimeMillis() + 100;
492 final int metaState = 0;
493
494 return MotionEvent.obtain(
495 downTime,
496 eventTime,
497 isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
498 x,
499 y,
500 metaState);
501 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700502}