blob: b645700abb794961342b03a351b5e216cff9d14f [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;
Andrii Kulianf0379de2018-03-14 16:24:07 -070034import static org.junit.Assert.assertFalse;
Wale Ogunwale34247952017-02-19 11:57:53 -080035import static org.junit.Assert.assertTrue;
Andrii Kulianf0379de2018-03-14 16:24:07 -070036import static org.mockito.Mockito.times;
37import static org.mockito.Mockito.verify;
Wale Ogunwale34247952017-02-19 11:57:53 -080038
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070039import org.junit.Test;
40import org.junit.runner.RunWith;
41
Andrii Kulian92c9a942017-10-10 00:41:41 -070042import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080043import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010044import android.graphics.Rect;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070045import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070046import android.platform.test.annotations.Presubmit;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070047import android.support.test.filters.SmallTest;
48import android.support.test.runner.AndroidJUnit4;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070049import android.util.DisplayMetrics;
Andrii Kulian0214ed92017-05-16 13:44:05 -070050import android.util.SparseIntArray;
Adrian Roos1cf585052018-01-03 18:43:27 +010051import android.view.DisplayCutout;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070052import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010053import android.view.Surface;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070054
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010055import com.android.server.wm.utils.WmDisplayCutout;
56
Wale Ogunwale34247952017-02-19 11:57:53 -080057import java.util.Arrays;
58import java.util.LinkedList;
59import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070060
61/**
62 * Tests for the {@link DisplayContent} class.
63 *
64 * Build/Install/Run:
Adrian Roos1cf585052018-01-03 18:43:27 +010065 * atest com.android.server.wm.DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070066 */
67@SmallTest
68@Presubmit
69@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080070public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070071
72 @Test
73 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080074 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070075 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070076 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
77 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080078 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070079
Wale Ogunwale34247952017-02-19 11:57:53 -080080 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070081 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080082 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070083 mChildAppWindowBelow,
84 mAppWindow,
85 mChildAppWindowAbove,
86 mDockedDividerWindow,
87 mStatusBarWindow,
88 mNavBarWindow,
89 mImeWindow,
90 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080091 }
92
93 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080094 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080095 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -070096 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080097
98 sWm.mInputMethodTarget = imeAppTarget;
99
Wale Ogunwale34247952017-02-19 11:57:53 -0800100 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700101 mWallpaperWindow,
102 mChildAppWindowBelow,
103 mAppWindow,
104 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800105 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700106 mImeWindow,
107 mImeDialogWindow,
108 mDockedDividerWindow,
109 mStatusBarWindow,
110 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800111 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800112
Wale Ogunwale34247952017-02-19 11:57:53 -0800113 @Test
114 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700115 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800116
Wale Ogunwale34247952017-02-19 11:57:53 -0800117 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700118 mWallpaperWindow,
119 mChildAppWindowBelow,
120 mAppWindow,
121 mChildAppWindowAbove,
122 mImeWindow,
123 mImeDialogWindow,
124 mDockedDividerWindow,
125 mStatusBarWindow,
126 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700127 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800128
129 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800130 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700131 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800132
Wale Ogunwale34247952017-02-19 11:57:53 -0800133 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700134 mWallpaperWindow,
135 mChildAppWindowBelow,
136 mAppWindow,
137 mChildAppWindowAbove,
138 mDockedDividerWindow,
139 mStatusBarWindow,
140 mImeWindow,
141 mImeDialogWindow,
142 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800143 }
144
145 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800146 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
147 // This window is set-up to be z-ordered between some windows that go in the same token like
148 // the nav bar and status bar.
149 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700150 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800151
Wale Ogunwale34247952017-02-19 11:57:53 -0800152 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 mWallpaperWindow,
154 mChildAppWindowBelow,
155 mAppWindow,
156 mChildAppWindowAbove,
157 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800158 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700159 mStatusBarWindow,
160 mNavBarWindow,
161 mImeWindow,
162 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800163 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800164
Wale Ogunwale34247952017-02-19 11:57:53 -0800165 @Test
166 public void testComputeImeTarget() throws Exception {
167 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700168 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800169 appWin.setHasSurface(true);
170 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700171 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800172 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800173 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800174
Wale Ogunwale34247952017-02-19 11:57:53 -0800175 // Verify that an child window can be an ime target.
176 final WindowState childWin = createWindow(appWin,
177 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
178 childWin.setHasSurface(true);
179 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700180 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800181 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800182 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800183
Andrii Kuliand68501e2017-01-10 22:57:27 -0800184 /**
185 * This tests stack movement between displays and proper stack's, task's and app token's display
186 * container references updates.
187 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800188 @Test
189 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800190 // Create a second display.
191 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800192
193 // Add stack with activity.
194 final TaskStack stack = createTaskStackOnDisplay(dc);
195 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
196 assertEquals(dc, stack.getParent().getParent());
197 assertEquals(dc, stack.getDisplayContent());
198
199 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800200 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
201 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800202 task.addChild(token, 0);
203 assertEquals(dc, task.getDisplayContent());
204 assertEquals(dc, token.getDisplayContent());
205
206 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700207 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
208 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
209 assertEquals(mDisplayContent, stack.getParent().getParent());
210 assertEquals(mDisplayContent, stack.getDisplayContent());
211 assertEquals(mDisplayContent, task.getDisplayContent());
212 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800213 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800214
215 /**
216 * This tests override configuration updates for display content.
217 */
218 @Test
219 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700220 final int displayId = mDisplayContent.getDisplayId();
221 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800222
223 // Create new, slightly changed override configuration and apply it to the display.
224 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
225 newOverrideConfig.densityDpi += 120;
226 newOverrideConfig.fontScale += 0.3;
227
228 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
229
230 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700231 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800232 }
233
234 /**
235 * This tests global configuration updates when default display config is updated.
236 */
237 @Test
238 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700239 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800240
241 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700242 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800243 newOverrideConfig.densityDpi += 120;
244 newOverrideConfig.fontScale += 0.3;
245
246 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800247
248 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800249 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800250 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
251 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800252
253 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700254 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800255 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700256 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
257 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800258 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800259
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700260 /**
261 * Tests tapping on a stack in different display results in window gaining focus.
262 */
263 @Test
264 public void testInputEventBringsCorrectDisplayInFocus() throws Exception {
265 DisplayContent dc0 = sWm.getDefaultDisplayContentLocked();
266 // Create a second display
267 final DisplayContent dc1 = createNewDisplay();
268
269 // Add stack with activity.
270 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
271 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
272 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800273 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700274 task0.addChild(token, 0);
275 dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
276 sWm.registerPointerEventListener(dc0.mTapDetector);
277 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
278 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
279 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800280 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700281 task1.addChild(token1, 0);
282 dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
283 sWm.registerPointerEventListener(dc1.mTapDetector);
284
285 // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
286 DisplayMetrics dm0 = dc0.getDisplayMetrics();
287 dc0.mTapDetector.onPointerEvent(
288 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
289 dc0.mTapDetector.onPointerEvent(
290 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
291
292 // Check focus is on primary display.
293 assertEquals(sWm.mCurrentFocus, dc0.findFocusedWindow());
294
295 // Tap on secondary display
296 DisplayMetrics dm1 = dc1.getDisplayMetrics();
297 dc1.mTapDetector.onPointerEvent(
298 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
299 dc1.mTapDetector.onPointerEvent(
300 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
301
302 // Check focus is on secondary.
303 assertEquals(sWm.mCurrentFocus, dc1.findFocusedWindow());
304 }
305
David Stevens46939562017-03-24 13:04:00 -0700306 @Test
307 public void testFocusedWindowMultipleDisplays() throws Exception {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700308 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700309 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700310 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700311 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
312
313 // Check that a new display doesn't affect focus
314 final DisplayContent dc = createNewDisplay();
315 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
316
317 // Add a window to the second display, and it should be focused
318 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
319 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
320
321 // Move the first window to the to including parents, and make sure focus is updated
322 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
323 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
324 }
325
Bryce Lee27cec322017-03-21 09:41:37 -0700326 /**
327 * This tests setting the maximum ui width on a display.
328 */
329 @Test
330 public void testMaxUiWidth() throws Exception {
331 final int baseWidth = 1440;
332 final int baseHeight = 2560;
333 final int baseDensity = 300;
334
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700335 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700336
337 final int maxWidth = 300;
338 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
339 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
340
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700341 mDisplayContent.setMaxUiWidth(maxWidth);
342 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700343
344 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700345 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
346 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700347
348 final int smallerWidth = 200;
349 final int smallerHeight = 400;
350 final int smallerDensity = 100;
351
352 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700353 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
354 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700355
356 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700357 mDisplayContent.setMaxUiWidth(maxWidth);
358 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700359 }
360
Bryce Lee48f4b572017-04-10 10:54:15 -0700361 /**
362 * This test enforces that the pinned stack is always kept as the top stack.
363 */
364 @Test
365 public void testPinnedStackLocation() {
Wale Ogunwale61911492017-10-11 08:50:50 -0700366 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
367 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
368 // Ensure that the pinned stack is the top stack
369 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
370 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700371 // By default, this should try to create a new stack on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700372 final TaskStack otherStack = createTaskStackOnDisplay(mDisplayContent);
373 // Ensure that the other stack is on the display.
374 assertEquals(mDisplayContent, otherStack.getDisplayContent());
Bryce Lee48f4b572017-04-10 10:54:15 -0700375 // Ensure that the pinned stack is still on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700376 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700377 }
378
Andrii Kulian0214ed92017-05-16 13:44:05 -0700379 /**
380 * Test that WM does not report displays to AM that are pending to be removed.
381 */
382 @Test
383 public void testDontReportDeferredRemoval() {
384 // Create a display and add an animating window to it.
385 final DisplayContent dc = createNewDisplay();
386 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
387 window.mAnimatingExit = true;
388 // Request display removal, it should be deferred.
389 dc.removeIfPossible();
390 // Request ordered display ids from WM.
391 final SparseIntArray orderedDisplayIds = new SparseIntArray();
392 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
393 // Make sure that display that is marked for removal is not reported.
394 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
395 }
396
Andrii Kulian92c9a942017-10-10 00:41:41 -0700397 @Test
Adrian Roos1cf585052018-01-03 18:43:27 +0100398 public void testDisplayCutout_rot0() throws Exception {
399 synchronized (sWm.getWindowManagerLock()) {
400 final DisplayContent dc = createNewDisplay();
401 dc.mInitialDisplayWidth = 200;
402 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100403 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100404 final DisplayCutout cutout = new WmDisplayCutout(
405 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
406 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100407
408 dc.mInitialDisplayCutout = cutout;
409 dc.setRotation(Surface.ROTATION_0);
410 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
411
412 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
413 }
414 }
415
416 @Test
417 public void testDisplayCutout_rot90() throws Exception {
418 synchronized (sWm.getWindowManagerLock()) {
419 final DisplayContent dc = createNewDisplay();
420 dc.mInitialDisplayWidth = 200;
421 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100422 Rect r1 = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100423 final DisplayCutout cutout = new WmDisplayCutout(
424 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
425 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100426
427 dc.mInitialDisplayCutout = cutout;
428 dc.setRotation(Surface.ROTATION_90);
429 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
430
Adrian Roos24264212018-02-19 16:26:15 +0100431 final Rect r = new Rect(0, 80, 10, 120);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100432 assertEquals(new WmDisplayCutout(
433 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
434 .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100435 }
436 }
437
438 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700439 @SuppressLint("InlinedApi")
440 public void testOrientationDefinedByKeyguard() {
441 final DisplayContent dc = createNewDisplay();
442 // Create a window that requests landscape orientation. It will define device orientation
443 // by default.
444 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
445 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
446
447 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
448 keyguard.mHasSurface = true;
449 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
450
451 assertEquals("Screen orientation must be defined by the app window by default",
452 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
453
454 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
455 assertEquals("Visible keyguard must influence device orientation",
456 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
457
458 sWm.setKeyguardGoingAway(true);
459 assertEquals("Keyguard that is going away must not influence device orientation",
460 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
461 }
462
Andrii Kulianf0379de2018-03-14 16:24:07 -0700463 @Test
464 public void testDisableDisplayInfoOverrideFromWindowManager() {
465 final DisplayContent dc = createNewDisplay();
466
467 assertTrue(dc.mShouldOverrideDisplayConfiguration);
468 sWm.dontOverrideDisplayInfo(dc.getDisplayId());
469
470 assertFalse(dc.mShouldOverrideDisplayConfiguration);
471 verify(sWm.mDisplayManagerInternal, times(1))
472 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
473 }
474
Bryce Lee27cec322017-03-21 09:41:37 -0700475 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
476 int expectedBaseHeight, int expectedBaseDensity) {
477 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
478 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
479 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
480 }
481
Wale Ogunwale34247952017-02-19 11:57:53 -0800482 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
483 final LinkedList<WindowState> actualWindows = new LinkedList();
484
485 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700486 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800487 assertEquals(expectedWindows.size(), actualWindows.size());
488 for (WindowState w : expectedWindows) {
489 assertEquals(w, actualWindows.pollFirst());
490 }
491 assertTrue(actualWindows.isEmpty());
492
493 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700494 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800495 assertEquals(expectedWindows.size(), actualWindows.size());
496 for (WindowState w : expectedWindows) {
497 assertEquals(w, actualWindows.pollLast());
498 }
499 assertTrue(actualWindows.isEmpty());
500 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700501
502 private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
503 final long downTime = SystemClock.uptimeMillis();
504 final long eventTime = SystemClock.uptimeMillis() + 100;
505 final int metaState = 0;
506
507 return MotionEvent.obtain(
508 downTime,
509 eventTime,
510 isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
511 x,
512 y,
513 metaState);
514 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700515}