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