blob: 51dac6fdd1eb692733b5a2307f873ebb29694084 [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;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080022import static android.os.Build.VERSION_CODES.P;
23import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080024import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020025import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
26import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010027import static android.view.DisplayCutout.fromBoundingRect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010028import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
29import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
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
Garfield Tan90b04282018-12-11 14:04:42 -080036import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
37import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090038import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Garfield Tan90b04282018-12-11 14:04:42 -080039import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
40import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
41import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
42import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090043import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
44import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
45import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070046import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080047import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080048
Adrian Roos5251b1d2018-03-23 18:57:43 +010049import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080050import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070051import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080052import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080053import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010054import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080055import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080056import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080057
Andrii Kulian92c9a942017-10-10 00:41:41 -070058import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080059import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080060import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010061import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010062import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050063import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070064import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070065import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070066import android.util.DisplayMetrics;
Adrian Roos4ffc8972019-02-07 20:45:11 +010067import android.util.MutableBoolean;
Adrian Roos1cf585052018-01-03 18:43:27 +010068import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080069import android.view.Gravity;
Adrian Roos4ffc8972019-02-07 20:45:11 +010070import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070071import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010072import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080073import android.view.ViewRootImpl;
74import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070075
Brett Chabota26eda92018-07-23 13:08:30 -070076import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070077
Garfield Tan90b04282018-12-11 14:04:42 -080078import com.android.dx.mockito.inline.extended.ExtendedMockito;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050079import com.android.internal.logging.MetricsLogger;
80import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010081import com.android.server.wm.utils.WmDisplayCutout;
82
Brett Chabota26eda92018-07-23 13:08:30 -070083import org.junit.Test;
Garfield Tan90b04282018-12-11 14:04:42 -080084import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050085import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070086
Adrian Roos0f9368c2018-04-08 10:59:08 -070087import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080088import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070089import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080090import java.util.LinkedList;
91import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070092
93/**
94 * Tests for the {@link DisplayContent} class.
95 *
96 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +090097 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070098 */
99@SmallTest
100@Presubmit
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800101public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700102
103 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700104 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800105 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700106 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700107 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900108 // Wait until everything in animation handler get executed to prevent the exiting window
109 // from being removed during WindowSurfacePlacer Traversal.
110 waitUntilHandlersIdle();
111
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700112 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -0800113 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700114
Wale Ogunwale34247952017-02-19 11:57:53 -0800115 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700116 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800117 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700118 mChildAppWindowBelow,
119 mAppWindow,
120 mChildAppWindowAbove,
121 mDockedDividerWindow,
122 mStatusBarWindow,
123 mNavBarWindow,
124 mImeWindow,
125 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800126 }
127
128 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700129 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800130 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700131 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800132
lumarkff0ab692018-11-05 20:32:30 +0800133 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800134
Wale Ogunwale34247952017-02-19 11:57:53 -0800135 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700136 mWallpaperWindow,
137 mChildAppWindowBelow,
138 mAppWindow,
139 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800140 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700141 mImeWindow,
142 mImeDialogWindow,
143 mDockedDividerWindow,
144 mStatusBarWindow,
145 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800146 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800147
Wale Ogunwale34247952017-02-19 11:57:53 -0800148 @Test
lumarkff0ab692018-11-05 20:32:30 +0800149 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
150 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800151
Wale Ogunwale34247952017-02-19 11:57:53 -0800152 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 mWallpaperWindow,
154 mChildAppWindowBelow,
155 mAppWindow,
156 mChildAppWindowAbove,
157 mImeWindow,
158 mImeDialogWindow,
159 mDockedDividerWindow,
160 mStatusBarWindow,
161 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700162 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800163
164 @Test
lumarkff0ab692018-11-05 20:32:30 +0800165 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
166 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800167
Wale Ogunwale34247952017-02-19 11:57:53 -0800168 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700169 mWallpaperWindow,
170 mChildAppWindowBelow,
171 mAppWindow,
172 mChildAppWindowAbove,
173 mDockedDividerWindow,
174 mStatusBarWindow,
175 mImeWindow,
176 mImeDialogWindow,
177 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800178 }
179
180 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700181 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800182 // This window is set-up to be z-ordered between some windows that go in the same token like
183 // the nav bar and status bar.
184 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700185 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800186
Wale Ogunwale34247952017-02-19 11:57:53 -0800187 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700188 mWallpaperWindow,
189 mChildAppWindowBelow,
190 mAppWindow,
191 mChildAppWindowAbove,
192 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800193 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700194 mStatusBarWindow,
195 mNavBarWindow,
196 mImeWindow,
197 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800198 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800199
Wale Ogunwale34247952017-02-19 11:57:53 -0800200 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700201 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800202 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700203 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800204 appWin.setHasSurface(true);
205 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700206 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800207 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800208 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800209
Wale Ogunwale34247952017-02-19 11:57:53 -0800210 // Verify that an child window can be an ime target.
211 final WindowState childWin = createWindow(appWin,
212 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
213 childWin.setHasSurface(true);
214 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700215 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800216 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800217 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800218
Andrii Kuliand68501e2017-01-10 22:57:27 -0800219 /**
220 * This tests stack movement between displays and proper stack's, task's and app token's display
221 * container references updates.
222 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800223 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700224 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800225 // Create a second display.
226 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800227
228 // Add stack with activity.
229 final TaskStack stack = createTaskStackOnDisplay(dc);
230 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
231 assertEquals(dc, stack.getParent().getParent());
232 assertEquals(dc, stack.getDisplayContent());
233
234 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800235 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
236 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800237 task.addChild(token, 0);
238 assertEquals(dc, task.getDisplayContent());
239 assertEquals(dc, token.getDisplayContent());
240
241 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700242 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
243 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
244 assertEquals(mDisplayContent, stack.getParent().getParent());
245 assertEquals(mDisplayContent, stack.getDisplayContent());
246 assertEquals(mDisplayContent, task.getDisplayContent());
247 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800248 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800249
250 /**
251 * This tests override configuration updates for display content.
252 */
253 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700254 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700255 final Configuration currentOverrideConfig =
256 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800257
258 // Create new, slightly changed override configuration and apply it to the display.
259 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
260 newOverrideConfig.densityDpi += 120;
261 newOverrideConfig.fontScale += 0.3;
262
Evan Roskye747c3e2018-10-30 20:06:41 -0700263 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800264
265 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700266 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800267 }
268
269 /**
270 * This tests global configuration updates when default display config is updated.
271 */
272 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700273 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700274 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
275 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800276
277 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700278 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800279 newOverrideConfig.densityDpi += 120;
280 newOverrideConfig.fontScale += 0.3;
281
Evan Roskye747c3e2018-10-30 20:06:41 -0700282 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800283
284 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700285 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800286 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
287 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800288
289 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700290 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700291 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700292 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
293 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800294 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800295
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700296 /**
297 * Tests tapping on a stack in different display results in window gaining focus.
298 */
299 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700300 public void testInputEventBringsCorrectDisplayInFocus() {
301 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700302 // Create a second display
303 final DisplayContent dc1 = createNewDisplay();
304
305 // Add stack with activity.
306 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
307 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
308 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800309 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700310 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800311 dc0.configureDisplayPolicy();
312 assertNotNull(dc0.mTapDetector);
313
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700314 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
315 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
316 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800317 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700318 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800319 dc1.configureDisplayPolicy();
320 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700321
Arthur Hungbe5ce212018-09-13 18:41:56 +0800322 // tap on primary display.
323 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700324 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700325 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800326 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700327
Arthur Hungbe5ce212018-09-13 18:41:56 +0800328 // Tap on secondary display.
329 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700330 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700331 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800332 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700333 }
334
David Stevens46939562017-03-24 13:04:00 -0700335 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700336 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800337 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
338 }
339
340 @Test
341 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
342 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
343 }
344
345 @Test
346 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
347 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
348 }
349
350 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
351 int targetSdk) {
352 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
353
Andrii Kulian0214ed92017-05-16 13:44:05 -0700354 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700355 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700356 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800357 window1.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800358 updateFocusedWindow();
359 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700360 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700361
362 // Check that a new display doesn't affect focus
363 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800364 updateFocusedWindow();
365 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700366 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700367
368 // Add a window to the second display, and it should be focused
369 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800370 window2.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800371 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800372 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800373 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700374 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700375
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800376 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700377 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800378 updateFocusedWindow();
379 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800380 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700381 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Adrian Roos4163d622018-05-22 16:56:35 +0200382 }
383
Bryce Lee27cec322017-03-21 09:41:37 -0700384 /**
385 * This tests setting the maximum ui width on a display.
386 */
387 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700388 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800389 // Prevent base display metrics for test from being updated to the value of real display.
390 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700391 final int baseWidth = 1440;
392 final int baseHeight = 2560;
393 final int baseDensity = 300;
394
Riddle Hsu654a6f92018-07-13 22:59:36 +0800395 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700396
397 final int maxWidth = 300;
398 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
399 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
400
Riddle Hsu654a6f92018-07-13 22:59:36 +0800401 displayContent.setMaxUiWidth(maxWidth);
402 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700403
404 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800405 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
406 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700407
408 final int smallerWidth = 200;
409 final int smallerHeight = 400;
410 final int smallerDensity = 100;
411
412 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800413 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
414 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700415
416 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800417 displayContent.setMaxUiWidth(maxWidth);
418 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700419 }
420
Andrii Kulian92c9a942017-10-10 00:41:41 -0700421 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700422 public void testDisplayCutout_rot0() {
423 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100424 final DisplayContent dc = createNewDisplay();
425 dc.mInitialDisplayWidth = 200;
426 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100427 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100428 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200429 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100430 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100431
432 dc.mInitialDisplayCutout = cutout;
433 dc.setRotation(Surface.ROTATION_0);
434 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
435
436 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
437 }
438 }
439
440 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700441 public void testDisplayCutout_rot90() {
442 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800443 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
444 // if the device has no cutout).
445 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
446 // Rotation may use real display info to compute bound, so here also uses the
447 // same width and height.
448 final int displayWidth = dc.mInitialDisplayWidth;
449 final int displayHeight = dc.mInitialDisplayHeight;
450 final int cutoutWidth = 40;
451 final int cutoutHeight = 10;
452 final int left = (displayWidth - cutoutWidth) / 2;
453 final int top = 0;
454 final int right = (displayWidth + cutoutWidth) / 2;
455 final int bottom = cutoutHeight;
456
457 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100458 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700459 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
460 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800461 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100462
463 dc.mInitialDisplayCutout = cutout;
464 dc.setRotation(Surface.ROTATION_90);
465 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
466
Riddle Hsu654a6f92018-07-13 22:59:36 +0800467 // ----o---------- -------------
468 // | | | | |
469 // | ------o | o---
470 // | | | |
471 // | | -> | |
472 // | | ---o
473 // | | |
474 // | | -------------
475 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100476 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200477 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800478 .computeSafeInsets(displayHeight, displayWidth)
479 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100480 }
481 }
482
483 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700484 public void testLayoutSeq_assignedDuringLayout() {
485 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100486
487 final DisplayContent dc = createNewDisplay();
488 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
489
490 dc.setLayoutNeeded();
491 dc.performLayout(true /* initial */, false /* updateImeWindows */);
492
493 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
494 }
495 }
496
497 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700498 @SuppressLint("InlinedApi")
499 public void testOrientationDefinedByKeyguard() {
500 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800501
502 // When display content is created its configuration is not yet initialized, which could
503 // cause unnecessary configuration propagation, so initialize it here.
504 final Configuration config = new Configuration();
505 dc.computeScreenConfiguration(config);
506 dc.onRequestedOverrideConfigurationChanged(config);
507
Andrii Kulian92c9a942017-10-10 00:41:41 -0700508 // Create a window that requests landscape orientation. It will define device orientation
509 // by default.
510 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
511 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
512
513 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
514 keyguard.mHasSurface = true;
515 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
516
517 assertEquals("Screen orientation must be defined by the app window by default",
518 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
519
520 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
521 assertEquals("Visible keyguard must influence device orientation",
522 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
523
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700524 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700525 assertEquals("Keyguard that is going away must not influence device orientation",
526 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
527 }
528
Andrii Kulianf0379de2018-03-14 16:24:07 -0700529 @Test
530 public void testDisableDisplayInfoOverrideFromWindowManager() {
531 final DisplayContent dc = createNewDisplay();
532
533 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700534 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700535
536 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700537 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700538 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
539 }
540
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800541 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800542 public void testClearLastFocusWhenReparentingFocusedWindow() {
543 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
544 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
545 defaultDisplay, "window");
546 defaultDisplay.mLastFocus = window;
547 mDisplayContent.mCurrentFocus = window;
548 mDisplayContent.reParentWindowToken(window.mToken);
549
550 assertNull(defaultDisplay.mLastFocus);
551 }
552
553 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800554 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
555 final DisplayContent portraitDisplay = createNewDisplay();
556 portraitDisplay.mInitialDisplayHeight = 2000;
557 portraitDisplay.mInitialDisplayWidth = 1000;
558
559 portraitDisplay.setRotation(Surface.ROTATION_0);
560 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
561 portraitDisplay.setRotation(Surface.ROTATION_90);
562 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
563
564 final DisplayContent landscapeDisplay = createNewDisplay();
565 landscapeDisplay.mInitialDisplayHeight = 1000;
566 landscapeDisplay.mInitialDisplayWidth = 2000;
567
568 landscapeDisplay.setRotation(Surface.ROTATION_0);
569 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
570 landscapeDisplay.setRotation(Surface.ROTATION_90);
571 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
572 }
573
lumarkff0ab692018-11-05 20:32:30 +0800574 @Test
575 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
576 final DisplayContent newDisplay = createNewDisplay();
577
578 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
579 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
580 appWin.setHasSurface(true);
581 appWin1.setHasSurface(true);
582
583 // Set current input method window on default display, make sure the input method target
584 // is appWin & null on the other display.
585 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
586 newDisplay.setInputMethodWindowLocked(null);
587 assertTrue("appWin should be IME target window",
588 appWin.equals(mDisplayContent.mInputMethodTarget));
589 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
590
591 // Switch input method window on new display & make sure the input method target also
592 // switched as expected.
593 newDisplay.setInputMethodWindowLocked(mImeWindow);
594 mDisplayContent.setInputMethodWindowLocked(null);
595 assertTrue("appWin1 should be IME target window",
596 appWin1.equals(newDisplay.mInputMethodTarget));
597 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
598 }
599
Garfield Tan90b04282018-12-11 14:04:42 -0800600 @Test
601 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800602 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800603 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800604 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
605 ? SCREEN_ORIENTATION_PORTRAIT
606 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800607
608 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
609 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800610 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800611
612 ActivityRecord activityRecord = mock(ActivityRecord.class);
613
614 assertTrue("Display should rotate to handle orientation request by default.",
615 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
616
617 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
618 verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
619 same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
620 final Configuration newDisplayConfig = captor.getValue();
Garfield Tan49dae102019-02-04 09:51:59 -0800621 assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800622 }
623
624 @Test
625 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800626 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800627 dc.getDisplayRotation().setFixedToUserRotation(
628 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan90b04282018-12-11 14:04:42 -0800629 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800630 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
631 ? SCREEN_ORIENTATION_PORTRAIT
632 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800633
634 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
635 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800636 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800637
638 ActivityRecord activityRecord = mock(ActivityRecord.class);
639
640 assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
641 + " user rotation.",
642 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
643 verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
644 eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
645 }
646
Tarandeep Singha6f35612019-01-11 19:50:46 -0800647 @Test
648 public void testComputeImeParent_app() throws Exception {
649 try (final InsetsModeSession session =
650 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
651 final DisplayContent dc = createNewDisplay();
652 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
653 assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
654 dc.computeImeParent());
655 }
656 }
657
658 @Test
659 public void testComputeImeParent_app_notFullscreen() throws Exception {
660 try (final InsetsModeSession session =
661 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
662 final DisplayContent dc = createNewDisplay();
663 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
664 dc.mInputMethodTarget.setWindowingMode(
665 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
666 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
667 }
668 }
669
670 @Test
671 public void testComputeImeParent_noApp() throws Exception {
672 try (final InsetsModeSession session =
673 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
674 final DisplayContent dc = createNewDisplay();
675 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
676 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
677 }
678 }
679
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500680 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100681 public void testUpdateSystemGestureExclusion() throws Exception {
682 final DisplayContent dc = createNewDisplay();
683 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
684 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
685 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
686
687 dc.setLayoutNeeded();
688 dc.performLayout(true /* initial */, false /* updateImeWindows */);
689
690 win.setHasSurface(true);
691 dc.updateSystemGestureExclusion();
692
693 final MutableBoolean invoked = new MutableBoolean(false);
694 final ISystemGestureExclusionListener.Stub verifier =
695 new ISystemGestureExclusionListener.Stub() {
696 @Override
697 public void onSystemGestureExclusionChanged(int displayId, Region actual) {
698 Region expected = Region.obtain();
699 expected.set(10, 20, 30, 40);
700 assertEquals(expected, actual);
701 invoked.value = true;
702 }
703 };
704 try {
705 dc.registerSystemGestureExclusionListener(verifier);
706 } finally {
707 dc.unregisterSystemGestureExclusionListener(verifier);
708 }
709 assertTrue("SystemGestureExclusionListener was not invoked", invoked.value);
710 }
711
712 @Test
713 public void testCalculateSystemGestureExclusion() throws Exception {
714 final DisplayContent dc = createNewDisplay();
715 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
716 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
717 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
718
719 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
720 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
721 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
722
723 dc.setLayoutNeeded();
724 dc.performLayout(true /* initial */, false /* updateImeWindows */);
725
726 win.setHasSurface(true);
727 win2.setHasSurface(true);
728
729 final Region expected = Region.obtain();
730 expected.set(20, 30, 40, 50);
731 assertEquals(expected, dc.calculateSystemGestureExclusion());
732 }
733
734 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500735 public void testOrientationChangeLogging() {
736 MetricsLogger mockLogger = mock(MetricsLogger.class);
737 Configuration oldConfig = new Configuration();
738 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
739
740 Configuration newConfig = new Configuration();
741 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
742 final DisplayContent displayContent = spy(createNewDisplay());
743 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
744 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
745
746 displayContent.onConfigurationChanged(newConfig);
747
748 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
749 verify(mockLogger).write(logMakerCaptor.capture());
750 assertThat(logMakerCaptor.getValue().getCategory(),
751 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
752 assertThat(logMakerCaptor.getValue().getSubtype(),
753 is(Configuration.ORIENTATION_PORTRAIT));
754 }
755
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800756 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700757 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800758 }
759
Bryce Lee27cec322017-03-21 09:41:37 -0700760 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
761 int expectedBaseHeight, int expectedBaseDensity) {
762 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
763 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
764 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
765 }
766
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800767 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700768 synchronized (mWm.mGlobalLock) {
769 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800770 }
771 }
772
Riddle Hsu654a6f92018-07-13 22:59:36 +0800773 /**
774 * Create DisplayContent that does not update display base/initial values from device to keep
775 * the values set by test.
776 */
777 private DisplayContent createDisplayNoUpdateDisplayInfo() {
778 final DisplayContent displayContent = spy(createNewDisplay());
779 doNothing().when(displayContent).updateDisplayInfo();
780 return displayContent;
781 }
782
Adrian Roos0f9368c2018-04-08 10:59:08 -0700783 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
784 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800785
786 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700787 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700788 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
789
790 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800791
792 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700793 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700794 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
795 }
796
797 private static List<WindowState> reverseList(List<WindowState> list) {
798 final ArrayList<WindowState> result = new ArrayList<>(list);
799 Collections.reverse(result);
800 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800801 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700802
Arthur Hungbe5ce212018-09-13 18:41:56 +0800803 private void tapOnDisplay(final DisplayContent dc) {
804 final DisplayMetrics dm = dc.getDisplayMetrics();
805 final float x = dm.widthPixels / 2;
806 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700807 final long downTime = SystemClock.uptimeMillis();
808 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800809 // sending ACTION_DOWN
810 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700811 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800812 downTime,
813 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700814 x,
815 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800816 0 /*metaState*/);
817 downEvent.setDisplayId(dc.getDisplayId());
818 dc.mTapDetector.onPointerEvent(downEvent);
819
820 // sending ACTION_UP
821 final MotionEvent upEvent = MotionEvent.obtain(
822 downTime,
823 eventTime,
824 MotionEvent.ACTION_UP,
825 x,
826 y,
827 0 /*metaState*/);
828 upEvent.setDisplayId(dc.getDisplayId());
829 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700830 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700831}