DisplayContentTests.java revision 11cc516a925ac7fc814dbb0a79a7f0abfbfe1ce1
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.app.ActivityManager.StackId.PINNED_STACK_ID;
20import 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;
25import static com.android.server.wm.WindowContainer.POSITION_TOP;
26import static org.junit.Assert.assertEquals;
27import static org.junit.Assert.assertTrue;
28
29import org.junit.Test;
30import org.junit.runner.RunWith;
31
32import android.content.res.Configuration;
33import android.platform.test.annotations.Presubmit;
34import android.support.test.filters.SmallTest;
35import android.support.test.runner.AndroidJUnit4;
36
37import java.util.Arrays;
38import java.util.LinkedList;
39import java.util.List;
40
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)
50public class DisplayContentTests extends WindowTestsBase {
51
52    @Test
53    public void testForAllWindows() throws Exception {
54        final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
55                mDisplayContent, "exiting app");
56        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
57        exitingAppToken.mIsExiting = true;
58        exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
59
60        assertForAllWindowsOrder(Arrays.asList(
61                mWallpaperWindow,
62                exitingAppWindow,
63                mChildAppWindowBelow,
64                mAppWindow,
65                mChildAppWindowAbove,
66                mDockedDividerWindow,
67                mStatusBarWindow,
68                mNavBarWindow,
69                mImeWindow,
70                mImeDialogWindow));
71    }
72
73    @Test
74    public void testForAllWindows_WithAppImeTarget() throws Exception {
75        final WindowState imeAppTarget =
76                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
77
78        sWm.mInputMethodTarget = imeAppTarget;
79
80        assertForAllWindowsOrder(Arrays.asList(
81                mWallpaperWindow,
82                mChildAppWindowBelow,
83                mAppWindow,
84                mChildAppWindowAbove,
85                imeAppTarget,
86                mImeWindow,
87                mImeDialogWindow,
88                mDockedDividerWindow,
89                mStatusBarWindow,
90                mNavBarWindow));
91    }
92
93    @Test
94    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
95        sWm.mInputMethodTarget = mChildAppWindowAbove;
96
97        assertForAllWindowsOrder(Arrays.asList(
98                mWallpaperWindow,
99                mChildAppWindowBelow,
100                mAppWindow,
101                mChildAppWindowAbove,
102                mImeWindow,
103                mImeDialogWindow,
104                mDockedDividerWindow,
105                mStatusBarWindow,
106                mNavBarWindow));
107    }
108
109    @Test
110    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
111        sWm.mInputMethodTarget = mStatusBarWindow;
112
113        assertForAllWindowsOrder(Arrays.asList(
114                mWallpaperWindow,
115                mChildAppWindowBelow,
116                mAppWindow,
117                mChildAppWindowAbove,
118                mDockedDividerWindow,
119                mStatusBarWindow,
120                mImeWindow,
121                mImeDialogWindow,
122                mNavBarWindow));
123    }
124
125    @Test
126    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,
130                mDisplayContent, "voiceInteractionWindow");
131
132        assertForAllWindowsOrder(Arrays.asList(
133                mWallpaperWindow,
134                mChildAppWindowBelow,
135                mAppWindow,
136                mChildAppWindowAbove,
137                mDockedDividerWindow,
138                voiceInteractionWindow,
139                mStatusBarWindow,
140                mNavBarWindow,
141                mImeWindow,
142                mImeDialogWindow));
143    }
144
145    @Test
146    public void testComputeImeTarget() throws Exception {
147        // Verify that an app window can be an ime target.
148        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
149        appWin.setHasSurface(true);
150        assertTrue(appWin.canBeImeTarget());
151        WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
152        assertEquals(appWin, imeTarget);
153
154        // 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());
159        imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
160        assertEquals(childWin, imeTarget);
161    }
162
163    /**
164     * This tests stack movement between displays and proper stack's, task's and app token's display
165     * container references updates.
166     */
167    @Test
168    public void testMoveStackBetweenDisplays() throws Exception {
169        // Create a second display.
170        final DisplayContent dc = createNewDisplay();
171
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 */);
179        final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
180        task.addChild(token, 0);
181        assertEquals(dc, task.getDisplayContent());
182        assertEquals(dc, token.getDisplayContent());
183
184        // Move stack to first display.
185        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());
191    }
192
193    /**
194     * This tests override configuration updates for display content.
195     */
196    @Test
197    public void testDisplayOverrideConfigUpdate() throws Exception {
198        final int displayId = mDisplayContent.getDisplayId();
199        final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
200
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.
209        assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
210    }
211
212    /**
213     * This tests global configuration updates when default display config is updated.
214     */
215    @Test
216    public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
217        final Configuration currentConfig = mDisplayContent.getConfiguration();
218
219        // Create new, slightly changed override configuration and apply it to the display.
220        final Configuration newOverrideConfig = new Configuration(currentConfig);
221        newOverrideConfig.densityDpi += 120;
222        newOverrideConfig.fontScale += 0.3;
223
224        sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
225
226        // Check that global configuration is updated, as we've updated default display's config.
227        Configuration globalConfig = sWm.mRoot.getConfiguration();
228        assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
229        assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
230
231        // Return back to original values.
232        sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
233        globalConfig = sWm.mRoot.getConfiguration();
234        assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
235        assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
236    }
237
238    @Test
239    public void testFocusedWindowMultipleDisplays() throws Exception {
240        // Create a focusable window and check that focus is calcualted correctly
241        final WindowState window1 =
242                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
243        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
258    /**
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
267        mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
268
269        final int maxWidth = 300;
270        final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
271        final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
272
273        mDisplayContent.setMaxUiWidth(maxWidth);
274        verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
275
276        // Assert setting values again does not change;
277        mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
278        verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
279
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
285        mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
286        verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
287
288        // Verify that setting the max width to a greater value than the base width has no effect
289        mDisplayContent.setMaxUiWidth(maxWidth);
290        verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
291    }
292
293    /**
294     * This test enforces that the pinned stack is always kept as the top stack.
295     */
296    @Test
297    public void testPinnedStackLocation() {
298        createStackControllerOnStackOnDisplay(PINNED_STACK_ID, mDisplayContent);
299        final int initialStackCount = mDisplayContent.getStackCount();
300        // Ensure that the pinned stack was placed at the end
301        assertEquals(initialStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
302        // By default, this should try to create a new stack on top
303        createTaskStackOnDisplay(mDisplayContent);
304        final int afterStackCount = mDisplayContent.getStackCount();
305        // Make sure the stack count has increased
306        assertEquals(initialStackCount + 1, afterStackCount);
307        // Ensure that the pinned stack is still on top
308        assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
309    }
310
311    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
318    private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
319        final LinkedList<WindowState> actualWindows = new LinkedList();
320
321        // Test forward traversal.
322        mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
323        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.
330        mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
331        assertEquals(expectedWindows.size(), actualWindows.size());
332        for (WindowState w : expectedWindows) {
333            assertEquals(w, actualWindows.pollLast());
334        }
335        assertTrue(actualWindows.isEmpty());
336    }
337}
338