blob: 7c83ecc22c9015b7241f6bd44c39a73893261455 [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
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
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Andrii Kulian92c9a942017-10-10 00:41:41 -070019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwale34247952017-02-19 11:57:53 -080022import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020023import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
24import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010025import static android.view.DisplayCutout.fromBoundingRect;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
27import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
28import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070029import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080030import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Brett Chabota26eda92018-07-23 13:08:30 -070031
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090032import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
33import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
34import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
35import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070036import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080037import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080038
Adrian Roos5251b1d2018-03-23 18:57:43 +010039import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080040import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070041import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080042import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080043import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010044import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080045import static org.junit.Assert.assertTrue;
46
Andrii Kulian92c9a942017-10-10 00:41:41 -070047import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080048import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010049import android.graphics.Rect;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070050import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070051import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070052import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010053import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080054import android.view.Gravity;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070055import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010056import android.view.Surface;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070057
Brett Chabota26eda92018-07-23 13:08:30 -070058import androidx.test.filters.FlakyTest;
59import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070060
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010061import com.android.server.wm.utils.WmDisplayCutout;
62
Brett Chabota26eda92018-07-23 13:08:30 -070063import org.junit.Test;
Brett Chabota26eda92018-07-23 13:08:30 -070064
Adrian Roos0f9368c2018-04-08 10:59:08 -070065import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080066import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070067import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080068import java.util.LinkedList;
69import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070070
71/**
72 * Tests for the {@link DisplayContent} class.
73 *
74 * Build/Install/Run:
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070075 * atest FrameworksServicesTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070076 */
77@SmallTest
78@Presubmit
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080079public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070080
81 @Test
Adrian Roos0f9368c2018-04-08 10:59:08 -070082 @FlakyTest(bugId = 77772044)
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070083 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080084 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070085 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070086 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
87 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080088 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070089
Wale Ogunwale34247952017-02-19 11:57:53 -080090 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070091 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080092 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070093 mChildAppWindowBelow,
94 mAppWindow,
95 mChildAppWindowAbove,
96 mDockedDividerWindow,
97 mStatusBarWindow,
98 mNavBarWindow,
99 mImeWindow,
100 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800101 }
102
103 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700104 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800105 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700106 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800107
lumarkff0ab692018-11-05 20:32:30 +0800108 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800109
Wale Ogunwale34247952017-02-19 11:57:53 -0800110 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700111 mWallpaperWindow,
112 mChildAppWindowBelow,
113 mAppWindow,
114 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800115 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700116 mImeWindow,
117 mImeDialogWindow,
118 mDockedDividerWindow,
119 mStatusBarWindow,
120 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800121 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800122
Wale Ogunwale34247952017-02-19 11:57:53 -0800123 @Test
lumarkff0ab692018-11-05 20:32:30 +0800124 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
125 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800126
Wale Ogunwale34247952017-02-19 11:57:53 -0800127 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700128 mWallpaperWindow,
129 mChildAppWindowBelow,
130 mAppWindow,
131 mChildAppWindowAbove,
132 mImeWindow,
133 mImeDialogWindow,
134 mDockedDividerWindow,
135 mStatusBarWindow,
136 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700137 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800138
139 @Test
lumarkff0ab692018-11-05 20:32:30 +0800140 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
141 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800142
Wale Ogunwale34247952017-02-19 11:57:53 -0800143 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700144 mWallpaperWindow,
145 mChildAppWindowBelow,
146 mAppWindow,
147 mChildAppWindowAbove,
148 mDockedDividerWindow,
149 mStatusBarWindow,
150 mImeWindow,
151 mImeDialogWindow,
152 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800153 }
154
155 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700156 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800157 // This window is set-up to be z-ordered between some windows that go in the same token like
158 // the nav bar and status bar.
159 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700160 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800161
Wale Ogunwale34247952017-02-19 11:57:53 -0800162 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700163 mWallpaperWindow,
164 mChildAppWindowBelow,
165 mAppWindow,
166 mChildAppWindowAbove,
167 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800168 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700169 mStatusBarWindow,
170 mNavBarWindow,
171 mImeWindow,
172 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800173 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800174
Wale Ogunwale34247952017-02-19 11:57:53 -0800175 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700176 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800177 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700178 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800179 appWin.setHasSurface(true);
180 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700181 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800182 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800183 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800184
Wale Ogunwale34247952017-02-19 11:57:53 -0800185 // Verify that an child window can be an ime target.
186 final WindowState childWin = createWindow(appWin,
187 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
188 childWin.setHasSurface(true);
189 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700190 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800191 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800192 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800193
Andrii Kuliand68501e2017-01-10 22:57:27 -0800194 /**
195 * This tests stack movement between displays and proper stack's, task's and app token's display
196 * container references updates.
197 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800198 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700199 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800200 // Create a second display.
201 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800202
203 // Add stack with activity.
204 final TaskStack stack = createTaskStackOnDisplay(dc);
205 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
206 assertEquals(dc, stack.getParent().getParent());
207 assertEquals(dc, stack.getDisplayContent());
208
209 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800210 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
211 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800212 task.addChild(token, 0);
213 assertEquals(dc, task.getDisplayContent());
214 assertEquals(dc, token.getDisplayContent());
215
216 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700217 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
218 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
219 assertEquals(mDisplayContent, stack.getParent().getParent());
220 assertEquals(mDisplayContent, stack.getDisplayContent());
221 assertEquals(mDisplayContent, task.getDisplayContent());
222 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800223 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800224
225 /**
226 * This tests override configuration updates for display content.
227 */
228 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700229 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700230 final Configuration currentOverrideConfig =
231 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800232
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
Evan Roskye747c3e2018-10-30 20:06:41 -0700238 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800239
240 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700241 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800242 }
243
244 /**
245 * This tests global configuration updates when default display config is updated.
246 */
247 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700248 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700249 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
250 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800251
252 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700253 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800254 newOverrideConfig.densityDpi += 120;
255 newOverrideConfig.fontScale += 0.3;
256
Evan Roskye747c3e2018-10-30 20:06:41 -0700257 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800258
259 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700260 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800261 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
262 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800263
264 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700265 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700266 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700267 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
268 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800269 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800270
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700271 /**
272 * Tests tapping on a stack in different display results in window gaining focus.
273 */
274 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700275 public void testInputEventBringsCorrectDisplayInFocus() {
276 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700277 // Create a second display
278 final DisplayContent dc1 = createNewDisplay();
279
280 // Add stack with activity.
281 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
282 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
283 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800284 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700285 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800286 dc0.configureDisplayPolicy();
287 assertNotNull(dc0.mTapDetector);
288
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700289 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
290 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
291 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800292 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700293 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800294 dc1.configureDisplayPolicy();
295 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700296
Arthur Hungbe5ce212018-09-13 18:41:56 +0800297 // tap on primary display.
298 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700299 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700300 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800301 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700302
Arthur Hungbe5ce212018-09-13 18:41:56 +0800303 // Tap on secondary display.
304 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700305 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700306 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800307 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700308 }
309
David Stevens46939562017-03-24 13:04:00 -0700310 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700311 public void testFocusedWindowMultipleDisplays() {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700312 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700313 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700314 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800315 updateFocusedWindow();
316 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700317 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700318
319 // Check that a new display doesn't affect focus
320 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800321 updateFocusedWindow();
322 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700323 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700324
325 // Add a window to the second display, and it should be focused
326 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800327 updateFocusedWindow();
328 assertTrue(window1.isFocused());
329 assertTrue(window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700330 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700331
332 // Move the first window to the to including parents, and make sure focus is updated
333 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800334 updateFocusedWindow();
335 assertTrue(window1.isFocused());
336 assertTrue(window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700337 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Adrian Roos4163d622018-05-22 16:56:35 +0200338 }
339
Bryce Lee27cec322017-03-21 09:41:37 -0700340 /**
341 * This tests setting the maximum ui width on a display.
342 */
343 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700344 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800345 // Prevent base display metrics for test from being updated to the value of real display.
346 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700347 final int baseWidth = 1440;
348 final int baseHeight = 2560;
349 final int baseDensity = 300;
350
Riddle Hsu654a6f92018-07-13 22:59:36 +0800351 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700352
353 final int maxWidth = 300;
354 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
355 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
356
Riddle Hsu654a6f92018-07-13 22:59:36 +0800357 displayContent.setMaxUiWidth(maxWidth);
358 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700359
360 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800361 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
362 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700363
364 final int smallerWidth = 200;
365 final int smallerHeight = 400;
366 final int smallerDensity = 100;
367
368 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800369 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
370 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700371
372 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800373 displayContent.setMaxUiWidth(maxWidth);
374 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700375 }
376
Andrii Kulian92c9a942017-10-10 00:41:41 -0700377 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700378 public void testDisplayCutout_rot0() {
379 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100380 final DisplayContent dc = createNewDisplay();
381 dc.mInitialDisplayWidth = 200;
382 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100383 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100384 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200385 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100386 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100387
388 dc.mInitialDisplayCutout = cutout;
389 dc.setRotation(Surface.ROTATION_0);
390 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
391
392 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
393 }
394 }
395
396 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700397 public void testDisplayCutout_rot90() {
398 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800399 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
400 // if the device has no cutout).
401 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
402 // Rotation may use real display info to compute bound, so here also uses the
403 // same width and height.
404 final int displayWidth = dc.mInitialDisplayWidth;
405 final int displayHeight = dc.mInitialDisplayHeight;
406 final int cutoutWidth = 40;
407 final int cutoutHeight = 10;
408 final int left = (displayWidth - cutoutWidth) / 2;
409 final int top = 0;
410 final int right = (displayWidth + cutoutWidth) / 2;
411 final int bottom = cutoutHeight;
412
413 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100414 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700415 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
416 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800417 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100418
419 dc.mInitialDisplayCutout = cutout;
420 dc.setRotation(Surface.ROTATION_90);
421 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
422
Riddle Hsu654a6f92018-07-13 22:59:36 +0800423 // ----o---------- -------------
424 // | | | | |
425 // | ------o | o---
426 // | | | |
427 // | | -> | |
428 // | | ---o
429 // | | |
430 // | | -------------
431 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100432 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200433 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800434 .computeSafeInsets(displayHeight, displayWidth)
435 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100436 }
437 }
438
439 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700440 public void testLayoutSeq_assignedDuringLayout() {
441 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100442
443 final DisplayContent dc = createNewDisplay();
444 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
445
446 dc.setLayoutNeeded();
447 dc.performLayout(true /* initial */, false /* updateImeWindows */);
448
449 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
450 }
451 }
452
453 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700454 @SuppressLint("InlinedApi")
455 public void testOrientationDefinedByKeyguard() {
456 final DisplayContent dc = createNewDisplay();
457 // Create a window that requests landscape orientation. It will define device orientation
458 // by default.
459 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
460 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
461
462 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
463 keyguard.mHasSurface = true;
464 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
465
466 assertEquals("Screen orientation must be defined by the app window by default",
467 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
468
469 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
470 assertEquals("Visible keyguard must influence device orientation",
471 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
472
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700473 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700474 assertEquals("Keyguard that is going away must not influence device orientation",
475 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
476 }
477
Andrii Kulianf0379de2018-03-14 16:24:07 -0700478 @Test
479 public void testDisableDisplayInfoOverrideFromWindowManager() {
480 final DisplayContent dc = createNewDisplay();
481
482 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700483 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700484
485 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700486 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700487 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
488 }
489
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800490 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800491 public void testClearLastFocusWhenReparentingFocusedWindow() {
492 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
493 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
494 defaultDisplay, "window");
495 defaultDisplay.mLastFocus = window;
496 mDisplayContent.mCurrentFocus = window;
497 mDisplayContent.reParentWindowToken(window.mToken);
498
499 assertNull(defaultDisplay.mLastFocus);
500 }
501
502 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800503 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
504 final DisplayContent portraitDisplay = createNewDisplay();
505 portraitDisplay.mInitialDisplayHeight = 2000;
506 portraitDisplay.mInitialDisplayWidth = 1000;
507
508 portraitDisplay.setRotation(Surface.ROTATION_0);
509 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
510 portraitDisplay.setRotation(Surface.ROTATION_90);
511 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
512
513 final DisplayContent landscapeDisplay = createNewDisplay();
514 landscapeDisplay.mInitialDisplayHeight = 1000;
515 landscapeDisplay.mInitialDisplayWidth = 2000;
516
517 landscapeDisplay.setRotation(Surface.ROTATION_0);
518 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
519 landscapeDisplay.setRotation(Surface.ROTATION_90);
520 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
521 }
522
lumarkff0ab692018-11-05 20:32:30 +0800523 @Test
524 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
525 final DisplayContent newDisplay = createNewDisplay();
526
527 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
528 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
529 appWin.setHasSurface(true);
530 appWin1.setHasSurface(true);
531
532 // Set current input method window on default display, make sure the input method target
533 // is appWin & null on the other display.
534 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
535 newDisplay.setInputMethodWindowLocked(null);
536 assertTrue("appWin should be IME target window",
537 appWin.equals(mDisplayContent.mInputMethodTarget));
538 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
539
540 // Switch input method window on new display & make sure the input method target also
541 // switched as expected.
542 newDisplay.setInputMethodWindowLocked(mImeWindow);
543 mDisplayContent.setInputMethodWindowLocked(null);
544 assertTrue("appWin1 should be IME target window",
545 appWin1.equals(newDisplay.mInputMethodTarget));
546 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
547 }
548
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800549 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700550 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800551 }
552
Bryce Lee27cec322017-03-21 09:41:37 -0700553 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
554 int expectedBaseHeight, int expectedBaseDensity) {
555 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
556 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
557 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
558 }
559
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800560 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700561 synchronized (mWm.mGlobalLock) {
562 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800563 }
564 }
565
Riddle Hsu654a6f92018-07-13 22:59:36 +0800566 /**
567 * Create DisplayContent that does not update display base/initial values from device to keep
568 * the values set by test.
569 */
570 private DisplayContent createDisplayNoUpdateDisplayInfo() {
571 final DisplayContent displayContent = spy(createNewDisplay());
572 doNothing().when(displayContent).updateDisplayInfo();
573 return displayContent;
574 }
575
Adrian Roos0f9368c2018-04-08 10:59:08 -0700576 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
577 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800578
579 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700580 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700581 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
582
583 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800584
585 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700586 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700587 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
588 }
589
590 private static List<WindowState> reverseList(List<WindowState> list) {
591 final ArrayList<WindowState> result = new ArrayList<>(list);
592 Collections.reverse(result);
593 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800594 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700595
Arthur Hungbe5ce212018-09-13 18:41:56 +0800596 private void tapOnDisplay(final DisplayContent dc) {
597 final DisplayMetrics dm = dc.getDisplayMetrics();
598 final float x = dm.widthPixels / 2;
599 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700600 final long downTime = SystemClock.uptimeMillis();
601 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800602 // sending ACTION_DOWN
603 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700604 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800605 downTime,
606 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700607 x,
608 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800609 0 /*metaState*/);
610 downEvent.setDisplayId(dc.getDisplayId());
611 dc.mTapDetector.onPointerEvent(downEvent);
612
613 // sending ACTION_UP
614 final MotionEvent upEvent = MotionEvent.obtain(
615 downTime,
616 eventTime,
617 MotionEvent.ACTION_UP,
618 x,
619 y,
620 0 /*metaState*/);
621 upEvent.setDisplayId(dc.getDisplayId());
622 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700623 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700624}