blob: e8dc69faeee9dd216766a8b0b8513b733635158f [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 Ogunwaleb783fd82016-11-04 09:51:54 -070029import org.junit.Test;
30import org.junit.runner.RunWith;
31
Andrii Kuliand68501e2017-01-10 22:57:27 -080032import android.content.res.Configuration;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070033import android.platform.test.annotations.Presubmit;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070034import android.support.test.filters.SmallTest;
35import android.support.test.runner.AndroidJUnit4;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070036
Wale Ogunwale34247952017-02-19 11:57:53 -080037import java.util.Arrays;
38import java.util.LinkedList;
39import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070040
41/**
42 * Tests for the {@link DisplayContent} class.
43 *
44 * Build/Install/Run:
45 * bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
46 */
47@SmallTest
48@Presubmit
49@RunWith(AndroidJUnit4.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080050public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070051
52 @Test
53 public void testForAllWindows() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080054 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070055 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070056 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
57 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080058 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070059
Wale Ogunwale34247952017-02-19 11:57:53 -080060 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070061 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080062 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070063 mChildAppWindowBelow,
64 mAppWindow,
65 mChildAppWindowAbove,
66 mDockedDividerWindow,
67 mStatusBarWindow,
68 mNavBarWindow,
69 mImeWindow,
70 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080071 }
72
73 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080074 public void testForAllWindows_WithAppImeTarget() throws Exception {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080075 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -070076 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080077
78 sWm.mInputMethodTarget = imeAppTarget;
79
Wale Ogunwale34247952017-02-19 11:57:53 -080080 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070081 mWallpaperWindow,
82 mChildAppWindowBelow,
83 mAppWindow,
84 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -080085 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070086 mImeWindow,
87 mImeDialogWindow,
88 mDockedDividerWindow,
89 mStatusBarWindow,
90 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -080091 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080092
Wale Ogunwale34247952017-02-19 11:57:53 -080093 @Test
94 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -070095 sWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080096
Wale Ogunwale34247952017-02-19 11:57:53 -080097 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070098 mWallpaperWindow,
99 mChildAppWindowBelow,
100 mAppWindow,
101 mChildAppWindowAbove,
102 mImeWindow,
103 mImeDialogWindow,
104 mDockedDividerWindow,
105 mStatusBarWindow,
106 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700107 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800108
109 @Test
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800110 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700111 sWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800112
Wale Ogunwale34247952017-02-19 11:57:53 -0800113 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700114 mWallpaperWindow,
115 mChildAppWindowBelow,
116 mAppWindow,
117 mChildAppWindowAbove,
118 mDockedDividerWindow,
119 mStatusBarWindow,
120 mImeWindow,
121 mImeDialogWindow,
122 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800123 }
124
125 @Test
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800126 public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
127 // This window is set-up to be z-ordered between some windows that go in the same token like
128 // the nav bar and status bar.
129 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700130 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800131
Wale Ogunwale34247952017-02-19 11:57:53 -0800132 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700133 mWallpaperWindow,
134 mChildAppWindowBelow,
135 mAppWindow,
136 mChildAppWindowAbove,
137 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800138 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700139 mStatusBarWindow,
140 mNavBarWindow,
141 mImeWindow,
142 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800143 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800144
Wale Ogunwale34247952017-02-19 11:57:53 -0800145 @Test
146 public void testComputeImeTarget() throws Exception {
147 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700148 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800149 appWin.setHasSurface(true);
150 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700151 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800152 assertEquals(appWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800153
Wale Ogunwale34247952017-02-19 11:57:53 -0800154 // Verify that an child window can be an ime target.
155 final WindowState childWin = createWindow(appWin,
156 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
157 childWin.setHasSurface(true);
158 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700159 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800160 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800161 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800162
Andrii Kuliand68501e2017-01-10 22:57:27 -0800163 /**
164 * This tests stack movement between displays and proper stack's, task's and app token's display
165 * container references updates.
166 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800167 @Test
168 public void testMoveStackBetweenDisplays() throws Exception {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800169 // Create a second display.
170 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800171
172 // Add stack with activity.
173 final TaskStack stack = createTaskStackOnDisplay(dc);
174 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
175 assertEquals(dc, stack.getParent().getParent());
176 assertEquals(dc, stack.getDisplayContent());
177
178 final Task task = createTaskInStack(stack, 0 /* userId */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700179 final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800180 task.addChild(token, 0);
181 assertEquals(dc, task.getDisplayContent());
182 assertEquals(dc, token.getDisplayContent());
183
184 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700185 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
186 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
187 assertEquals(mDisplayContent, stack.getParent().getParent());
188 assertEquals(mDisplayContent, stack.getDisplayContent());
189 assertEquals(mDisplayContent, task.getDisplayContent());
190 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800191 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800192
193 /**
194 * This tests override configuration updates for display content.
195 */
196 @Test
197 public void testDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700198 final int displayId = mDisplayContent.getDisplayId();
199 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800200
201 // Create new, slightly changed override configuration and apply it to the display.
202 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
203 newOverrideConfig.densityDpi += 120;
204 newOverrideConfig.fontScale += 0.3;
205
206 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
207
208 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700209 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800210 }
211
212 /**
213 * This tests global configuration updates when default display config is updated.
214 */
215 @Test
216 public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700217 final Configuration currentConfig = mDisplayContent.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800218
219 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700220 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800221 newOverrideConfig.densityDpi += 120;
222 newOverrideConfig.fontScale += 0.3;
223
224 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800225
226 // Check that global configuration is updated, as we've updated default display's config.
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800227 Configuration globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800228 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
229 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800230
231 // Return back to original values.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700232 sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800233 globalConfig = sWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700234 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
235 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800236 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800237
David Stevens46939562017-03-24 13:04:00 -0700238 @Test
239 public void testFocusedWindowMultipleDisplays() throws Exception {
240 // Create a focusable window and check that focus is calcualted correctly
241 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700242 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
David Stevens46939562017-03-24 13:04:00 -0700243 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
244
245 // Check that a new display doesn't affect focus
246 final DisplayContent dc = createNewDisplay();
247 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
248
249 // Add a window to the second display, and it should be focused
250 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
251 assertEquals(window2, sWm.mRoot.computeFocusedWindow());
252
253 // Move the first window to the to including parents, and make sure focus is updated
254 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
255 assertEquals(window1, sWm.mRoot.computeFocusedWindow());
256 }
257
Bryce Lee27cec322017-03-21 09:41:37 -0700258 /**
259 * This tests setting the maximum ui width on a display.
260 */
261 @Test
262 public void testMaxUiWidth() throws Exception {
263 final int baseWidth = 1440;
264 final int baseHeight = 2560;
265 final int baseDensity = 300;
266
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700267 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700268
269 final int maxWidth = 300;
270 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
271 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
272
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700273 mDisplayContent.setMaxUiWidth(maxWidth);
274 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700275
276 // Assert setting values again does not change;
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700277 mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
278 verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700279
280 final int smallerWidth = 200;
281 final int smallerHeight = 400;
282 final int smallerDensity = 100;
283
284 // Specify smaller dimension, verify that it is honored
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700285 mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
286 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700287
288 // Verify that setting the max width to a greater value than the base width has no effect
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700289 mDisplayContent.setMaxUiWidth(maxWidth);
290 verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700291 }
292
Bryce Lee48f4b572017-04-10 10:54:15 -0700293 /**
294 * This test enforces that the pinned stack is always kept as the top stack.
295 */
296 @Test
297 public void testPinnedStackLocation() {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700298 createStackControllerOnStackOnDisplay(PINNED_STACK_ID, mDisplayContent);
299 final int initialStackCount = mDisplayContent.getStackCount();
Bryce Lee48f4b572017-04-10 10:54:15 -0700300 // Ensure that the pinned stack was placed at the end
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700301 assertEquals(initialStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
Bryce Lee48f4b572017-04-10 10:54:15 -0700302 // By default, this should try to create a new stack on top
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700303 createTaskStackOnDisplay(mDisplayContent);
304 final int afterStackCount = mDisplayContent.getStackCount();
Bryce Lee48f4b572017-04-10 10:54:15 -0700305 // Make sure the stack count has increased
306 assertEquals(initialStackCount + 1, afterStackCount);
307 // Ensure that the pinned stack is still on top
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700308 assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
Bryce Lee48f4b572017-04-10 10:54:15 -0700309 }
310
Bryce Lee27cec322017-03-21 09:41:37 -0700311 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
312 int expectedBaseHeight, int expectedBaseDensity) {
313 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
314 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
315 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
316 }
317
Wale Ogunwale34247952017-02-19 11:57:53 -0800318 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
319 final LinkedList<WindowState> actualWindows = new LinkedList();
320
321 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700322 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800323 assertEquals(expectedWindows.size(), actualWindows.size());
324 for (WindowState w : expectedWindows) {
325 assertEquals(w, actualWindows.pollFirst());
326 }
327 assertTrue(actualWindows.isEmpty());
328
329 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700330 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800331 assertEquals(expectedWindows.size(), actualWindows.size());
332 for (WindowState w : expectedWindows) {
333 assertEquals(w, actualWindows.pollLast());
334 }
335 assertTrue(actualWindows.isEmpty());
336 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700337}