blob: ac196f9c80dcff7c21effb0811bdc208e520eaf2 [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
Adrian Roos4163d622018-05-22 16:56:35 +0200332 @Test
333 public void testKeyguard_preventsSecondaryDisplayFocus() throws Exception {
334 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR,
335 sWm.getDefaultDisplayContentLocked(), "keyguard");
336 assertEquals(keyguard, sWm.mRoot.computeFocusedWindow());
337
338 // Add a window to a second display, and it should be focused
339 final DisplayContent dc = createNewDisplay();
340 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
341 assertEquals(win, sWm.mRoot.computeFocusedWindow());
342
343 mWmRule.getWindowManagerPolicy().keyguardShowingAndNotOccluded = true;
344 assertEquals(keyguard, sWm.mRoot.computeFocusedWindow());
345 }
346
Bryce Lee27cec322017-03-21 09:41:37 -0700347 /**
348 * This tests setting the maximum ui width on a display.
349 */
350 @Test
351 public void testMaxUiWidth() throws Exception {
352 final int baseWidth = 1440;
353 final int baseHeight = 2560;
354 final int baseDensity = 300;
355
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700356 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700357
358 final int maxWidth = 300;
359 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
360 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
361
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700362 mDisplayContent.setMaxUiWidth(maxWidth);
363 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700364
365 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700366 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
367 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700368
369 final int smallerWidth = 200;
370 final int smallerHeight = 400;
371 final int smallerDensity = 100;
372
373 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700374 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
375 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700376
377 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700378 mDisplayContent.setMaxUiWidth(maxWidth);
379 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700380 }
381
Bryce Lee48f4b572017-04-10 10:54:15 -0700382 /**
383 * This test enforces that the pinned stack is always kept as the top stack.
384 */
385 @Test
386 public void testPinnedStackLocation() {
Wale Ogunwale61911492017-10-11 08:50:50 -0700387 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
388 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
389 // Ensure that the pinned stack is the top stack
390 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
391 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700392 // By default, this should try to create a new stack on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700393 final TaskStack otherStack = createTaskStackOnDisplay(mDisplayContent);
394 // Ensure that the other stack is on the display.
395 assertEquals(mDisplayContent, otherStack.getDisplayContent());
Bryce Lee48f4b572017-04-10 10:54:15 -0700396 // Ensure that the pinned stack is still on top
Wale Ogunwale61911492017-10-11 08:50:50 -0700397 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Bryce Lee48f4b572017-04-10 10:54:15 -0700398 }
399
Andrii Kulian0214ed92017-05-16 13:44:05 -0700400 /**
401 * Test that WM does not report displays to AM that are pending to be removed.
402 */
403 @Test
404 public void testDontReportDeferredRemoval() {
405 // Create a display and add an animating window to it.
406 final DisplayContent dc = createNewDisplay();
407 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
408 window.mAnimatingExit = true;
409 // Request display removal, it should be deferred.
410 dc.removeIfPossible();
411 // Request ordered display ids from WM.
412 final SparseIntArray orderedDisplayIds = new SparseIntArray();
413 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
414 // Make sure that display that is marked for removal is not reported.
415 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
416 }
417
Andrii Kulian92c9a942017-10-10 00:41:41 -0700418 @Test
Adrian Roos1cf585052018-01-03 18:43:27 +0100419 public void testDisplayCutout_rot0() throws Exception {
420 synchronized (sWm.getWindowManagerLock()) {
421 final DisplayContent dc = createNewDisplay();
422 dc.mInitialDisplayWidth = 200;
423 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100424 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100425 final DisplayCutout cutout = new WmDisplayCutout(
426 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
427 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100428
429 dc.mInitialDisplayCutout = cutout;
430 dc.setRotation(Surface.ROTATION_0);
431 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
432
433 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
434 }
435 }
436
437 @Test
438 public void testDisplayCutout_rot90() throws Exception {
439 synchronized (sWm.getWindowManagerLock()) {
440 final DisplayContent dc = createNewDisplay();
441 dc.mInitialDisplayWidth = 200;
442 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100443 Rect r1 = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100444 final DisplayCutout cutout = new WmDisplayCutout(
445 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
446 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100447
448 dc.mInitialDisplayCutout = cutout;
449 dc.setRotation(Surface.ROTATION_90);
450 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
451
Adrian Roos24264212018-02-19 16:26:15 +0100452 final Rect r = new Rect(0, 80, 10, 120);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100453 assertEquals(new WmDisplayCutout(
454 fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
455 .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100456 }
457 }
458
459 @Test
Adrian Roos5251b1d2018-03-23 18:57:43 +0100460 public void testLayoutSeq_assignedDuringLayout() throws Exception {
461 synchronized (sWm.getWindowManagerLock()) {
462
463 final DisplayContent dc = createNewDisplay();
464 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
465
466 dc.setLayoutNeeded();
467 dc.performLayout(true /* initial */, false /* updateImeWindows */);
468
469 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
470 }
471 }
472
473 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700474 @SuppressLint("InlinedApi")
475 public void testOrientationDefinedByKeyguard() {
476 final DisplayContent dc = createNewDisplay();
477 // Create a window that requests landscape orientation. It will define device orientation
478 // by default.
479 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
480 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
481
482 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
483 keyguard.mHasSurface = true;
484 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
485
486 assertEquals("Screen orientation must be defined by the app window by default",
487 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
488
489 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
490 assertEquals("Visible keyguard must influence device orientation",
491 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
492
493 sWm.setKeyguardGoingAway(true);
494 assertEquals("Keyguard that is going away must not influence device orientation",
495 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
496 }
497
Andrii Kulianf0379de2018-03-14 16:24:07 -0700498 @Test
499 public void testDisableDisplayInfoOverrideFromWindowManager() {
500 final DisplayContent dc = createNewDisplay();
501
502 assertTrue(dc.mShouldOverrideDisplayConfiguration);
503 sWm.dontOverrideDisplayInfo(dc.getDisplayId());
504
505 assertFalse(dc.mShouldOverrideDisplayConfiguration);
506 verify(sWm.mDisplayManagerInternal, times(1))
507 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
508 }
509
Bryce Lee27cec322017-03-21 09:41:37 -0700510 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
511 int expectedBaseHeight, int expectedBaseDensity) {
512 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
513 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
514 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
515 }
516
Adrian Roos0f9368c2018-04-08 10:59:08 -0700517 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
518 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800519
520 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700521 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700522 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
523
524 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800525
526 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700527 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700528 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
529 }
530
531 private static List<WindowState> reverseList(List<WindowState> list) {
532 final ArrayList<WindowState> result = new ArrayList<>(list);
533 Collections.reverse(result);
534 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800535 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700536
537 private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
538 final long downTime = SystemClock.uptimeMillis();
539 final long eventTime = SystemClock.uptimeMillis() + 100;
540 final int metaState = 0;
541
542 return MotionEvent.obtain(
543 downTime,
544 eventTime,
545 isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
546 x,
547 y,
548 metaState);
549 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700550}