DisplayContentTests.java revision 6d41026f1b3dc910c9d34ab89993a280dc9679cf
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 org.junit.Assert.assertEquals; 25import static org.junit.Assert.assertNotEquals; 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 sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder(); 151 WindowState imeTarget = sDisplayContent.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 = sDisplayContent.computeImeTarget(false /* updateImeTarget */); 160 assertEquals(childWin, imeTarget); 161 162 final WindowState appWin2 = 163 createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2"); 164 appWin2.setHasSurface(true); 165 assertTrue(appWin2.canBeImeTarget()); 166 // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change 167 // to the new app. 168 imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); 169 assertNotEquals(appWin2, imeTarget); 170 171 sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder(); 172 // Verify app is not IME target since its token is set as a candidate. 173 imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); 174 assertEquals(appWin2, imeTarget); 175 } 176 177 /** 178 * This tests stack movement between displays and proper stack's, task's and app token's display 179 * container references updates. 180 */ 181 @Test 182 public void testMoveStackBetweenDisplays() throws Exception { 183 // Create a second display. 184 final DisplayContent dc = createNewDisplay(); 185 186 // Add stack with activity. 187 final TaskStack stack = createTaskStackOnDisplay(dc); 188 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId()); 189 assertEquals(dc, stack.getParent().getParent()); 190 assertEquals(dc, stack.getDisplayContent()); 191 192 final Task task = createTaskInStack(stack, 0 /* userId */); 193 final TestAppWindowToken token = new TestAppWindowToken(dc); 194 task.addChild(token, 0); 195 assertEquals(dc, task.getDisplayContent()); 196 assertEquals(dc, token.getDisplayContent()); 197 198 // Move stack to first display. 199 sDisplayContent.moveStackToDisplay(stack); 200 assertEquals(sDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId()); 201 assertEquals(sDisplayContent, stack.getParent().getParent()); 202 assertEquals(sDisplayContent, stack.getDisplayContent()); 203 assertEquals(sDisplayContent, task.getDisplayContent()); 204 assertEquals(sDisplayContent, token.getDisplayContent()); 205 } 206 207 /** 208 * This tests override configuration updates for display content. 209 */ 210 @Test 211 public void testDisplayOverrideConfigUpdate() throws Exception { 212 final int displayId = sDisplayContent.getDisplayId(); 213 final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration(); 214 215 // Create new, slightly changed override configuration and apply it to the display. 216 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig); 217 newOverrideConfig.densityDpi += 120; 218 newOverrideConfig.fontScale += 0.3; 219 220 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId); 221 222 // Check that override config is applied. 223 assertEquals(newOverrideConfig, sDisplayContent.getOverrideConfiguration()); 224 } 225 226 /** 227 * This tests global configuration updates when default display config is updated. 228 */ 229 @Test 230 public void testDefaultDisplayOverrideConfigUpdate() throws Exception { 231 final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration(); 232 233 // Create new, slightly changed override configuration and apply it to the display. 234 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig); 235 newOverrideConfig.densityDpi += 120; 236 newOverrideConfig.fontScale += 0.3; 237 238 sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY); 239 240 // Check that global configuration is updated, as we've updated default display's config. 241 Configuration globalConfig = sWm.mRoot.getConfiguration(); 242 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi); 243 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */); 244 245 // Return back to original values. 246 sWm.setNewDisplayOverrideConfiguration(currentOverrideConfig, DEFAULT_DISPLAY); 247 globalConfig = sWm.mRoot.getConfiguration(); 248 assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi); 249 assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */); 250 } 251 252 private void assertForAllWindowsOrder(List<WindowState> expectedWindows) { 253 final LinkedList<WindowState> actualWindows = new LinkedList(); 254 255 // Test forward traversal. 256 sDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */); 257 assertEquals(expectedWindows.size(), actualWindows.size()); 258 for (WindowState w : expectedWindows) { 259 assertEquals(w, actualWindows.pollFirst()); 260 } 261 assertTrue(actualWindows.isEmpty()); 262 263 // Test backward traversal. 264 sDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */); 265 assertEquals(expectedWindows.size(), actualWindows.size()); 266 for (WindowState w : expectedWindows) { 267 assertEquals(w, actualWindows.pollLast()); 268 } 269 assertTrue(actualWindows.isEmpty()); 270 } 271} 272