blob: 04f897ed1bdb3ea1c56793b531f0cd1353771fab [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;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080039import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080040import 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;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080044import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090045import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
46import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070047import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080048import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080049
Adrian Roos5251b1d2018-03-23 18:57:43 +010050import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080051import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070052import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080053import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080054import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010055import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080056import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080057import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080058
Andrii Kulian92c9a942017-10-10 00:41:41 -070059import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080060import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080061import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010062import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010063import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050064import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070065import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070066import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070067import android.util.DisplayMetrics;
Adrian Roos4ffc8972019-02-07 20:45:11 +010068import android.util.MutableBoolean;
Adrian Roos1cf585052018-01-03 18:43:27 +010069import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080070import android.view.Gravity;
Adrian Roos4ffc8972019-02-07 20:45:11 +010071import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070072import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010073import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080074import android.view.ViewRootImpl;
75import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070076
Brett Chabota26eda92018-07-23 13:08:30 -070077import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070078
Garfield Tan90b04282018-12-11 14:04:42 -080079import com.android.dx.mockito.inline.extended.ExtendedMockito;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050080import com.android.internal.logging.MetricsLogger;
81import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010082import com.android.server.wm.utils.WmDisplayCutout;
83
Brett Chabota26eda92018-07-23 13:08:30 -070084import org.junit.Test;
Garfield Tan90b04282018-12-11 14:04:42 -080085import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050086import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070087
Adrian Roos0f9368c2018-04-08 10:59:08 -070088import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080089import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070090import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080091import java.util.LinkedList;
92import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070093
94/**
95 * Tests for the {@link DisplayContent} class.
96 *
97 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +090098 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070099 */
100@SmallTest
101@Presubmit
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800102public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700103
104 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700105 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800106 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700107 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700108 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900109 // Wait until everything in animation handler get executed to prevent the exiting window
110 // from being removed during WindowSurfacePlacer Traversal.
111 waitUntilHandlersIdle();
112
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700113 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -0800114 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700115
Wale Ogunwale34247952017-02-19 11:57:53 -0800116 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700117 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800118 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700119 mChildAppWindowBelow,
120 mAppWindow,
121 mChildAppWindowAbove,
122 mDockedDividerWindow,
123 mStatusBarWindow,
124 mNavBarWindow,
125 mImeWindow,
126 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800127 }
128
129 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700130 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800131 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700132 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800133
lumarkff0ab692018-11-05 20:32:30 +0800134 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800135
Wale Ogunwale34247952017-02-19 11:57:53 -0800136 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700137 mWallpaperWindow,
138 mChildAppWindowBelow,
139 mAppWindow,
140 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800141 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700142 mImeWindow,
143 mImeDialogWindow,
144 mDockedDividerWindow,
145 mStatusBarWindow,
146 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800147 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800148
Wale Ogunwale34247952017-02-19 11:57:53 -0800149 @Test
lumarkff0ab692018-11-05 20:32:30 +0800150 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
151 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800152
Wale Ogunwale34247952017-02-19 11:57:53 -0800153 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700154 mWallpaperWindow,
155 mChildAppWindowBelow,
156 mAppWindow,
157 mChildAppWindowAbove,
158 mImeWindow,
159 mImeDialogWindow,
160 mDockedDividerWindow,
161 mStatusBarWindow,
162 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700163 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800164
165 @Test
lumarkff0ab692018-11-05 20:32:30 +0800166 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
167 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800168
Wale Ogunwale34247952017-02-19 11:57:53 -0800169 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700170 mWallpaperWindow,
171 mChildAppWindowBelow,
172 mAppWindow,
173 mChildAppWindowAbove,
174 mDockedDividerWindow,
175 mStatusBarWindow,
176 mImeWindow,
177 mImeDialogWindow,
178 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800179 }
180
181 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700182 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800183 // This window is set-up to be z-ordered between some windows that go in the same token like
184 // the nav bar and status bar.
185 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700186 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800187
Wale Ogunwale34247952017-02-19 11:57:53 -0800188 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700189 mWallpaperWindow,
190 mChildAppWindowBelow,
191 mAppWindow,
192 mChildAppWindowAbove,
193 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800194 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700195 mStatusBarWindow,
196 mNavBarWindow,
197 mImeWindow,
198 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800199 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800200
Wale Ogunwale34247952017-02-19 11:57:53 -0800201 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700202 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800203 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700204 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800205 appWin.setHasSurface(true);
206 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700207 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800208 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800209 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800210
Wale Ogunwale34247952017-02-19 11:57:53 -0800211 // Verify that an child window can be an ime target.
212 final WindowState childWin = createWindow(appWin,
213 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
214 childWin.setHasSurface(true);
215 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700216 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800217 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800218 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800219
Andrii Kuliand68501e2017-01-10 22:57:27 -0800220 /**
221 * This tests stack movement between displays and proper stack's, task's and app token's display
222 * container references updates.
223 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800224 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700225 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800226 // Create a second display.
227 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800228
229 // Add stack with activity.
230 final TaskStack stack = createTaskStackOnDisplay(dc);
231 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
232 assertEquals(dc, stack.getParent().getParent());
233 assertEquals(dc, stack.getDisplayContent());
234
235 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800236 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
237 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800238 task.addChild(token, 0);
239 assertEquals(dc, task.getDisplayContent());
240 assertEquals(dc, token.getDisplayContent());
241
242 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700243 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
244 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
245 assertEquals(mDisplayContent, stack.getParent().getParent());
246 assertEquals(mDisplayContent, stack.getDisplayContent());
247 assertEquals(mDisplayContent, task.getDisplayContent());
248 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800249 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800250
251 /**
252 * This tests override configuration updates for display content.
253 */
254 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700255 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700256 final Configuration currentOverrideConfig =
257 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800258
259 // Create new, slightly changed override configuration and apply it to the display.
260 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
261 newOverrideConfig.densityDpi += 120;
262 newOverrideConfig.fontScale += 0.3;
263
Evan Roskye747c3e2018-10-30 20:06:41 -0700264 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800265
266 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700267 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800268 }
269
270 /**
271 * This tests global configuration updates when default display config is updated.
272 */
273 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700274 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700275 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
276 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800277
278 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700279 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800280 newOverrideConfig.densityDpi += 120;
281 newOverrideConfig.fontScale += 0.3;
282
Evan Roskye747c3e2018-10-30 20:06:41 -0700283 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800284
285 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700286 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800287 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
288 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800289
290 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700291 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700292 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700293 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
294 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800295 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800296
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700297 /**
298 * Tests tapping on a stack in different display results in window gaining focus.
299 */
300 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700301 public void testInputEventBringsCorrectDisplayInFocus() {
302 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700303 // Create a second display
304 final DisplayContent dc1 = createNewDisplay();
305
306 // Add stack with activity.
307 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
308 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
309 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800310 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700311 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800312 dc0.configureDisplayPolicy();
313 assertNotNull(dc0.mTapDetector);
314
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700315 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
316 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
317 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800318 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700319 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800320 dc1.configureDisplayPolicy();
321 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700322
Arthur Hungbe5ce212018-09-13 18:41:56 +0800323 // tap on primary display.
324 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700325 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700326 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800327 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700328
Arthur Hungbe5ce212018-09-13 18:41:56 +0800329 // Tap on secondary display.
330 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700331 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700332 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800333 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700334 }
335
David Stevens46939562017-03-24 13:04:00 -0700336 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700337 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800338 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
339 }
340
341 @Test
342 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
343 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
344 }
345
346 @Test
347 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
348 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
349 }
350
351 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
352 int targetSdk) {
353 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
354
Andrii Kulian0214ed92017-05-16 13:44:05 -0700355 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700356 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700357 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800358 window1.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800359 updateFocusedWindow();
360 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700361 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700362
363 // Check that a new display doesn't affect focus
364 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800365 updateFocusedWindow();
366 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700367 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700368
369 // Add a window to the second display, and it should be focused
370 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800371 window2.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800372 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800373 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800374 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700375 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700376
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800377 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700378 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800379 updateFocusedWindow();
380 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800381 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700382 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800383
384 // Make sure top focused display not changed if there is a focused app.
385 window1.mAppToken.hiddenRequested = true;
386 window1.getDisplayContent().setFocusedApp(window1.mAppToken);
387 updateFocusedWindow();
388 assertTrue(!window1.isFocused());
389 assertEquals(window1.getDisplayId(),
390 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200391 }
392
Bryce Lee27cec322017-03-21 09:41:37 -0700393 /**
394 * This tests setting the maximum ui width on a display.
395 */
396 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700397 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800398 // Prevent base display metrics for test from being updated to the value of real display.
399 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700400 final int baseWidth = 1440;
401 final int baseHeight = 2560;
402 final int baseDensity = 300;
403
Riddle Hsu654a6f92018-07-13 22:59:36 +0800404 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700405
406 final int maxWidth = 300;
407 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
408 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
409
Riddle Hsu654a6f92018-07-13 22:59:36 +0800410 displayContent.setMaxUiWidth(maxWidth);
411 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700412
413 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800414 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
415 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700416
417 final int smallerWidth = 200;
418 final int smallerHeight = 400;
419 final int smallerDensity = 100;
420
421 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800422 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
423 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700424
425 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800426 displayContent.setMaxUiWidth(maxWidth);
427 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700428 }
429
Andrii Kulian92c9a942017-10-10 00:41:41 -0700430 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700431 public void testDisplayCutout_rot0() {
432 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100433 final DisplayContent dc = createNewDisplay();
434 dc.mInitialDisplayWidth = 200;
435 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100436 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100437 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200438 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100439 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100440
441 dc.mInitialDisplayCutout = cutout;
442 dc.setRotation(Surface.ROTATION_0);
443 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
444
445 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
446 }
447 }
448
449 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700450 public void testDisplayCutout_rot90() {
451 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800452 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
453 // if the device has no cutout).
454 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
455 // Rotation may use real display info to compute bound, so here also uses the
456 // same width and height.
457 final int displayWidth = dc.mInitialDisplayWidth;
458 final int displayHeight = dc.mInitialDisplayHeight;
459 final int cutoutWidth = 40;
460 final int cutoutHeight = 10;
461 final int left = (displayWidth - cutoutWidth) / 2;
462 final int top = 0;
463 final int right = (displayWidth + cutoutWidth) / 2;
464 final int bottom = cutoutHeight;
465
466 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100467 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700468 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
469 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800470 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100471
472 dc.mInitialDisplayCutout = cutout;
473 dc.setRotation(Surface.ROTATION_90);
474 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
475
Riddle Hsu654a6f92018-07-13 22:59:36 +0800476 // ----o---------- -------------
477 // | | | | |
478 // | ------o | o---
479 // | | | |
480 // | | -> | |
481 // | | ---o
482 // | | |
483 // | | -------------
484 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100485 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200486 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800487 .computeSafeInsets(displayHeight, displayWidth)
488 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100489 }
490 }
491
492 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700493 public void testLayoutSeq_assignedDuringLayout() {
494 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100495
496 final DisplayContent dc = createNewDisplay();
497 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
498
499 dc.setLayoutNeeded();
500 dc.performLayout(true /* initial */, false /* updateImeWindows */);
501
502 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
503 }
504 }
505
506 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700507 @SuppressLint("InlinedApi")
508 public void testOrientationDefinedByKeyguard() {
509 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800510
511 // When display content is created its configuration is not yet initialized, which could
512 // cause unnecessary configuration propagation, so initialize it here.
513 final Configuration config = new Configuration();
514 dc.computeScreenConfiguration(config);
515 dc.onRequestedOverrideConfigurationChanged(config);
516
Andrii Kulian92c9a942017-10-10 00:41:41 -0700517 // 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
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800551 public void testClearLastFocusWhenReparentingFocusedWindow() {
552 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
553 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
554 defaultDisplay, "window");
555 defaultDisplay.mLastFocus = window;
556 mDisplayContent.mCurrentFocus = window;
557 mDisplayContent.reParentWindowToken(window.mToken);
558
559 assertNull(defaultDisplay.mLastFocus);
560 }
561
562 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800563 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
564 final DisplayContent portraitDisplay = createNewDisplay();
565 portraitDisplay.mInitialDisplayHeight = 2000;
566 portraitDisplay.mInitialDisplayWidth = 1000;
567
568 portraitDisplay.setRotation(Surface.ROTATION_0);
569 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
570 portraitDisplay.setRotation(Surface.ROTATION_90);
571 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
572
573 final DisplayContent landscapeDisplay = createNewDisplay();
574 landscapeDisplay.mInitialDisplayHeight = 1000;
575 landscapeDisplay.mInitialDisplayWidth = 2000;
576
577 landscapeDisplay.setRotation(Surface.ROTATION_0);
578 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
579 landscapeDisplay.setRotation(Surface.ROTATION_90);
580 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
581 }
582
lumarkff0ab692018-11-05 20:32:30 +0800583 @Test
584 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
585 final DisplayContent newDisplay = createNewDisplay();
586
587 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
588 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
589 appWin.setHasSurface(true);
590 appWin1.setHasSurface(true);
591
592 // Set current input method window on default display, make sure the input method target
593 // is appWin & null on the other display.
594 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
595 newDisplay.setInputMethodWindowLocked(null);
596 assertTrue("appWin should be IME target window",
597 appWin.equals(mDisplayContent.mInputMethodTarget));
598 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
599
600 // Switch input method window on new display & make sure the input method target also
601 // switched as expected.
602 newDisplay.setInputMethodWindowLocked(mImeWindow);
603 mDisplayContent.setInputMethodWindowLocked(null);
604 assertTrue("appWin1 should be IME target window",
605 appWin1.equals(newDisplay.mInputMethodTarget));
606 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
607 }
608
Garfield Tan90b04282018-12-11 14:04:42 -0800609 @Test
610 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800611 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800612 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800613 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
614 ? SCREEN_ORIENTATION_PORTRAIT
615 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800616
617 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
618 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800619 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800620
621 ActivityRecord activityRecord = mock(ActivityRecord.class);
622
623 assertTrue("Display should rotate to handle orientation request by default.",
624 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
625
626 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
627 verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
628 same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
629 final Configuration newDisplayConfig = captor.getValue();
Garfield Tan49dae102019-02-04 09:51:59 -0800630 assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800631 }
632
633 @Test
634 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800635 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800636 dc.getDisplayRotation().setFixedToUserRotation(
637 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan90b04282018-12-11 14:04:42 -0800638 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800639 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
640 ? SCREEN_ORIENTATION_PORTRAIT
641 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800642
643 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
644 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800645 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800646
647 ActivityRecord activityRecord = mock(ActivityRecord.class);
648
649 assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
650 + " user rotation.",
651 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
652 verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
653 eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
654 }
655
Tarandeep Singha6f35612019-01-11 19:50:46 -0800656 @Test
657 public void testComputeImeParent_app() throws Exception {
658 try (final InsetsModeSession session =
659 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
660 final DisplayContent dc = createNewDisplay();
661 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
662 assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
663 dc.computeImeParent());
664 }
665 }
666
667 @Test
668 public void testComputeImeParent_app_notFullscreen() throws Exception {
669 try (final InsetsModeSession session =
670 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
671 final DisplayContent dc = createNewDisplay();
672 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
673 dc.mInputMethodTarget.setWindowingMode(
674 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
675 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
676 }
677 }
678
679 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800680 public void testComputeImeParent_app_notMatchParentBounds() {
681 spyOn(mAppWindow.mAppToken);
682 doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
683 mDisplayContent.mInputMethodTarget = mAppWindow;
684 // The surface parent of IME should be the display instead of app window.
685 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
686 }
687
688 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800689 public void testComputeImeParent_noApp() throws Exception {
690 try (final InsetsModeSession session =
691 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
692 final DisplayContent dc = createNewDisplay();
693 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
694 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
695 }
696 }
697
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500698 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100699 public void testUpdateSystemGestureExclusion() throws Exception {
700 final DisplayContent dc = createNewDisplay();
701 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
702 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
703 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
704
705 dc.setLayoutNeeded();
706 dc.performLayout(true /* initial */, false /* updateImeWindows */);
707
708 win.setHasSurface(true);
709 dc.updateSystemGestureExclusion();
710
711 final MutableBoolean invoked = new MutableBoolean(false);
712 final ISystemGestureExclusionListener.Stub verifier =
713 new ISystemGestureExclusionListener.Stub() {
714 @Override
715 public void onSystemGestureExclusionChanged(int displayId, Region actual) {
716 Region expected = Region.obtain();
717 expected.set(10, 20, 30, 40);
718 assertEquals(expected, actual);
719 invoked.value = true;
720 }
721 };
722 try {
723 dc.registerSystemGestureExclusionListener(verifier);
724 } finally {
725 dc.unregisterSystemGestureExclusionListener(verifier);
726 }
727 assertTrue("SystemGestureExclusionListener was not invoked", invoked.value);
728 }
729
730 @Test
731 public void testCalculateSystemGestureExclusion() throws Exception {
732 final DisplayContent dc = createNewDisplay();
733 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
734 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
735 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
736
737 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
738 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
739 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
740
741 dc.setLayoutNeeded();
742 dc.performLayout(true /* initial */, false /* updateImeWindows */);
743
744 win.setHasSurface(true);
745 win2.setHasSurface(true);
746
747 final Region expected = Region.obtain();
748 expected.set(20, 30, 40, 50);
749 assertEquals(expected, dc.calculateSystemGestureExclusion());
750 }
751
752 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500753 public void testOrientationChangeLogging() {
754 MetricsLogger mockLogger = mock(MetricsLogger.class);
755 Configuration oldConfig = new Configuration();
756 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
757
758 Configuration newConfig = new Configuration();
759 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
760 final DisplayContent displayContent = spy(createNewDisplay());
761 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
762 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
763
764 displayContent.onConfigurationChanged(newConfig);
765
766 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
767 verify(mockLogger).write(logMakerCaptor.capture());
768 assertThat(logMakerCaptor.getValue().getCategory(),
769 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
770 assertThat(logMakerCaptor.getValue().getSubtype(),
771 is(Configuration.ORIENTATION_PORTRAIT));
772 }
773
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800774 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700775 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800776 }
777
Bryce Lee27cec322017-03-21 09:41:37 -0700778 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
779 int expectedBaseHeight, int expectedBaseDensity) {
780 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
781 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
782 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
783 }
784
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800785 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700786 synchronized (mWm.mGlobalLock) {
787 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800788 }
789 }
790
Riddle Hsu654a6f92018-07-13 22:59:36 +0800791 /**
792 * Create DisplayContent that does not update display base/initial values from device to keep
793 * the values set by test.
794 */
795 private DisplayContent createDisplayNoUpdateDisplayInfo() {
796 final DisplayContent displayContent = spy(createNewDisplay());
797 doNothing().when(displayContent).updateDisplayInfo();
798 return displayContent;
799 }
800
Adrian Roos0f9368c2018-04-08 10:59:08 -0700801 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
802 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800803
804 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700805 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700806 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
807
808 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800809
810 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700811 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700812 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
813 }
814
815 private static List<WindowState> reverseList(List<WindowState> list) {
816 final ArrayList<WindowState> result = new ArrayList<>(list);
817 Collections.reverse(result);
818 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800819 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700820
Arthur Hungbe5ce212018-09-13 18:41:56 +0800821 private void tapOnDisplay(final DisplayContent dc) {
822 final DisplayMetrics dm = dc.getDisplayMetrics();
823 final float x = dm.widthPixels / 2;
824 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700825 final long downTime = SystemClock.uptimeMillis();
826 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800827 // sending ACTION_DOWN
828 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700829 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800830 downTime,
831 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700832 x,
833 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800834 0 /*metaState*/);
835 downEvent.setDisplayId(dc.getDisplayId());
836 dc.mTapDetector.onPointerEvent(downEvent);
837
838 // sending ACTION_UP
839 final MotionEvent upEvent = MotionEvent.obtain(
840 downTime,
841 eventTime,
842 MotionEvent.ACTION_UP,
843 x,
844 y,
845 0 /*metaState*/);
846 upEvent.setDisplayId(dc.getDisplayId());
847 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700848 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700849}