blob: 845095ae19b90772453bc17a893b544863986fc0 [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
Adrian Roos5251b1d2018-03-23 18:57:43 +010033import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080034import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070035import static org.junit.Assert.assertFalse;
Adrian Roos5251b1d2018-03-23 18:57:43 +010036import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080037import static org.junit.Assert.assertTrue;
Andrii Kulianf0379de2018-03-14 16:24:07 -070038import static org.mockito.Mockito.times;
39import static org.mockito.Mockito.verify;
Wale Ogunwale34247952017-02-19 11:57:53 -080040
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070041import org.junit.Test;
42import org.junit.runner.RunWith;
43
Andrii Kulian92c9a942017-10-10 00:41:41 -070044import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080045import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010046import android.graphics.Rect;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070047import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070048import android.platform.test.annotations.Presubmit;
Adrian Roos0f9368c2018-04-08 10:59:08 -070049import android.support.test.filters.FlakyTest;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070050import android.support.test.filters.SmallTest;
51import android.support.test.runner.AndroidJUnit4;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070052import android.util.DisplayMetrics;
Andrii Kulian0214ed92017-05-16 13:44:05 -070053import android.util.SparseIntArray;
Adrian Roos1cf585052018-01-03 18:43:27 +010054import android.view.DisplayCutout;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070055import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010056import android.view.Surface;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070057
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010058import com.android.server.wm.utils.WmDisplayCutout;
59
Adrian Roos0f9368c2018-04-08 10:59:08 -070060import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080061import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070062import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080063import java.util.LinkedList;
64import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070065
66/**
67 * Tests for the {@link DisplayContent} class.
68 *
69 * Build/Install/Run:
Adrian Roos1cf585052018-01-03 18:43:27 +010070 * atest com.android.server.wm.DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070071 */
72@SmallTest
73@Presubmit
74@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080075public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070076
77 @Test
Adrian Roos0f9368c2018-04-08 10:59:08 -070078 @FlakyTest(bugId = 77772044)
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070079 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080080 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070081 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070082 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
83 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080084 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070085
Wale Ogunwale34247952017-02-19 11:57:53 -080086 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070087 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080088 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070089 mChildAppWindowBelow,
90 mAppWindow,
91 mChildAppWindowAbove,
92 mDockedDividerWindow,
93 mStatusBarWindow,
94 mNavBarWindow,
95 mImeWindow,
96 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080097 }
98
99 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800100 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800101 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700102 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800103
104 sWm.mInputMethodTarget = imeAppTarget;
105
Wale Ogunwale34247952017-02-19 11:57:53 -0800106 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700107 mWallpaperWindow,
108 mChildAppWindowBelow,
109 mAppWindow,
110 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800111 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700112 mImeWindow,
113 mImeDialogWindow,
114 mDockedDividerWindow,
115 mStatusBarWindow,
116 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800117 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800118
Wale Ogunwale34247952017-02-19 11:57:53 -0800119 @Test
120 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700121 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800122
Wale Ogunwale34247952017-02-19 11:57:53 -0800123 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700124 mWallpaperWindow,
125 mChildAppWindowBelow,
126 mAppWindow,
127 mChildAppWindowAbove,
128 mImeWindow,
129 mImeDialogWindow,
130 mDockedDividerWindow,
131 mStatusBarWindow,
132 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700133 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800134
135 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800136 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700137 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800138
Wale Ogunwale34247952017-02-19 11:57:53 -0800139 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700140 mWallpaperWindow,
141 mChildAppWindowBelow,
142 mAppWindow,
143 mChildAppWindowAbove,
144 mDockedDividerWindow,
145 mStatusBarWindow,
146 mImeWindow,
147 mImeDialogWindow,
148 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800149 }
150
151 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800152 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
153 // This window is set-up to be z-ordered between some windows that go in the same token like
154 // the nav bar and status bar.
155 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700156 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800157
Wale Ogunwale34247952017-02-19 11:57:53 -0800158 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700159 mWallpaperWindow,
160 mChildAppWindowBelow,
161 mAppWindow,
162 mChildAppWindowAbove,
163 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800164 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700165 mStatusBarWindow,
166 mNavBarWindow,
167 mImeWindow,
168 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800169 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800170
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 @Test
172 public void testComputeImeTarget() throws Exception {
173 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700174 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800175 appWin.setHasSurface(true);
176 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700177 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800178 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800179 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800180
Wale Ogunwale34247952017-02-19 11:57:53 -0800181 // Verify that an child window can be an ime target.
182 final WindowState childWin = createWindow(appWin,
183 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
184 childWin.setHasSurface(true);
185 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700186 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800187 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800188 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800189
Andrii Kuliand68501e2017-01-10 22:57:27 -0800190 /**
191 * This tests stack movement between displays and proper stack's, task's and app token's display
192 * container references updates.
193 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800194 @Test
195 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800196 // Create a second display.
197 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800198
199 // Add stack with activity.
200 final TaskStack stack = createTaskStackOnDisplay(dc);
201 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
202 assertEquals(dc, stack.getParent().getParent());
203 assertEquals(dc, stack.getDisplayContent());
204
205 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800206 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
207 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800208 task.addChild(token, 0);
209 assertEquals(dc, task.getDisplayContent());
210 assertEquals(dc, token.getDisplayContent());
211
212 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700213 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
214 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
215 assertEquals(mDisplayContent, stack.getParent().getParent());
216 assertEquals(mDisplayContent, stack.getDisplayContent());
217 assertEquals(mDisplayContent, task.getDisplayContent());
218 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800219 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800220
221 /**
222 * This tests override configuration updates for display content.
223 */
224 @Test
225 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700226 final int displayId = mDisplayContent.getDisplayId();
227 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800228
229 // Create new, slightly changed override configuration and apply it to the display.
230 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
231 newOverrideConfig.densityDpi += 120;
232 newOverrideConfig.fontScale += 0.3;
233
234 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
235
236 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700237 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800238 }
239
240 /**
241 * This tests global configuration updates when default display config is updated.
242 */
243 @Test
244 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700245 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800246
247 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700248 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800249 newOverrideConfig.densityDpi += 120;
250 newOverrideConfig.fontScale += 0.3;
251
252 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800253
254 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800255 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800256 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
257 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800258
259 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700260 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800261 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700262 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
263 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800264 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800265
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700266 /**
267 * Tests tapping on a stack in different display results in window gaining focus.
268 */
269 @Test
270 public void testInputEventBringsCorrectDisplayInFocus() throws Exception {
271 DisplayContent dc0 = sWm.getDefaultDisplayContentLocked();
272 // Create a second display
273 final DisplayContent dc1 = createNewDisplay();
274
275 // Add stack with activity.
276 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
277 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
278 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800279 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700280 task0.addChild(token, 0);
281 dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
282 sWm.registerPointerEventListener(dc0.mTapDetector);
283 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
284 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
285 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800286 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700287 task1.addChild(token1, 0);
288 dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
289 sWm.registerPointerEventListener(dc1.mTapDetector);
290
291 // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
292 DisplayMetrics dm0 = dc0.getDisplayMetrics();
293 dc0.mTapDetector.onPointerEvent(
294 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
295 dc0.mTapDetector.onPointerEvent(
296 createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
297
298 // Check focus is on primary display.
299 assertEquals(sWm.mCurrentFocus, dc0.findFocusedWindow());
300
301 // Tap on secondary display
302 DisplayMetrics dm1 = dc1.getDisplayMetrics();
303 dc1.mTapDetector.onPointerEvent(
304 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
305 dc1.mTapDetector.onPointerEvent(
306 createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
307
308 // Check focus is on secondary.
309 assertEquals(sWm.mCurrentFocus, dc1.findFocusedWindow());
310 }
311
David Stevens46939562017-03-24 13:04:00 -0700312 @Test
313 public void testFocusedWindowMultipleDisplays() throws Exception {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700314 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700315 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700316 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700317 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
318
319 // Check that a new display doesn't affect focus
320 final DisplayContent dc = createNewDisplay();
321 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
322
323 // Add a window to the second display, and it should be focused
324 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
325 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
326
327 // Move the first window to the to including parents, and make sure focus is updated
328 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
329 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
330 }
331
Bryce Lee27cec322017-03-21 09:41:37 -0700332 /**
333 * This tests setting the maximum ui width on a display.
334 */
335 @Test
336 public void testMaxUiWidth() throws Exception {
337 final int baseWidth = 1440;
338 final int baseHeight = 2560;
339 final int baseDensity = 300;
340
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700341 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700342
343 final int maxWidth = 300;
344 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
345 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
346
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700347 mDisplayContent.setMaxUiWidth(maxWidth);
348 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700349
350 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700351 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
352 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700353
354 final int smallerWidth = 200;
355 final int smallerHeight = 400;
356 final int smallerDensity = 100;
357
358 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700359 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
360 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700361
362 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700363 mDisplayContent.setMaxUiWidth(maxWidth);
364 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700365 }
366
Bryce Lee48f4b572017-04-10 10:54:15 -0700367 /**
368 * This test enforces that the pinned stack is always kept as the top stack.
369 */
370 @Test
371 public void testPinnedStackLocation() {
Wale Ogunwale61911492017-10-11 08:50:50 -0700372 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
373 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
374 // Ensure that the pinned stack is the top stack
375 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
376 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700377 // By default, this should try to create a new stack on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700378 final TaskStack otherStack = createTaskStackOnDisplay(mDisplayContent);
379 // Ensure that the other stack is on the display.
380 assertEquals(mDisplayContent, otherStack.getDisplayContent());
Bryce Lee48f4b572017-04-10 10:54:15 -0700381 // Ensure that the pinned stack is still on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700382 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700383 }
384
Andrii Kulian0214ed92017-05-16 13:44:05 -0700385 /**
386 * Test that WM does not report displays to AM that are pending to be removed.
387 */
388 @Test
389 public void testDontReportDeferredRemoval() {
390 // Create a display and add an animating window to it.
391 final DisplayContent dc = createNewDisplay();
392 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
393 window.mAnimatingExit = true;
394 // Request display removal, it should be deferred.
395 dc.removeIfPossible();
396 // Request ordered display ids from WM.
397 final SparseIntArray orderedDisplayIds = new SparseIntArray();
398 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
399 // Make sure that display that is marked for removal is not reported.
400 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
401 }
402
Andrii Kulian92c9a942017-10-10 00:41:41 -0700403 @Test
Adrian Roos1cf585052018-01-03 18:43:27 +0100404 public void testDisplayCutout_rot0() throws Exception {
405 synchronized (sWm.getWindowManagerLock()) {
406 final DisplayContent dc = createNewDisplay();
407 dc.mInitialDisplayWidth = 200;
408 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100409 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100410 final DisplayCutout cutout = new WmDisplayCutout(
411 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
412 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100413
414 dc.mInitialDisplayCutout = cutout;
415 dc.setRotation(Surface.ROTATION_0);
416 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
417
418 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
419 }
420 }
421
422 @Test
423 public void testDisplayCutout_rot90() throws Exception {
424 synchronized (sWm.getWindowManagerLock()) {
425 final DisplayContent dc = createNewDisplay();
426 dc.mInitialDisplayWidth = 200;
427 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100428 Rect r1 = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100429 final DisplayCutout cutout = new WmDisplayCutout(
430 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
431 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100432
433 dc.mInitialDisplayCutout = cutout;
434 dc.setRotation(Surface.ROTATION_90);
435 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
436
Adrian Roos24264212018-02-19 16:26:15 +0100437 final Rect r = new Rect(0, 80, 10, 120);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100438 assertEquals(new WmDisplayCutout(
439 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
440 .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100441 }
442 }
443
444 @Test
Adrian Roos5251b1d2018-03-23 18:57:43 +0100445 public void testLayoutSeq_assignedDuringLayout() throws Exception {
446 synchronized (sWm.getWindowManagerLock()) {
447
448 final DisplayContent dc = createNewDisplay();
449 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
450
451 dc.setLayoutNeeded();
452 dc.performLayout(true /* initial */, false /* updateImeWindows */);
453
454 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
455 }
456 }
457
458 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700459 @SuppressLint("InlinedApi")
460 public void testOrientationDefinedByKeyguard() {
461 final DisplayContent dc = createNewDisplay();
462 // Create a window that requests landscape orientation. It will define device orientation
463 // by default.
464 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
465 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
466
467 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
468 keyguard.mHasSurface = true;
469 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
470
471 assertEquals("Screen orientation must be defined by the app window by default",
472 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
473
474 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
475 assertEquals("Visible keyguard must influence device orientation",
476 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
477
478 sWm.setKeyguardGoingAway(true);
479 assertEquals("Keyguard that is going away must not influence device orientation",
480 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
481 }
482
Andrii Kulianf0379de2018-03-14 16:24:07 -0700483 @Test
484 public void testDisableDisplayInfoOverrideFromWindowManager() {
485 final DisplayContent dc = createNewDisplay();
486
487 assertTrue(dc.mShouldOverrideDisplayConfiguration);
488 sWm.dontOverrideDisplayInfo(dc.getDisplayId());
489
490 assertFalse(dc.mShouldOverrideDisplayConfiguration);
491 verify(sWm.mDisplayManagerInternal, times(1))
492 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
493 }
494
Bryce Lee27cec322017-03-21 09:41:37 -0700495 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
496 int expectedBaseHeight, int expectedBaseDensity) {
497 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
498 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
499 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
500 }
501
Adrian Roos0f9368c2018-04-08 10:59:08 -0700502 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
503 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800504
505 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700506 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700507 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
508
509 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800510
511 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700512 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700513 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
514 }
515
516 private static List<WindowState> reverseList(List<WindowState> list) {
517 final ArrayList<WindowState> result = new ArrayList<>(list);
518 Collections.reverse(result);
519 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800520 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700521
522 private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
523 final long downTime = SystemClock.uptimeMillis();
524 final long eventTime = SystemClock.uptimeMillis() + 100;
525 final int metaState = 0;
526
527 return MotionEvent.obtain(
528 downTime,
529 eventTime,
530 isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
531 x,
532 y,
533 metaState);
534 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700535}