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