DisplayContentTests.java revision a95bfff74604bbf05a66ff37947b1b2fb2fdcaa2
1/*
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
19import static android.view.Display.DEFAULT_DISPLAY;
20import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
21import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
22import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
23import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
24import static com.android.server.wm.WindowContainer.POSITION_TOP;
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertTrue;
27
28import org.junit.Test;
29import org.junit.runner.RunWith;
30
31import android.content.res.Configuration;
32import android.platform.test.annotations.Presubmit;
33import android.support.test.filters.SmallTest;
34import android.support.test.runner.AndroidJUnit4;
35
36import java.util.Arrays;
37import java.util.LinkedList;
38import java.util.List;
39
40/**
41 * Tests for the {@link DisplayContent} class.
42 *
43 * Build/Install/Run:
44 *  bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
45 */
46@SmallTest
47@Presubmit
48@RunWith(AndroidJUnit4.class)
49public class DisplayContentTests extends WindowTestsBase {
50
51    @Test
52    public void testForAllWindows() throws Exception {
53        final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
54                sDisplayContent, "exiting app");
55        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
56        exitingAppToken.mIsExiting = true;
57        exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
58
59        assertForAllWindowsOrder(Arrays.asList(
60                sWallpaperWindow,
61                exitingAppWindow,
62                sChildAppWindowBelow,
63                sAppWindow,
64                sChildAppWindowAbove,
65                sDockedDividerWindow,
66                sStatusBarWindow,
67                sNavBarWindow,
68                sImeWindow,
69                sImeDialogWindow));
70    }
71
72    @Test
73    public void testForAllWindows_WithAppImeTarget() throws Exception {
74        final WindowState imeAppTarget =
75                createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
76
77        sWm.mInputMethodTarget = imeAppTarget;
78
79        assertForAllWindowsOrder(Arrays.asList(
80                sWallpaperWindow,
81                sChildAppWindowBelow,
82                sAppWindow,
83                sChildAppWindowAbove,
84                imeAppTarget,
85                sImeWindow,
86                sImeDialogWindow,
87                sDockedDividerWindow,
88                sStatusBarWindow,
89                sNavBarWindow));
90    }
91
92    @Test
93    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
94        sWm.mInputMethodTarget = sChildAppWindowAbove;
95
96        assertForAllWindowsOrder(Arrays.asList(
97                sWallpaperWindow,
98                sChildAppWindowBelow,
99                sAppWindow,
100                sChildAppWindowAbove,
101                sImeWindow,
102                sImeDialogWindow,
103                sDockedDividerWindow,
104                sStatusBarWindow,
105                sNavBarWindow));
106    }
107
108    @Test
109    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
110        sWm.mInputMethodTarget = sStatusBarWindow;
111
112        assertForAllWindowsOrder(Arrays.asList(
113                sWallpaperWindow,
114                sChildAppWindowBelow,
115                sAppWindow,
116                sChildAppWindowAbove,
117                sDockedDividerWindow,
118                sStatusBarWindow,
119                sImeWindow,
120                sImeDialogWindow,
121                sNavBarWindow));
122    }
123
124    @Test
125    public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
126        // This window is set-up to be z-ordered between some windows that go in the same token like
127        // the nav bar and status bar.
128        final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
129                sDisplayContent, "voiceInteractionWindow");
130
131        assertForAllWindowsOrder(Arrays.asList(
132                sWallpaperWindow,
133                sChildAppWindowBelow,
134                sAppWindow,
135                sChildAppWindowAbove,
136                sDockedDividerWindow,
137                voiceInteractionWindow,
138                sStatusBarWindow,
139                sNavBarWindow,
140                sImeWindow,
141                sImeDialogWindow));
142    }
143
144    @Test
145    public void testComputeImeTarget() throws Exception {
146        // Verify that an app window can be an ime target.
147        final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
148        appWin.setHasSurface(true);
149        assertTrue(appWin.canBeImeTarget());
150        WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
151        assertEquals(appWin, imeTarget);
152
153        // Verify that an child window can be an ime target.
154        final WindowState childWin = createWindow(appWin,
155                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
156        childWin.setHasSurface(true);
157        assertTrue(childWin.canBeImeTarget());
158        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
159        assertEquals(childWin, imeTarget);
160    }
161
162    /**
163     * This tests stack movement between displays and proper stack's, task's and app token's display
164     * container references updates.
165     */
166    @Test
167    public void testMoveStackBetweenDisplays() throws Exception {
168        // Create a second display.
169        final DisplayContent dc = createNewDisplay();
170
171        // Add stack with activity.
172        final TaskStack stack = createTaskStackOnDisplay(dc);
173        assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
174        assertEquals(dc, stack.getParent().getParent());
175        assertEquals(dc, stack.getDisplayContent());
176
177        final Task task = createTaskInStack(stack, 0 /* userId */);
178        final TestAppWindowToken token = new TestAppWindowToken(dc);
179        task.addChild(token, 0);
180        assertEquals(dc, task.getDisplayContent());
181        assertEquals(dc, token.getDisplayContent());
182
183        // Move stack to first display.
184        sDisplayContent.moveStackToDisplay(stack);
185        assertEquals(sDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
186        assertEquals(sDisplayContent, stack.getParent().getParent());
187        assertEquals(sDisplayContent, stack.getDisplayContent());
188        assertEquals(sDisplayContent, task.getDisplayContent());
189        assertEquals(sDisplayContent, token.getDisplayContent());
190    }
191
192    /**
193     * This tests override configuration updates for display content.
194     */
195    @Test
196    public void testDisplayOverrideConfigUpdate() throws Exception {
197        final int displayId = sDisplayContent.getDisplayId();
198        final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration();
199
200        // Create new, slightly changed override configuration and apply it to the display.
201        final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
202        newOverrideConfig.densityDpi += 120;
203        newOverrideConfig.fontScale += 0.3;
204
205        sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
206
207        // Check that override config is applied.
208        assertEquals(newOverrideConfig, sDisplayContent.getOverrideConfiguration());
209    }
210
211    /**
212     * This tests global configuration updates when default display config is updated.
213     */
214    @Test
215    public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
216        final Configuration currentConfig = sDisplayContent.getConfiguration();
217
218        // Create new, slightly changed override configuration and apply it to the display.
219        final Configuration newOverrideConfig = new Configuration(currentConfig);
220        newOverrideConfig.densityDpi += 120;
221        newOverrideConfig.fontScale += 0.3;
222
223        sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
224
225        // Check that global configuration is updated, as we've updated default display's config.
226        Configuration globalConfig = sWm.mRoot.getConfiguration();
227        assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
228        assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
229
230        // Return back to original values.
231        sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
232        globalConfig = sWm.mRoot.getConfiguration();
233        assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
234        assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
235    }
236
237    @Test
238    public void testFocusedWindowMultipleDisplays() throws Exception {
239        // Create a focusable window and check that focus is calcualted correctly
240        final WindowState window1 =
241                createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "window1");
242        assertEquals(window1, sWm.mRoot.computeFocusedWindow());
243
244        // Check that a new display doesn't affect focus
245        final DisplayContent dc = createNewDisplay();
246        assertEquals(window1, sWm.mRoot.computeFocusedWindow());
247
248        // Add a window to the second display, and it should be focused
249        final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
250        assertEquals(window2, sWm.mRoot.computeFocusedWindow());
251
252        // Move the first window to the to including parents, and make sure focus is updated
253        window1.getParent().positionChildAt(POSITION_TOP, window1, true);
254        assertEquals(window1, sWm.mRoot.computeFocusedWindow());
255    }
256
257    /**
258     * This tests setting the maximum ui width on a display.
259     */
260    @Test
261    public void testMaxUiWidth() throws Exception {
262        final int baseWidth = 1440;
263        final int baseHeight = 2560;
264        final int baseDensity = 300;
265
266        sDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
267
268        final int maxWidth = 300;
269        final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
270        final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
271
272        sDisplayContent.setMaxUiWidth(maxWidth);
273        verifySizes(sDisplayContent, maxWidth, resultingHeight, resultingDensity);
274
275        // Assert setting values again does not change;
276        sDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
277        verifySizes(sDisplayContent, maxWidth, resultingHeight, resultingDensity);
278
279        final int smallerWidth = 200;
280        final int smallerHeight = 400;
281        final int smallerDensity = 100;
282
283        // Specify smaller dimension, verify that it is honored
284        sDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
285        verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
286
287        // Verify that setting the max width to a greater value than the base width has no effect
288        sDisplayContent.setMaxUiWidth(maxWidth);
289        verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
290    }
291
292    private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
293                             int expectedBaseHeight, int expectedBaseDensity) {
294        assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
295        assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
296        assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
297    }
298
299    private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
300        final LinkedList<WindowState> actualWindows = new LinkedList();
301
302        // Test forward traversal.
303        sDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
304        assertEquals(expectedWindows.size(), actualWindows.size());
305        for (WindowState w : expectedWindows) {
306            assertEquals(w, actualWindows.pollFirst());
307        }
308        assertTrue(actualWindows.isEmpty());
309
310        // Test backward traversal.
311        sDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
312        assertEquals(expectedWindows.size(), actualWindows.size());
313        for (WindowState w : expectedWindows) {
314            assertEquals(w, actualWindows.pollLast());
315        }
316        assertTrue(actualWindows.isEmpty());
317    }
318}
319