blob: 856e94055ed5121127aef464b328a6d657888021 [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
Bryce Lee48f4b572017-04-10 10:54:15 -070019import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwale34247952017-02-19 11:57:53 -080020import static android.view.Display.DEFAULT_DISPLAY;
21import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
22import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
23import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
24import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
David Stevens46939562017-03-24 13:04:00 -070025import static com.android.server.wm.WindowContainer.POSITION_TOP;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static org.junit.Assert.assertEquals;
27import static org.junit.Assert.assertTrue;
28
Wale Ogunwale42bab782017-05-02 13:16:39 -070029import org.junit.Ignore;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070030import org.junit.Test;
31import org.junit.runner.RunWith;
32
Andrii Kuliand68501e2017-01-10 22:57:27 -080033import android.content.res.Configuration;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070034import android.platform.test.annotations.Presubmit;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070035import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
Andrii Kulian0214ed92017-05-16 13:44:05 -070037import android.util.SparseIntArray;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070038
Wale Ogunwale34247952017-02-19 11:57:53 -080039import java.util.Arrays;
40import java.util.LinkedList;
41import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070042
43/**
44 * Tests for the {@link DisplayContent} class.
45 *
46 * Build/Install/Run:
47 * bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
48 */
49@SmallTest
50@Presubmit
51@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080052public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070053
54 @Test
55 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080056 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070057 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070058 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
59 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080060 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070061
Wale Ogunwale34247952017-02-19 11:57:53 -080062 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070063 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080064 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070065 mChildAppWindowBelow,
66 mAppWindow,
67 mChildAppWindowAbove,
68 mDockedDividerWindow,
69 mStatusBarWindow,
70 mNavBarWindow,
71 mImeWindow,
72 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080073 }
74
75 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080076 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080077 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -070078 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080079
80 sWm.mInputMethodTarget = imeAppTarget;
81
Wale Ogunwale34247952017-02-19 11:57:53 -080082 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070083 mWallpaperWindow,
84 mChildAppWindowBelow,
85 mAppWindow,
86 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -080087 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070088 mImeWindow,
89 mImeDialogWindow,
90 mDockedDividerWindow,
91 mStatusBarWindow,
92 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -080093 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080094
Wale Ogunwale34247952017-02-19 11:57:53 -080095 @Test
96 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -070097 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080098
Wale Ogunwale34247952017-02-19 11:57:53 -080099 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700100 mWallpaperWindow,
101 mChildAppWindowBelow,
102 mAppWindow,
103 mChildAppWindowAbove,
104 mImeWindow,
105 mImeDialogWindow,
106 mDockedDividerWindow,
107 mStatusBarWindow,
108 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700109 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800110
111 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800112 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700113 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -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 mDockedDividerWindow,
121 mStatusBarWindow,
122 mImeWindow,
123 mImeDialogWindow,
124 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800125 }
126
127 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800128 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
129 // This window is set-up to be z-ordered between some windows that go in the same token like
130 // the nav bar and status bar.
131 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700132 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800133
Wale Ogunwale34247952017-02-19 11:57:53 -0800134 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700135 mWallpaperWindow,
136 mChildAppWindowBelow,
137 mAppWindow,
138 mChildAppWindowAbove,
139 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800140 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700141 mStatusBarWindow,
142 mNavBarWindow,
143 mImeWindow,
144 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800145 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800146
Wale Ogunwale34247952017-02-19 11:57:53 -0800147 @Test
148 public void testComputeImeTarget() throws Exception {
149 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700150 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800151 appWin.setHasSurface(true);
152 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800154 assertEquals(appWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800155
Wale Ogunwale34247952017-02-19 11:57:53 -0800156 // Verify that an child window can be an ime target.
157 final WindowState childWin = createWindow(appWin,
158 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
159 childWin.setHasSurface(true);
160 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700161 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800162 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800163 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800164
Andrii Kuliand68501e2017-01-10 22:57:27 -0800165 /**
166 * This tests stack movement between displays and proper stack's, task's and app token's display
167 * container references updates.
168 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800169 @Test
170 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800171 // Create a second display.
172 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800173
174 // Add stack with activity.
175 final TaskStack stack = createTaskStackOnDisplay(dc);
176 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
177 assertEquals(dc, stack.getParent().getParent());
178 assertEquals(dc, stack.getDisplayContent());
179
180 final Task task = createTaskInStack(stack, 0 /* userId */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700181 final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800182 task.addChild(token, 0);
183 assertEquals(dc, task.getDisplayContent());
184 assertEquals(dc, token.getDisplayContent());
185
186 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700187 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
188 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
189 assertEquals(mDisplayContent, stack.getParent().getParent());
190 assertEquals(mDisplayContent, stack.getDisplayContent());
191 assertEquals(mDisplayContent, task.getDisplayContent());
192 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800193 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800194
195 /**
196 * This tests override configuration updates for display content.
197 */
198 @Test
199 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700200 final int displayId = mDisplayContent.getDisplayId();
201 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800202
203 // Create new, slightly changed override configuration and apply it to the display.
204 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
205 newOverrideConfig.densityDpi += 120;
206 newOverrideConfig.fontScale += 0.3;
207
208 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
209
210 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700211 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800212 }
213
214 /**
215 * This tests global configuration updates when default display config is updated.
216 */
217 @Test
218 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700219 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800220
221 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700222 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800223 newOverrideConfig.densityDpi += 120;
224 newOverrideConfig.fontScale += 0.3;
225
226 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800227
228 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800229 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800230 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
231 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800232
233 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700234 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800235 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700236 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
237 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800238 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800239
David Stevens46939562017-03-24 13:04:00 -0700240 @Test
Wale Ogunwale42bab782017-05-02 13:16:39 -0700241 @Ignore
David Stevens46939562017-03-24 13:04:00 -0700242 public void testFocusedWindowMultipleDisplays() throws Exception {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700243 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700244 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700245 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700246 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
247
248 // Check that a new display doesn't affect focus
249 final DisplayContent dc = createNewDisplay();
250 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
251
252 // Add a window to the second display, and it should be focused
253 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
254 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
255
256 // Move the first window to the to including parents, and make sure focus is updated
257 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
258 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
259 }
260
Bryce Lee27cec322017-03-21 09:41:37 -0700261 /**
262 * This tests setting the maximum ui width on a display.
263 */
264 @Test
265 public void testMaxUiWidth() throws Exception {
266 final int baseWidth = 1440;
267 final int baseHeight = 2560;
268 final int baseDensity = 300;
269
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700270 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700271
272 final int maxWidth = 300;
273 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
274 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
275
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700276 mDisplayContent.setMaxUiWidth(maxWidth);
277 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700278
279 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700280 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
281 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700282
283 final int smallerWidth = 200;
284 final int smallerHeight = 400;
285 final int smallerDensity = 100;
286
287 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700288 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
289 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700290
291 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700292 mDisplayContent.setMaxUiWidth(maxWidth);
293 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700294 }
295
Bryce Lee48f4b572017-04-10 10:54:15 -0700296 /**
297 * This test enforces that the pinned stack is always kept as the top stack.
298 */
299 @Test
300 public void testPinnedStackLocation() {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700301 createStackControllerOnStackOnDisplay(PINNED_STACK_ID, mDisplayContent);
302 final int initialStackCount = mDisplayContent.getStackCount();
Bryce Lee48f4b572017-04-10 10:54:15 -0700303 // Ensure that the pinned stack was placed at the end
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700304 assertEquals(initialStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
Bryce Lee48f4b572017-04-10 10:54:15 -0700305 // By default, this should try to create a new stack on top
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700306 createTaskStackOnDisplay(mDisplayContent);
307 final int afterStackCount = mDisplayContent.getStackCount();
Bryce Lee48f4b572017-04-10 10:54:15 -0700308 // Make sure the stack count has increased
309 assertEquals(initialStackCount + 1, afterStackCount);
310 // Ensure that the pinned stack is still on top
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700311 assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
Bryce Lee48f4b572017-04-10 10:54:15 -0700312 }
313
Andrii Kulian0214ed92017-05-16 13:44:05 -0700314 /**
315 * Test that WM does not report displays to AM that are pending to be removed.
316 */
317 @Test
318 public void testDontReportDeferredRemoval() {
319 // Create a display and add an animating window to it.
320 final DisplayContent dc = createNewDisplay();
321 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
322 window.mAnimatingExit = true;
323 // Request display removal, it should be deferred.
324 dc.removeIfPossible();
325 // Request ordered display ids from WM.
326 final SparseIntArray orderedDisplayIds = new SparseIntArray();
327 sWm.getDisplaysInFocusOrder(orderedDisplayIds);
328 // Make sure that display that is marked for removal is not reported.
329 assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
330 }
331
Bryce Lee27cec322017-03-21 09:41:37 -0700332 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
333 int expectedBaseHeight, int expectedBaseDensity) {
334 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
335 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
336 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
337 }
338
Wale Ogunwale34247952017-02-19 11:57:53 -0800339 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
340 final LinkedList<WindowState> actualWindows = new LinkedList();
341
342 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700343 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800344 assertEquals(expectedWindows.size(), actualWindows.size());
345 for (WindowState w : expectedWindows) {
346 assertEquals(w, actualWindows.pollFirst());
347 }
348 assertTrue(actualWindows.isEmpty());
349
350 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700351 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800352 assertEquals(expectedWindows.size(), actualWindows.size());
353 for (WindowState w : expectedWindows) {
354 assertEquals(w, actualWindows.pollLast());
355 }
356 assertTrue(actualWindows.isEmpty());
357 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700358}