blob: ae4074275b97a32cc89a3c0af0d8ad9819732ee9 [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 Huang86e6d072019-05-02 20:23:47 +080022import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080023import static android.os.Build.VERSION_CODES.P;
24import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080025import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020026import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
27import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010028import static android.view.DisplayCutout.fromBoundingRect;
Adrian Roos019a52b2019-07-02 16:47:44 +020029import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
30import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
31import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010032import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
33import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020034import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
35import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080036import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
37import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080039import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070040import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080041import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Brett Chabota26eda92018-07-23 13:08:30 -070042
Garfield Tan90b04282018-12-11 14:04:42 -080043import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
44import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090045import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080046import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080047import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
48import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
49import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080050import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090051import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
52import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070053import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080054import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080055
Adrian Roos5251b1d2018-03-23 18:57:43 +010056import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080057import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070058import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080059import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080060import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010061import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080062import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080063import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080064
Andrii Kulian92c9a942017-10-10 00:41:41 -070065import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080066import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080067import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010068import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010069import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050070import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070071import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070072import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070073import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010074import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080075import android.view.Gravity;
Adrian Roos4ffc8972019-02-07 20:45:11 +010076import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070077import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010078import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080079import android.view.ViewRootImpl;
80import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070081
Brett Chabota26eda92018-07-23 13:08:30 -070082import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070083
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050084import com.android.internal.logging.MetricsLogger;
85import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010086import com.android.server.wm.utils.WmDisplayCutout;
87
Brett Chabota26eda92018-07-23 13:08:30 -070088import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080089import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -080090import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050091import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070092
Adrian Roos0f9368c2018-04-08 10:59:08 -070093import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080094import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070095import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080096import java.util.LinkedList;
97import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070098
99/**
100 * Tests for the {@link DisplayContent} class.
101 *
102 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900103 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700104 */
105@SmallTest
106@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800107@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800108public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700109
110 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700111 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800112 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700113 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700114 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900115 // Wait until everything in animation handler get executed to prevent the exiting window
116 // from being removed during WindowSurfacePlacer Traversal.
117 waitUntilHandlersIdle();
118
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700119 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -0800120 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700121
Wale Ogunwale34247952017-02-19 11:57:53 -0800122 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700123 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800124 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700125 mChildAppWindowBelow,
126 mAppWindow,
127 mChildAppWindowAbove,
128 mDockedDividerWindow,
129 mStatusBarWindow,
130 mNavBarWindow,
131 mImeWindow,
132 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800133 }
134
135 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700136 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800137 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700138 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800139
lumarkff0ab692018-11-05 20:32:30 +0800140 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800141
Wale Ogunwale34247952017-02-19 11:57:53 -0800142 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700143 mWallpaperWindow,
144 mChildAppWindowBelow,
145 mAppWindow,
146 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800147 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700148 mImeWindow,
149 mImeDialogWindow,
150 mDockedDividerWindow,
151 mStatusBarWindow,
152 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800153 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800154
Wale Ogunwale34247952017-02-19 11:57:53 -0800155 @Test
lumarkff0ab692018-11-05 20:32:30 +0800156 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
157 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800158
Wale Ogunwale34247952017-02-19 11:57:53 -0800159 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700160 mWallpaperWindow,
161 mChildAppWindowBelow,
162 mAppWindow,
163 mChildAppWindowAbove,
164 mImeWindow,
165 mImeDialogWindow,
166 mDockedDividerWindow,
167 mStatusBarWindow,
168 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700169 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800170
171 @Test
lumarkff0ab692018-11-05 20:32:30 +0800172 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
173 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800174
Wale Ogunwale34247952017-02-19 11:57:53 -0800175 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700176 mWallpaperWindow,
177 mChildAppWindowBelow,
178 mAppWindow,
179 mChildAppWindowAbove,
180 mDockedDividerWindow,
181 mStatusBarWindow,
182 mImeWindow,
183 mImeDialogWindow,
184 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800185 }
186
187 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700188 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800189 // This window is set-up to be z-ordered between some windows that go in the same token like
190 // the nav bar and status bar.
191 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700192 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800193
Wale Ogunwale34247952017-02-19 11:57:53 -0800194 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700195 mWallpaperWindow,
196 mChildAppWindowBelow,
197 mAppWindow,
198 mChildAppWindowAbove,
199 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800200 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700201 mStatusBarWindow,
202 mNavBarWindow,
203 mImeWindow,
204 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800205 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800206
Wale Ogunwale34247952017-02-19 11:57:53 -0800207 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700208 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800209 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700210 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800211 appWin.setHasSurface(true);
212 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700213 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800214 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800215 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800216
Wale Ogunwale34247952017-02-19 11:57:53 -0800217 // Verify that an child window can be an ime target.
218 final WindowState childWin = createWindow(appWin,
219 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
220 childWin.setHasSurface(true);
221 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700222 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800223 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800224 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800225
Andrii Kuliand68501e2017-01-10 22:57:27 -0800226 /**
227 * This tests stack movement between displays and proper stack's, task's and app token's display
228 * container references updates.
229 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800230 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700231 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800232 // Create a second display.
233 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800234
235 // Add stack with activity.
236 final TaskStack stack = createTaskStackOnDisplay(dc);
237 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
238 assertEquals(dc, stack.getParent().getParent());
239 assertEquals(dc, stack.getDisplayContent());
240
241 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800242 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
243 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800244 task.addChild(token, 0);
245 assertEquals(dc, task.getDisplayContent());
246 assertEquals(dc, token.getDisplayContent());
247
248 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700249 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
250 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
251 assertEquals(mDisplayContent, stack.getParent().getParent());
252 assertEquals(mDisplayContent, stack.getDisplayContent());
253 assertEquals(mDisplayContent, task.getDisplayContent());
254 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800255 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800256
257 /**
258 * This tests override configuration updates for display content.
259 */
260 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700261 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700262 final Configuration currentOverrideConfig =
263 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800264
265 // Create new, slightly changed override configuration and apply it to the display.
266 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
267 newOverrideConfig.densityDpi += 120;
268 newOverrideConfig.fontScale += 0.3;
269
Evan Roskye747c3e2018-10-30 20:06:41 -0700270 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800271
272 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700273 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800274 }
275
276 /**
277 * This tests global configuration updates when default display config is updated.
278 */
279 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700280 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700281 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
282 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800283
284 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700285 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800286 newOverrideConfig.densityDpi += 120;
287 newOverrideConfig.fontScale += 0.3;
288
Evan Roskye747c3e2018-10-30 20:06:41 -0700289 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800290
291 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700292 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800293 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
294 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800295
296 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700297 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700298 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700299 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
300 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800301 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800302
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700303 /**
304 * Tests tapping on a stack in different display results in window gaining focus.
305 */
306 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700307 public void testInputEventBringsCorrectDisplayInFocus() {
308 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700309 // Create a second display
310 final DisplayContent dc1 = createNewDisplay();
311
312 // Add stack with activity.
313 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
314 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
315 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800316 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700317 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800318 dc0.configureDisplayPolicy();
319 assertNotNull(dc0.mTapDetector);
320
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700321 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
322 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
323 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800324 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700325 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800326 dc1.configureDisplayPolicy();
327 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700328
Arthur Hungbe5ce212018-09-13 18:41:56 +0800329 // tap on primary display.
330 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700331 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700332 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800333 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700334
Arthur Hungbe5ce212018-09-13 18:41:56 +0800335 // Tap on secondary display.
336 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700337 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700338 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800339 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700340 }
341
David Stevens46939562017-03-24 13:04:00 -0700342 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700343 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800344 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
345 }
346
347 @Test
348 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
349 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
350 }
351
352 @Test
353 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
354 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
355 }
356
357 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
358 int targetSdk) {
359 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
360
Andrii Kulian0214ed92017-05-16 13:44:05 -0700361 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700362 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700363 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800364 window1.mAppToken.mTargetSdk = targetSdk;
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 // Check that a new display doesn't affect focus
370 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800371 updateFocusedWindow();
372 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700373 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700374
375 // Add a window to the second display, and it should be focused
376 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800377 window2.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800378 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800379 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800380 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700381 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700382
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800383 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700384 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800385 updateFocusedWindow();
386 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800387 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700388 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800389
390 // Make sure top focused display not changed if there is a focused app.
391 window1.mAppToken.hiddenRequested = true;
392 window1.getDisplayContent().setFocusedApp(window1.mAppToken);
393 updateFocusedWindow();
394 assertTrue(!window1.isFocused());
395 assertEquals(window1.getDisplayId(),
396 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200397 }
398
Bryce Lee27cec322017-03-21 09:41:37 -0700399 /**
400 * This tests setting the maximum ui width on a display.
401 */
402 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700403 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800404 // Prevent base display metrics for test from being updated to the value of real display.
405 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700406 final int baseWidth = 1440;
407 final int baseHeight = 2560;
408 final int baseDensity = 300;
409
Riddle Hsu654a6f92018-07-13 22:59:36 +0800410 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700411
412 final int maxWidth = 300;
413 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
414 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
415
Riddle Hsu654a6f92018-07-13 22:59:36 +0800416 displayContent.setMaxUiWidth(maxWidth);
417 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700418
419 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800420 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
421 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700422
423 final int smallerWidth = 200;
424 final int smallerHeight = 400;
425 final int smallerDensity = 100;
426
427 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800428 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
429 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700430
431 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800432 displayContent.setMaxUiWidth(maxWidth);
433 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700434 }
435
Andrii Kulian92c9a942017-10-10 00:41:41 -0700436 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700437 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800438 final DisplayContent dc = createNewDisplay();
439 dc.mInitialDisplayWidth = 200;
440 dc.mInitialDisplayHeight = 400;
441 final Rect r = new Rect(80, 0, 120, 10);
442 final DisplayCutout cutout = new WmDisplayCutout(
443 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
444 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100445
Riddle Hsu73f53572019-09-23 23:13:01 +0800446 dc.mInitialDisplayCutout = cutout;
447 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
448 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100449
Riddle Hsu73f53572019-09-23 23:13:01 +0800450 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100451 }
452
453 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700454 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800455 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
456 // if the device has no cutout).
457 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
458 // Rotation may use real display info to compute bound, so here also uses the
459 // same width and height.
460 final int displayWidth = dc.mInitialDisplayWidth;
461 final int displayHeight = dc.mInitialDisplayHeight;
462 final int cutoutWidth = 40;
463 final int cutoutHeight = 10;
464 final int left = (displayWidth - cutoutWidth) / 2;
465 final int top = 0;
466 final int right = (displayWidth + cutoutWidth) / 2;
467 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800468
Riddle Hsu73f53572019-09-23 23:13:01 +0800469 final Rect r1 = new Rect(left, top, right, bottom);
470 final DisplayCutout cutout = new WmDisplayCutout(
471 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
472 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100473
Riddle Hsu73f53572019-09-23 23:13:01 +0800474 dc.mInitialDisplayCutout = cutout;
475 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
476 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100477
Riddle Hsu73f53572019-09-23 23:13:01 +0800478 // ----o---------- -------------
479 // | | | | |
480 // | ------o | o---
481 // | | | |
482 // | | -> | |
483 // | | ---o
484 // | | |
485 // | | -------------
486 final Rect r = new Rect(top, left, bottom, right);
487 assertEquals(new WmDisplayCutout(
488 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
489 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
490 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100491 }
492
493 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700494 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800495 final DisplayContent dc = createNewDisplay();
496 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100497
Riddle Hsu73f53572019-09-23 23:13:01 +0800498 dc.setLayoutNeeded();
499 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100500
Riddle Hsu73f53572019-09-23 23:13:01 +0800501 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100502 }
503
504 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700505 @SuppressLint("InlinedApi")
506 public void testOrientationDefinedByKeyguard() {
507 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800508
509 // When display content is created its configuration is not yet initialized, which could
510 // cause unnecessary configuration propagation, so initialize it here.
511 final Configuration config = new Configuration();
512 dc.computeScreenConfiguration(config);
513 dc.onRequestedOverrideConfigurationChanged(config);
514
Andrii Kulian92c9a942017-10-10 00:41:41 -0700515 // Create a window that requests landscape orientation. It will define device orientation
516 // by default.
517 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
518 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
519
520 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
521 keyguard.mHasSurface = true;
522 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
523
524 assertEquals("Screen orientation must be defined by the app window by default",
525 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
526
527 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
528 assertEquals("Visible keyguard must influence device orientation",
529 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
530
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700531 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700532 assertEquals("Keyguard that is going away must not influence device orientation",
533 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
534 }
535
Andrii Kulianf0379de2018-03-14 16:24:07 -0700536 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800537 public void testOrientationForAspectRatio() {
538 final DisplayContent dc = createNewDisplay();
539
540 // When display content is created its configuration is not yet initialized, which could
541 // cause unnecessary configuration propagation, so initialize it here.
542 final Configuration config = new Configuration();
543 dc.computeScreenConfiguration(config);
544 dc.onRequestedOverrideConfigurationChanged(config);
545
546 // Create a window that requests a fixed orientation. It will define device orientation
547 // by default.
548 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
549 "window");
550 window.mHasSurface = true;
551 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
552
553 // --------------------------------
554 // Test non-close-to-square display
555 // --------------------------------
556 dc.mBaseDisplayWidth = 1000;
557 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
558 dc.configureDisplayPolicy();
559
560 assertEquals("Screen orientation must be defined by the window by default.",
561 window.mAttrs.screenOrientation, dc.getOrientation());
562
563 // ----------------------------
564 // Test close-to-square display
565 // ----------------------------
566 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
567 dc.configureDisplayPolicy();
568
569 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
570 SCREEN_ORIENTATION_USER, dc.getOrientation());
571 }
572
573 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700574 public void testDisableDisplayInfoOverrideFromWindowManager() {
575 final DisplayContent dc = createNewDisplay();
576
577 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700578 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700579
580 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700581 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700582 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
583 }
584
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800585 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800586 public void testClearLastFocusWhenReparentingFocusedWindow() {
587 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
588 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
589 defaultDisplay, "window");
590 defaultDisplay.mLastFocus = window;
591 mDisplayContent.mCurrentFocus = window;
592 mDisplayContent.reParentWindowToken(window.mToken);
593
594 assertNull(defaultDisplay.mLastFocus);
595 }
596
597 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800598 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
599 final DisplayContent portraitDisplay = createNewDisplay();
600 portraitDisplay.mInitialDisplayHeight = 2000;
601 portraitDisplay.mInitialDisplayWidth = 1000;
602
Riddle Hsuccf09402019-08-13 00:33:06 +0800603 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800604 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Riddle Hsuccf09402019-08-13 00:33:06 +0800605 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800606 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
607
608 final DisplayContent landscapeDisplay = createNewDisplay();
609 landscapeDisplay.mInitialDisplayHeight = 1000;
610 landscapeDisplay.mInitialDisplayWidth = 2000;
611
Riddle Hsuccf09402019-08-13 00:33:06 +0800612 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800613 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Riddle Hsuccf09402019-08-13 00:33:06 +0800614 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800615 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
616 }
617
lumarkff0ab692018-11-05 20:32:30 +0800618 @Test
619 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
620 final DisplayContent newDisplay = createNewDisplay();
621
622 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
623 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
624 appWin.setHasSurface(true);
625 appWin1.setHasSurface(true);
626
627 // Set current input method window on default display, make sure the input method target
628 // is appWin & null on the other display.
629 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
630 newDisplay.setInputMethodWindowLocked(null);
631 assertTrue("appWin should be IME target window",
632 appWin.equals(mDisplayContent.mInputMethodTarget));
633 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
634
635 // Switch input method window on new display & make sure the input method target also
636 // switched as expected.
637 newDisplay.setInputMethodWindowLocked(mImeWindow);
638 mDisplayContent.setInputMethodWindowLocked(null);
639 assertTrue("appWin1 should be IME target window",
640 appWin1.equals(newDisplay.mInputMethodTarget));
641 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
642 }
643
Garfield Tan90b04282018-12-11 14:04:42 -0800644 @Test
645 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800646 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700647 dc.getDisplayRotation().setFixedToUserRotation(
648 DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800649 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
650 ? SCREEN_ORIENTATION_PORTRAIT
651 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800652
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700653 final ActivityStack stack =
654 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
655 .setDisplay(dc.mAcitvityDisplay).build();
656 final ActivityRecord activity = stack.topTask().getTopActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800657
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700658 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800659
660 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
Shivam Agrawal1d3db652019-07-01 15:26:11 -0700661 verify(dc.mAcitvityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700662 same(activity), anyBoolean(), same(null));
Garfield Tan90b04282018-12-11 14:04:42 -0800663 final Configuration newDisplayConfig = captor.getValue();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700664 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
665 ? Configuration.ORIENTATION_PORTRAIT
666 : Configuration.ORIENTATION_LANDSCAPE;
667 assertEquals(expectedOrientation, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800668 }
669
670 @Test
671 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800672 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800673 dc.getDisplayRotation().setFixedToUserRotation(
674 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800675 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
676 ? SCREEN_ORIENTATION_PORTRAIT
677 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800678
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700679 final ActivityStack stack =
680 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
681 .setDisplay(dc.mAcitvityDisplay).build();
682 final ActivityRecord activity = stack.topTask().getTopActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800683
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700684 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800685
Shivam Agrawal1d3db652019-07-01 15:26:11 -0700686 verify(dc.mAcitvityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700687 eq(activity), anyBoolean(), same(null));
688 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800689 }
690
Tarandeep Singha6f35612019-01-11 19:50:46 -0800691 @Test
692 public void testComputeImeParent_app() throws Exception {
693 try (final InsetsModeSession session =
694 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
695 final DisplayContent dc = createNewDisplay();
696 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
697 assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
698 dc.computeImeParent());
699 }
700 }
701
702 @Test
703 public void testComputeImeParent_app_notFullscreen() throws Exception {
704 try (final InsetsModeSession session =
705 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
706 final DisplayContent dc = createNewDisplay();
707 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
708 dc.mInputMethodTarget.setWindowingMode(
709 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
710 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
711 }
712 }
713
714 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800715 public void testComputeImeParent_app_notMatchParentBounds() {
716 spyOn(mAppWindow.mAppToken);
717 doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
718 mDisplayContent.mInputMethodTarget = mAppWindow;
719 // The surface parent of IME should be the display instead of app window.
720 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
721 }
722
723 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800724 public void testComputeImeParent_noApp() throws Exception {
725 try (final InsetsModeSession session =
726 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
727 final DisplayContent dc = createNewDisplay();
728 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
729 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
730 }
731 }
732
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500733 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100734 public void testUpdateSystemGestureExclusion() throws Exception {
735 final DisplayContent dc = createNewDisplay();
736 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
737 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
738 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
739
740 dc.setLayoutNeeded();
741 dc.performLayout(true /* initial */, false /* updateImeWindows */);
742
743 win.setHasSurface(true);
744 dc.updateSystemGestureExclusion();
745
Riddle Hsu73f53572019-09-23 23:13:01 +0800746 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100747 final ISystemGestureExclusionListener.Stub verifier =
748 new ISystemGestureExclusionListener.Stub() {
749 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200750 public void onSystemGestureExclusionChanged(int displayId, Region actual,
751 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100752 Region expected = Region.obtain();
753 expected.set(10, 20, 30, 40);
754 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800755 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100756 }
757 };
758 try {
759 dc.registerSystemGestureExclusionListener(verifier);
760 } finally {
761 dc.unregisterSystemGestureExclusionListener(verifier);
762 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800763 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100764 }
765
766 @Test
767 public void testCalculateSystemGestureExclusion() throws Exception {
768 final DisplayContent dc = createNewDisplay();
769 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
770 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
771 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
772
773 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
774 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
775 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
776
777 dc.setLayoutNeeded();
778 dc.performLayout(true /* initial */, false /* updateImeWindows */);
779
780 win.setHasSurface(true);
781 win2.setHasSurface(true);
782
783 final Region expected = Region.obtain();
784 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200785 assertEquals(expected, calculateSystemGestureExclusion(dc));
786 }
787
788 private Region calculateSystemGestureExclusion(DisplayContent dc) {
789 Region out = Region.obtain();
790 Region unrestricted = Region.obtain();
791 dc.calculateSystemGestureExclusion(out, unrestricted);
792 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100793 }
794
795 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200796 public void testCalculateSystemGestureExclusion_modal() throws Exception {
797 final DisplayContent dc = createNewDisplay();
798 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
799 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
800 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
801
802 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
803 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
804 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
805 win2.getAttrs().width = 10;
806 win2.getAttrs().height = 10;
807 win2.setSystemGestureExclusion(Collections.emptyList());
808
809 dc.setLayoutNeeded();
810 dc.performLayout(true /* initial */, false /* updateImeWindows */);
811
812 win.setHasSurface(true);
813 win2.setHasSurface(true);
814
815 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200816 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200817 }
818
819 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200820 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Riddle Hsu73f53572019-09-23 23:13:01 +0800821 mWm.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200822
Riddle Hsu73f53572019-09-23 23:13:01 +0800823 final DisplayContent dc = createNewDisplay();
824 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
825 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
826 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
827 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
828 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
829 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
830 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
831 win.mAppToken.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200832
Riddle Hsu73f53572019-09-23 23:13:01 +0800833 dc.setLayoutNeeded();
834 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos019a52b2019-07-02 16:47:44 +0200835
Riddle Hsu73f53572019-09-23 23:13:01 +0800836 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200837
Riddle Hsu73f53572019-09-23 23:13:01 +0800838 final Region expected = Region.obtain();
839 expected.set(dc.getBounds());
840 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200841
Riddle Hsu73f53572019-09-23 23:13:01 +0800842 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200843 }
844
845 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500846 public void testOrientationChangeLogging() {
847 MetricsLogger mockLogger = mock(MetricsLogger.class);
848 Configuration oldConfig = new Configuration();
849 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
850
851 Configuration newConfig = new Configuration();
852 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800853 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500854 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
855 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
856
857 displayContent.onConfigurationChanged(newConfig);
858
859 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
860 verify(mockLogger).write(logMakerCaptor.capture());
861 assertThat(logMakerCaptor.getValue().getCategory(),
862 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
863 assertThat(logMakerCaptor.getValue().getSubtype(),
864 is(Configuration.ORIENTATION_PORTRAIT));
865 }
866
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800867 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700868 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800869 }
870
Bryce Lee27cec322017-03-21 09:41:37 -0700871 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
872 int expectedBaseHeight, int expectedBaseDensity) {
873 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
874 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
875 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
876 }
877
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800878 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800879 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800880 }
881
Riddle Hsu654a6f92018-07-13 22:59:36 +0800882 /**
883 * Create DisplayContent that does not update display base/initial values from device to keep
884 * the values set by test.
885 */
886 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800887 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +0800888 doNothing().when(displayContent).updateDisplayInfo();
889 return displayContent;
890 }
891
Adrian Roos0f9368c2018-04-08 10:59:08 -0700892 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
893 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800894
895 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700896 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700897 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
898
899 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800900
901 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700902 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700903 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
904 }
905
906 private static List<WindowState> reverseList(List<WindowState> list) {
907 final ArrayList<WindowState> result = new ArrayList<>(list);
908 Collections.reverse(result);
909 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800910 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700911
Arthur Hungbe5ce212018-09-13 18:41:56 +0800912 private void tapOnDisplay(final DisplayContent dc) {
913 final DisplayMetrics dm = dc.getDisplayMetrics();
914 final float x = dm.widthPixels / 2;
915 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700916 final long downTime = SystemClock.uptimeMillis();
917 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800918 // sending ACTION_DOWN
919 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700920 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800921 downTime,
922 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700923 x,
924 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800925 0 /*metaState*/);
926 downEvent.setDisplayId(dc.getDisplayId());
927 dc.mTapDetector.onPointerEvent(downEvent);
928
929 // sending ACTION_UP
930 final MotionEvent upEvent = MotionEvent.obtain(
931 downTime,
932 eventTime,
933 MotionEvent.ACTION_UP,
934 x,
935 y,
936 0 /*metaState*/);
937 upEvent.setDisplayId(dc.getDisplayId());
938 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700939 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700940}