blob: f4da4b338cef508eaabbc6d766898823f55c37b5 [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
Wale Ogunwale68278562017-09-23 17:13:55 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Kazuki Takise048e2662018-06-27 17:05:11 +090020import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
21import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale68278562017-09-23 17:13:55 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Andrii Kulian92c9a942017-10-10 00:41:41 -070023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020027import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
28import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010029import static android.view.DisplayCutout.fromBoundingRect;
Wale Ogunwale34247952017-02-19 11:57:53 -080030import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
31import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
32import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070033import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080034import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Brett Chabota26eda92018-07-23 13:08:30 -070035
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;
Adrian Roos5251b1d2018-03-23 18:57:43 +010043import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080044import static org.junit.Assert.assertTrue;
Riddle Hsu654a6f92018-07-13 22:59:36 +080045import static org.mockito.Mockito.doNothing;
46import static org.mockito.Mockito.spy;
Andrii Kulianf0379de2018-03-14 16:24:07 -070047import static org.mockito.Mockito.times;
48import static org.mockito.Mockito.verify;
Wale Ogunwale34247952017-02-19 11:57:53 -080049
Andrii Kulian92c9a942017-10-10 00:41:41 -070050import android.annotation.SuppressLint;
Andrii Kuliand68501e2017-01-10 22:57:27 -080051import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010052import android.graphics.Rect;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070053import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070054import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070055import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010056import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080057import android.view.Gravity;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070058import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010059import android.view.Surface;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070060
Brett Chabota26eda92018-07-23 13:08:30 -070061import androidx.test.filters.FlakyTest;
62import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070063
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010064import com.android.server.wm.utils.WmDisplayCutout;
65
Brett Chabota26eda92018-07-23 13:08:30 -070066import org.junit.Test;
Brett Chabota26eda92018-07-23 13:08:30 -070067
Adrian Roos0f9368c2018-04-08 10:59:08 -070068import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080069import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070070import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080071import java.util.LinkedList;
72import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070073
74/**
75 * Tests for the {@link DisplayContent} class.
76 *
77 * Build/Install/Run:
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070078 * atest FrameworksServicesTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070079 */
80@SmallTest
81@Presubmit
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080082public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070083
84 @Test
Adrian Roos0f9368c2018-04-08 10:59:08 -070085 @FlakyTest(bugId = 77772044)
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070086 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -080087 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070088 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070089 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
90 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -080091 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070092
Wale Ogunwale34247952017-02-19 11:57:53 -080093 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -070094 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -080095 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -070096 mChildAppWindowBelow,
97 mAppWindow,
98 mChildAppWindowAbove,
99 mDockedDividerWindow,
100 mStatusBarWindow,
101 mNavBarWindow,
102 mImeWindow,
103 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800104 }
105
106 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700107 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800108 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700109 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800110
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700111 mWm.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800112
Wale Ogunwale34247952017-02-19 11:57:53 -0800113 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700114 mWallpaperWindow,
115 mChildAppWindowBelow,
116 mAppWindow,
117 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800118 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700119 mImeWindow,
120 mImeDialogWindow,
121 mDockedDividerWindow,
122 mStatusBarWindow,
123 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800124 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800125
Wale Ogunwale34247952017-02-19 11:57:53 -0800126 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700127 public void testForAllWindows_WithChildWindowImeTarget() {
128 mWm.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800129
Wale Ogunwale34247952017-02-19 11:57:53 -0800130 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700131 mWallpaperWindow,
132 mChildAppWindowBelow,
133 mAppWindow,
134 mChildAppWindowAbove,
135 mImeWindow,
136 mImeDialogWindow,
137 mDockedDividerWindow,
138 mStatusBarWindow,
139 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700140 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800141
142 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700143 public void testForAllWindows_WithStatusBarImeTarget() {
144 mWm.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800145
Wale Ogunwale34247952017-02-19 11:57:53 -0800146 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700147 mWallpaperWindow,
148 mChildAppWindowBelow,
149 mAppWindow,
150 mChildAppWindowAbove,
151 mDockedDividerWindow,
152 mStatusBarWindow,
153 mImeWindow,
154 mImeDialogWindow,
155 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800156 }
157
158 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700159 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800160 // This window is set-up to be z-ordered between some windows that go in the same token like
161 // the nav bar and status bar.
162 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700163 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800164
Wale Ogunwale34247952017-02-19 11:57:53 -0800165 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700166 mWallpaperWindow,
167 mChildAppWindowBelow,
168 mAppWindow,
169 mChildAppWindowAbove,
170 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700172 mStatusBarWindow,
173 mNavBarWindow,
174 mImeWindow,
175 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800176 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800177
Wale Ogunwale34247952017-02-19 11:57:53 -0800178 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700179 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800180 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700181 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800182 appWin.setHasSurface(true);
183 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700184 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800185 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800186 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800187
Wale Ogunwale34247952017-02-19 11:57:53 -0800188 // Verify that an child window can be an ime target.
189 final WindowState childWin = createWindow(appWin,
190 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
191 childWin.setHasSurface(true);
192 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700193 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800194 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800195 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800196
Andrii Kuliand68501e2017-01-10 22:57:27 -0800197 /**
198 * This tests stack movement between displays and proper stack's, task's and app token's display
199 * container references updates.
200 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800201 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700202 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800203 // Create a second display.
204 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800205
206 // Add stack with activity.
207 final TaskStack stack = createTaskStackOnDisplay(dc);
208 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
209 assertEquals(dc, stack.getParent().getParent());
210 assertEquals(dc, stack.getDisplayContent());
211
212 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800213 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
214 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800215 task.addChild(token, 0);
216 assertEquals(dc, task.getDisplayContent());
217 assertEquals(dc, token.getDisplayContent());
218
219 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700220 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
221 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
222 assertEquals(mDisplayContent, stack.getParent().getParent());
223 assertEquals(mDisplayContent, stack.getDisplayContent());
224 assertEquals(mDisplayContent, task.getDisplayContent());
225 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800226 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800227
228 /**
229 * This tests override configuration updates for display content.
230 */
231 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700232 public void testDisplayOverrideConfigUpdate() {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700233 final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800234
235 // Create new, slightly changed override configuration and apply it to the display.
236 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
237 newOverrideConfig.densityDpi += 120;
238 newOverrideConfig.fontScale += 0.3;
239
Evan Roskye747c3e2018-10-30 20:06:41 -0700240 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800241
242 // Check that override config is applied.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700243 assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800244 }
245
246 /**
247 * This tests global configuration updates when default display config is updated.
248 */
249 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700250 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700251 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
252 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800253
254 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700255 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800256 newOverrideConfig.densityDpi += 120;
257 newOverrideConfig.fontScale += 0.3;
258
Evan Roskye747c3e2018-10-30 20:06:41 -0700259 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800260
261 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700262 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800263 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
264 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800265
266 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700267 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700268 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700269 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
270 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800271 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800272
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700273 /**
274 * Tests tapping on a stack in different display results in window gaining focus.
275 */
276 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700277 public void testInputEventBringsCorrectDisplayInFocus() {
278 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700279 // Create a second display
280 final DisplayContent dc1 = createNewDisplay();
281
282 // Add stack with activity.
283 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
284 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
285 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800286 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700287 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800288 dc0.configureDisplayPolicy();
289 assertNotNull(dc0.mTapDetector);
290
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700291 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
292 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
293 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800294 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700295 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800296 dc1.configureDisplayPolicy();
297 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700298
Arthur Hungbe5ce212018-09-13 18:41:56 +0800299 // tap on primary display.
300 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700301 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700302 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800303 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700304
Arthur Hungbe5ce212018-09-13 18:41:56 +0800305 // Tap on secondary display.
306 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700307 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700308 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800309 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700310 }
311
David Stevens46939562017-03-24 13:04:00 -0700312 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700313 public void testFocusedWindowMultipleDisplays() {
Andrii Kulian0214ed92017-05-16 13:44:05 -0700314 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700315 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700316 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800317 updateFocusedWindow();
318 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700319 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700320
321 // Check that a new display doesn't affect focus
322 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800323 updateFocusedWindow();
324 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700325 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700326
327 // Add a window to the second display, and it should be focused
328 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800329 updateFocusedWindow();
330 assertTrue(window1.isFocused());
331 assertTrue(window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700332 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700333
334 // Move the first window to the to including parents, and make sure focus is updated
335 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800336 updateFocusedWindow();
337 assertTrue(window1.isFocused());
338 assertTrue(window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Adrian Roos4163d622018-05-22 16:56:35 +0200340 }
341
Bryce Lee27cec322017-03-21 09:41:37 -0700342 /**
343 * This tests setting the maximum ui width on a display.
344 */
345 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700346 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800347 // Prevent base display metrics for test from being updated to the value of real display.
348 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700349 final int baseWidth = 1440;
350 final int baseHeight = 2560;
351 final int baseDensity = 300;
352
Riddle Hsu654a6f92018-07-13 22:59:36 +0800353 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700354
355 final int maxWidth = 300;
356 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
357 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
358
Riddle Hsu654a6f92018-07-13 22:59:36 +0800359 displayContent.setMaxUiWidth(maxWidth);
360 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700361
362 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800363 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
364 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700365
366 final int smallerWidth = 200;
367 final int smallerHeight = 400;
368 final int smallerDensity = 100;
369
370 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800371 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
372 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700373
374 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800375 displayContent.setMaxUiWidth(maxWidth);
376 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700377 }
378
Bryce Lee48f4b572017-04-10 10:54:15 -0700379 /**
Kazuki Takise148d00a2018-05-31 15:32:19 +0900380 * This test enforces that alwaysOnTop stack is placed at proper position.
Bryce Lee48f4b572017-04-10 10:54:15 -0700381 */
382 @Test
Kazuki Takise148d00a2018-05-31 15:32:19 +0900383 public void testAlwaysOnTopStackLocation() {
Kazuki Takise048e2662018-06-27 17:05:11 +0900384 final TaskStack alwaysOnTopStack = createStackControllerOnStackOnDisplay(
385 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
Kazuki Takise4e7e7892018-06-19 13:55:23 +0900386 final Task task = createTaskInStack(alwaysOnTopStack, 0 /* userId */);
Kazuki Takise148d00a2018-05-31 15:32:19 +0900387 alwaysOnTopStack.setAlwaysOnTop(true);
Riddle Hsu57831b52018-07-27 00:31:48 +0800388 mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack,
389 false /* includingParents */);
Kazuki Takise148d00a2018-05-31 15:32:19 +0900390 assertTrue(alwaysOnTopStack.isAlwaysOnTop());
Kazuki Takise4e7e7892018-06-19 13:55:23 +0900391 // Ensure always on top state is synced to the children of the stack.
392 assertTrue(alwaysOnTopStack.getTopChild().isAlwaysOnTop());
Kazuki Takise148d00a2018-05-31 15:32:19 +0900393 assertEquals(alwaysOnTopStack, mDisplayContent.getTopStack());
394
Wale Ogunwale61911492017-10-11 08:50:50 -0700395 final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
396 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
Wale Ogunwale61911492017-10-11 08:50:50 -0700397 assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
398 assertEquals(pinnedStack, mDisplayContent.getTopStack());
Kazuki Takise148d00a2018-05-31 15:32:19 +0900399
Kazuki Takise048e2662018-06-27 17:05:11 +0900400 final TaskStack anotherAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
401 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
Kazuki Takise148d00a2018-05-31 15:32:19 +0900402 anotherAlwaysOnTopStack.setAlwaysOnTop(true);
Riddle Hsu57831b52018-07-27 00:31:48 +0800403 mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
404 false /* includingParents */);
Kazuki Takise148d00a2018-05-31 15:32:19 +0900405 assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
406 int topPosition = mDisplayContent.getStacks().size() - 1;
407 // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
408 // existing alwaysOnTop stack.
409 assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
410
Kazuki Takise048e2662018-06-27 17:05:11 +0900411 final TaskStack nonAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
412 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
Kazuki Takise148d00a2018-05-31 15:32:19 +0900413 assertEquals(mDisplayContent, nonAlwaysOnTopStack.getDisplayContent());
414 topPosition = mDisplayContent.getStacks().size() - 1;
415 // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
416 // existing other non-alwaysOnTop stacks.
417 assertEquals(nonAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 3));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900418
419 anotherAlwaysOnTopStack.setAlwaysOnTop(false);
Riddle Hsu57831b52018-07-27 00:31:48 +0800420 mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
421 false /* includingParents */);
Kazuki Takisef85197b2018-06-18 18:18:36 +0900422 assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
Kazuki Takisef85197b2018-06-18 18:18:36 +0900423 // Ensure, when always on top is turned off for a stack, the stack is put just below all
424 // other always on top stacks.
425 assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
Kazuki Takise048e2662018-06-27 17:05:11 +0900426 anotherAlwaysOnTopStack.setAlwaysOnTop(true);
427
428 // Ensure always on top state changes properly when windowing mode changes.
429 anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
430 assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
431 assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
432 anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
433 assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
434 assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
Bryce Lee48f4b572017-04-10 10:54:15 -0700435 }
436
Andrii Kulian92c9a942017-10-10 00:41:41 -0700437 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700438 public void testDisplayCutout_rot0() {
439 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100440 final DisplayContent dc = createNewDisplay();
441 dc.mInitialDisplayWidth = 200;
442 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100443 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100444 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200445 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100446 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100447
448 dc.mInitialDisplayCutout = cutout;
449 dc.setRotation(Surface.ROTATION_0);
450 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
451
452 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
453 }
454 }
455
456 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700457 public void testDisplayCutout_rot90() {
458 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800459 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
460 // if the device has no cutout).
461 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
462 // Rotation may use real display info to compute bound, so here also uses the
463 // same width and height.
464 final int displayWidth = dc.mInitialDisplayWidth;
465 final int displayHeight = dc.mInitialDisplayHeight;
466 final int cutoutWidth = 40;
467 final int cutoutHeight = 10;
468 final int left = (displayWidth - cutoutWidth) / 2;
469 final int top = 0;
470 final int right = (displayWidth + cutoutWidth) / 2;
471 final int bottom = cutoutHeight;
472
473 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100474 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700475 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
476 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800477 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100478
479 dc.mInitialDisplayCutout = cutout;
480 dc.setRotation(Surface.ROTATION_90);
481 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
482
Riddle Hsu654a6f92018-07-13 22:59:36 +0800483 // ----o---------- -------------
484 // | | | | |
485 // | ------o | o---
486 // | | | |
487 // | | -> | |
488 // | | ---o
489 // | | |
490 // | | -------------
491 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100492 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200493 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800494 .computeSafeInsets(displayHeight, displayWidth)
495 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100496 }
497 }
498
499 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700500 public void testLayoutSeq_assignedDuringLayout() {
501 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100502
503 final DisplayContent dc = createNewDisplay();
504 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
505
506 dc.setLayoutNeeded();
507 dc.performLayout(true /* initial */, false /* updateImeWindows */);
508
509 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
510 }
511 }
512
513 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700514 @SuppressLint("InlinedApi")
515 public void testOrientationDefinedByKeyguard() {
516 final DisplayContent dc = createNewDisplay();
517 // Create a window that requests landscape orientation. It will define device orientation
518 // by default.
519 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
520 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
521
522 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
523 keyguard.mHasSurface = true;
524 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
525
526 assertEquals("Screen orientation must be defined by the app window by default",
527 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
528
529 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
530 assertEquals("Visible keyguard must influence device orientation",
531 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
532
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700533 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700534 assertEquals("Keyguard that is going away must not influence device orientation",
535 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
536 }
537
Andrii Kulianf0379de2018-03-14 16:24:07 -0700538 @Test
539 public void testDisableDisplayInfoOverrideFromWindowManager() {
540 final DisplayContent dc = createNewDisplay();
541
542 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700543 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700544
545 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700546 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700547 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
548 }
549
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800550 @Test
551 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
552 final DisplayContent portraitDisplay = createNewDisplay();
553 portraitDisplay.mInitialDisplayHeight = 2000;
554 portraitDisplay.mInitialDisplayWidth = 1000;
555
556 portraitDisplay.setRotation(Surface.ROTATION_0);
557 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
558 portraitDisplay.setRotation(Surface.ROTATION_90);
559 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
560
561 final DisplayContent landscapeDisplay = createNewDisplay();
562 landscapeDisplay.mInitialDisplayHeight = 1000;
563 landscapeDisplay.mInitialDisplayWidth = 2000;
564
565 landscapeDisplay.setRotation(Surface.ROTATION_0);
566 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
567 landscapeDisplay.setRotation(Surface.ROTATION_90);
568 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
569 }
570
571 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700572 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800573 }
574
Bryce Lee27cec322017-03-21 09:41:37 -0700575 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
576 int expectedBaseHeight, int expectedBaseDensity) {
577 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
578 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
579 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
580 }
581
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800582 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700583 synchronized (mWm.mGlobalLock) {
584 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800585 }
586 }
587
Riddle Hsu654a6f92018-07-13 22:59:36 +0800588 /**
589 * Create DisplayContent that does not update display base/initial values from device to keep
590 * the values set by test.
591 */
592 private DisplayContent createDisplayNoUpdateDisplayInfo() {
593 final DisplayContent displayContent = spy(createNewDisplay());
594 doNothing().when(displayContent).updateDisplayInfo();
595 return displayContent;
596 }
597
Adrian Roos0f9368c2018-04-08 10:59:08 -0700598 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
599 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800600
601 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700602 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700603 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
604
605 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800606
607 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700608 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700609 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
610 }
611
612 private static List<WindowState> reverseList(List<WindowState> list) {
613 final ArrayList<WindowState> result = new ArrayList<>(list);
614 Collections.reverse(result);
615 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800616 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700617
Arthur Hungbe5ce212018-09-13 18:41:56 +0800618 private void tapOnDisplay(final DisplayContent dc) {
619 final DisplayMetrics dm = dc.getDisplayMetrics();
620 final float x = dm.widthPixels / 2;
621 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700622 final long downTime = SystemClock.uptimeMillis();
623 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800624 // sending ACTION_DOWN
625 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700626 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800627 downTime,
628 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700629 x,
630 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800631 0 /*metaState*/);
632 downEvent.setDisplayId(dc.getDisplayId());
633 dc.mTapDetector.onPointerEvent(downEvent);
634
635 // sending ACTION_UP
636 final MotionEvent upEvent = MotionEvent.obtain(
637 downTime,
638 eventTime,
639 MotionEvent.ACTION_UP,
640 x,
641 y,
642 0 /*metaState*/);
643 upEvent.setDisplayId(dc.getDisplayId());
644 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700645 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700646}