blob: f2ba97c269d5edbf83b4d8f181791eb70267e833 [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
Garfield Tan98eead32019-11-18 13:24:53 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Andrii Kulian92c9a942017-10-10 00:41:41 -070020import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
22import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080024import static android.os.Build.VERSION_CODES.P;
25import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020027import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
28import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010029import static android.view.DisplayCutout.fromBoundingRect;
Evan Rosky69cace42019-09-20 16:28:13 -070030import static android.view.Surface.ROTATION_90;
Adrian Roos019a52b2019-07-02 16:47:44 +020031import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
32import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
33import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010034import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
35import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020036import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
37import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
39import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080040import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080041import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070042import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080043import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060044import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070045
Garfield Tan90b04282018-12-11 14:04:42 -080046import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
47import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090048import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080049import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080050import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
51import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060052import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080053import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080054import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090055import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
56import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070057import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080058import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080059
Riddle Hsu12c05452020-01-09 00:39:52 +080060import static com.google.common.truth.Truth.assertThat;
61
Adrian Roos5251b1d2018-03-23 18:57:43 +010062import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080063import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070064import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080065import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080066import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010067import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080068import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070069import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080070import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080071
Andrii Kulian92c9a942017-10-10 00:41:41 -070072import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080073import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080074import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010075import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010076import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050077import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070078import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070079import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070080import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070081import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010082import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080083import android.view.Gravity;
Evan Rosky69cace42019-09-20 16:28:13 -070084import android.view.IDisplayWindowRotationCallback;
85import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010086import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080087import android.view.IWindowManager;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070088import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010089import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080090import android.view.ViewRootImpl;
Riddle Hsu12c05452020-01-09 00:39:52 +080091import android.view.WindowManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080092import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070093
Brett Chabota26eda92018-07-23 13:08:30 -070094import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070095
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050096import com.android.internal.logging.MetricsLogger;
97import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010098import com.android.server.wm.utils.WmDisplayCutout;
99
Brett Chabota26eda92018-07-23 13:08:30 -0700100import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800101import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800102import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500103import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700104
Adrian Roos0f9368c2018-04-08 10:59:08 -0700105import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800106import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700107import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800108import java.util.LinkedList;
109import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700110
111/**
112 * Tests for the {@link DisplayContent} class.
113 *
114 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900115 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700116 */
117@SmallTest
118@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800119@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800120public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700121
122 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700123 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800124 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700125 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700126 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900127 // Wait until everything in animation handler get executed to prevent the exiting window
128 // from being removed during WindowSurfacePlacer Traversal.
129 waitUntilHandlersIdle();
130
Garfield Tane8d84ab2019-10-11 09:49:40 -0700131 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800132 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700133
Wale Ogunwale34247952017-02-19 11:57:53 -0800134 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700135 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800136 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700137 mChildAppWindowBelow,
138 mAppWindow,
139 mChildAppWindowAbove,
140 mDockedDividerWindow,
141 mStatusBarWindow,
142 mNavBarWindow,
143 mImeWindow,
144 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800145 }
146
147 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700148 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800149 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700150 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800151
lumarkff0ab692018-11-05 20:32:30 +0800152 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800153
Wale Ogunwale34247952017-02-19 11:57:53 -0800154 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700155 mWallpaperWindow,
156 mChildAppWindowBelow,
157 mAppWindow,
158 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800159 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700160 mImeWindow,
161 mImeDialogWindow,
162 mDockedDividerWindow,
163 mStatusBarWindow,
164 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800165 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800166
Wale Ogunwale34247952017-02-19 11:57:53 -0800167 @Test
lumarkff0ab692018-11-05 20:32:30 +0800168 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
169 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800170
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700172 mWallpaperWindow,
173 mChildAppWindowBelow,
174 mAppWindow,
175 mChildAppWindowAbove,
176 mImeWindow,
177 mImeDialogWindow,
178 mDockedDividerWindow,
179 mStatusBarWindow,
180 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700181 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800182
183 @Test
lumarkff0ab692018-11-05 20:32:30 +0800184 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
185 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800186
Wale Ogunwale34247952017-02-19 11:57:53 -0800187 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700188 mWallpaperWindow,
189 mChildAppWindowBelow,
190 mAppWindow,
191 mChildAppWindowAbove,
192 mDockedDividerWindow,
193 mStatusBarWindow,
194 mImeWindow,
195 mImeDialogWindow,
196 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800197 }
198
199 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700200 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800201 // This window is set-up to be z-ordered between some windows that go in the same token like
202 // the nav bar and status bar.
203 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700204 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800205
Wale Ogunwale34247952017-02-19 11:57:53 -0800206 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700207 mWallpaperWindow,
208 mChildAppWindowBelow,
209 mAppWindow,
210 mChildAppWindowAbove,
211 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800212 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700213 mStatusBarWindow,
214 mNavBarWindow,
215 mImeWindow,
216 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800217 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800218
Wale Ogunwale34247952017-02-19 11:57:53 -0800219 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700220 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800221 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700222 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800223 appWin.setHasSurface(true);
224 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700225 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800226 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800227 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800228
Wale Ogunwale34247952017-02-19 11:57:53 -0800229 // Verify that an child window can be an ime target.
230 final WindowState childWin = createWindow(appWin,
231 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
232 childWin.setHasSurface(true);
233 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700234 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800235 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800236 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800237
Andrii Kuliand68501e2017-01-10 22:57:27 -0800238 /**
239 * This tests stack movement between displays and proper stack's, task's and app token's display
240 * container references updates.
241 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800242 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700243 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800244 // Create a second display.
245 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800246
247 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700248 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800249 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800250 assertEquals(dc, stack.getDisplayContent());
251
252 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700253 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
254 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800255 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700256 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800257
258 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700259 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
260 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700261 assertEquals(mDisplayContent, stack.getDisplayContent());
262 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700263 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800264 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800265
266 /**
267 * This tests override configuration updates for display content.
268 */
269 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700270 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700271 final Configuration currentOverrideConfig =
272 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800273
274 // Create new, slightly changed override configuration and apply it to the display.
275 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
276 newOverrideConfig.densityDpi += 120;
277 newOverrideConfig.fontScale += 0.3;
278
Evan Roskye747c3e2018-10-30 20:06:41 -0700279 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800280
281 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700282 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800283 }
284
285 /**
286 * This tests global configuration updates when default display config is updated.
287 */
288 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700289 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700290 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
291 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800292
293 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700294 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800295 newOverrideConfig.densityDpi += 120;
296 newOverrideConfig.fontScale += 0.3;
297
Evan Roskye747c3e2018-10-30 20:06:41 -0700298 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800299
300 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700301 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800302 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
303 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800304
305 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700306 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700307 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700308 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
309 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800310 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800311
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700312 /**
313 * Tests tapping on a stack in different display results in window gaining focus.
314 */
315 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700316 public void testInputEventBringsCorrectDisplayInFocus() {
317 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700318 // Create a second display
319 final DisplayContent dc1 = createNewDisplay();
320
321 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700322 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700323 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700324 final ActivityRecord activity =
325 WindowTestUtils.createTestActivityRecord(dc0);
326 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800327 dc0.configureDisplayPolicy();
328 assertNotNull(dc0.mTapDetector);
329
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700330 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700331 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700332 final ActivityRecord activity1 =
333 WindowTestUtils.createTestActivityRecord(dc0);
334 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800335 dc1.configureDisplayPolicy();
336 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700337
Arthur Hungbe5ce212018-09-13 18:41:56 +0800338 // tap on primary display.
339 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700340 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700341 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800342 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700343
Arthur Hungbe5ce212018-09-13 18:41:56 +0800344 // Tap on secondary display.
345 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700346 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700347 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800348 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700349 }
350
David Stevens46939562017-03-24 13:04:00 -0700351 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700352 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800353 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
354 }
355
356 @Test
357 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
358 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
359 }
360
361 @Test
362 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
363 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
364 }
365
366 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
367 int targetSdk) {
368 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
369
Andrii Kulian0214ed92017-05-16 13:44:05 -0700370 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700371 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700372 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700373 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800374 updateFocusedWindow();
375 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700376 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700377
378 // Check that a new display doesn't affect focus
379 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800380 updateFocusedWindow();
381 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700382 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700383
384 // Add a window to the second display, and it should be focused
385 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700386 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800387 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800388 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800389 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700390 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700391
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800392 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700393 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800394 updateFocusedWindow();
395 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800396 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700397 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800398
399 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100400 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700401 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800402 updateFocusedWindow();
403 assertTrue(!window1.isFocused());
404 assertEquals(window1.getDisplayId(),
405 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200406 }
407
Riddle Hsub2297ad2019-07-26 23:37:25 -0600408 @Test
409 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
410 mWm.mSystemBooted = true;
411 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
412 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
413 TYPE_WALLPAPER, TYPE_APPLICATION);
414
415 // Verify waiting for windows to be drawn.
416 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
417
418 // Verify not waiting for drawn windows.
419 makeWindowsDrawn(windows);
420 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
421 }
422
423 @Test
424 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
425 mWm.mSystemBooted = true;
426 final DisplayContent secondaryDisplay = createNewDisplay();
427 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
428 TYPE_WALLPAPER, TYPE_APPLICATION);
429
430 // Verify not waiting for display without system decorations.
431 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
432 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
433
434 // Verify waiting for non-drawn windows on display with system decorations.
435 reset(secondaryDisplay);
436 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
437 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
438
439 // Verify not waiting for drawn windows on display with system decorations.
440 makeWindowsDrawn(windows);
441 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
442 }
443
444 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
445 final WindowState[] windows = new WindowState[types.length];
446 for (int i = 0; i < types.length; i++) {
447 final int type = types[i];
448 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
449 windows[i].mHasSurface = false;
450 }
451 return windows;
452 }
453
454 private static void makeWindowsDrawn(WindowState[] windows) {
455 for (WindowState window : windows) {
456 window.mHasSurface = true;
457 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
458 }
459 }
460
Bryce Lee27cec322017-03-21 09:41:37 -0700461 /**
462 * This tests setting the maximum ui width on a display.
463 */
464 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700465 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800466 // Prevent base display metrics for test from being updated to the value of real display.
467 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700468 final int baseWidth = 1440;
469 final int baseHeight = 2560;
470 final int baseDensity = 300;
471
Riddle Hsu654a6f92018-07-13 22:59:36 +0800472 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700473
474 final int maxWidth = 300;
475 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
476 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
477
Riddle Hsu654a6f92018-07-13 22:59:36 +0800478 displayContent.setMaxUiWidth(maxWidth);
479 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700480
481 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800482 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
483 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700484
485 final int smallerWidth = 200;
486 final int smallerHeight = 400;
487 final int smallerDensity = 100;
488
489 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800490 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
491 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700492
493 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800494 displayContent.setMaxUiWidth(maxWidth);
495 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700496 }
497
Andrii Kulian92c9a942017-10-10 00:41:41 -0700498 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700499 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800500 final DisplayContent dc = createNewDisplay();
501 dc.mInitialDisplayWidth = 200;
502 dc.mInitialDisplayHeight = 400;
503 final Rect r = new Rect(80, 0, 120, 10);
504 final DisplayCutout cutout = new WmDisplayCutout(
505 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
506 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100507
Riddle Hsu73f53572019-09-23 23:13:01 +0800508 dc.mInitialDisplayCutout = cutout;
509 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
510 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100511
Riddle Hsu73f53572019-09-23 23:13:01 +0800512 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100513 }
514
515 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700516 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800517 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
518 // if the device has no cutout).
519 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800520 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
521 // landscape display let's rotate it.
522 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
523 int tmp = dc.mInitialDisplayHeight;
524 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
525 dc.mInitialDisplayWidth = tmp;
526 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800527 // Rotation may use real display info to compute bound, so here also uses the
528 // same width and height.
529 final int displayWidth = dc.mInitialDisplayWidth;
530 final int displayHeight = dc.mInitialDisplayHeight;
531 final int cutoutWidth = 40;
532 final int cutoutHeight = 10;
533 final int left = (displayWidth - cutoutWidth) / 2;
534 final int top = 0;
535 final int right = (displayWidth + cutoutWidth) / 2;
536 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800537
Riddle Hsu73f53572019-09-23 23:13:01 +0800538 final Rect r1 = new Rect(left, top, right, bottom);
539 final DisplayCutout cutout = new WmDisplayCutout(
540 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
541 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100542
Riddle Hsu73f53572019-09-23 23:13:01 +0800543 dc.mInitialDisplayCutout = cutout;
544 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
545 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100546
Riddle Hsu73f53572019-09-23 23:13:01 +0800547 // ----o---------- -------------
548 // | | | | |
549 // | ------o | o---
550 // | | | |
551 // | | -> | |
552 // | | ---o
553 // | | |
554 // | | -------------
555 final Rect r = new Rect(top, left, bottom, right);
556 assertEquals(new WmDisplayCutout(
557 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
558 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
559 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100560 }
561
562 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700563 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800564 final DisplayContent dc = createNewDisplay();
565 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100566
Riddle Hsu12c05452020-01-09 00:39:52 +0800567 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100568
Riddle Hsu73f53572019-09-23 23:13:01 +0800569 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100570 }
571
572 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700573 @SuppressLint("InlinedApi")
574 public void testOrientationDefinedByKeyguard() {
575 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800576
577 // When display content is created its configuration is not yet initialized, which could
578 // cause unnecessary configuration propagation, so initialize it here.
579 final Configuration config = new Configuration();
580 dc.computeScreenConfiguration(config);
581 dc.onRequestedOverrideConfigurationChanged(config);
582
Andrii Kulian92c9a942017-10-10 00:41:41 -0700583 // Create a window that requests landscape orientation. It will define device orientation
584 // by default.
585 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700586 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700587
588 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
589 keyguard.mHasSurface = true;
590 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
591
592 assertEquals("Screen orientation must be defined by the app window by default",
593 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
594
595 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
596 assertEquals("Visible keyguard must influence device orientation",
597 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
598
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700599 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700600 assertEquals("Keyguard that is going away must not influence device orientation",
601 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
602 }
603
Andrii Kulianf0379de2018-03-14 16:24:07 -0700604 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800605 public void testOrientationForAspectRatio() {
606 final DisplayContent dc = createNewDisplay();
607
608 // When display content is created its configuration is not yet initialized, which could
609 // cause unnecessary configuration propagation, so initialize it here.
610 final Configuration config = new Configuration();
611 dc.computeScreenConfiguration(config);
612 dc.onRequestedOverrideConfigurationChanged(config);
613
614 // Create a window that requests a fixed orientation. It will define device orientation
615 // by default.
616 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
617 "window");
618 window.mHasSurface = true;
619 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
620
621 // --------------------------------
622 // Test non-close-to-square display
623 // --------------------------------
624 dc.mBaseDisplayWidth = 1000;
625 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
626 dc.configureDisplayPolicy();
627
628 assertEquals("Screen orientation must be defined by the window by default.",
629 window.mAttrs.screenOrientation, dc.getOrientation());
630
631 // ----------------------------
632 // Test close-to-square display
633 // ----------------------------
634 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
635 dc.configureDisplayPolicy();
636
637 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
638 SCREEN_ORIENTATION_USER, dc.getOrientation());
639 }
640
641 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700642 public void testDisableDisplayInfoOverrideFromWindowManager() {
643 final DisplayContent dc = createNewDisplay();
644
645 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700646 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700647
648 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700649 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700650 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
651 }
652
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800653 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800654 public void testClearLastFocusWhenReparentingFocusedWindow() {
655 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
656 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
657 defaultDisplay, "window");
658 defaultDisplay.mLastFocus = window;
659 mDisplayContent.mCurrentFocus = window;
660 mDisplayContent.reParentWindowToken(window.mToken);
661
662 assertNull(defaultDisplay.mLastFocus);
663 }
664
665 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800666 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
667 final DisplayContent portraitDisplay = createNewDisplay();
668 portraitDisplay.mInitialDisplayHeight = 2000;
669 portraitDisplay.mInitialDisplayWidth = 1000;
670
Riddle Hsuccf09402019-08-13 00:33:06 +0800671 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800672 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700673 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800674 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
675
676 final DisplayContent landscapeDisplay = createNewDisplay();
677 landscapeDisplay.mInitialDisplayHeight = 1000;
678 landscapeDisplay.mInitialDisplayWidth = 2000;
679
Riddle Hsuccf09402019-08-13 00:33:06 +0800680 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800681 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700682 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800683 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
684 }
685
lumarkff0ab692018-11-05 20:32:30 +0800686 @Test
687 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
688 final DisplayContent newDisplay = createNewDisplay();
689
690 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
691 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
692 appWin.setHasSurface(true);
693 appWin1.setHasSurface(true);
694
695 // Set current input method window on default display, make sure the input method target
696 // is appWin & null on the other display.
697 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
698 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200699 assertEquals("appWin should be IME target window",
700 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800701 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
702
703 // Switch input method window on new display & make sure the input method target also
704 // switched as expected.
705 newDisplay.setInputMethodWindowLocked(mImeWindow);
706 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200707 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800708 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
709 }
710
Garfield Tan90b04282018-12-11 14:04:42 -0800711 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800712 public void testAllowsTopmostFullscreenOrientation() {
713 final DisplayContent dc = createNewDisplay();
714 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800715 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800716
717 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800718 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800719 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800720 .build();
721 doReturn(true).when(stack).isVisible();
722
723 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800724 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800725 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800726 .setWindowingMode(WINDOWING_MODE_FREEFORM)
727 .build();
728 doReturn(true).when(freeformStack).isVisible();
729 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
730
731 assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
732
733 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
734 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
735 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
736
737 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
738 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
739 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
740 }
741
742 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800743 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800744 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700745 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800746 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800747 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
748 ? SCREEN_ORIENTATION_PORTRAIT
749 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800750
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700751 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800752 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800753 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900754 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800755
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700756 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800757
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700758 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
759 ? Configuration.ORIENTATION_PORTRAIT
760 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700761 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800762 }
763
764 @Test
765 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800766 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800767 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800768 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800769 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
770 ? SCREEN_ORIENTATION_PORTRAIT
771 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800772
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700773 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800774 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800775 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900776 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800777
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700778 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800779
Louis Chang677921f2019-12-06 16:44:24 +0800780 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
781 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700782 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800783 }
784
Tarandeep Singha6f35612019-01-11 19:50:46 -0800785 @Test
786 public void testComputeImeParent_app() throws Exception {
787 try (final InsetsModeSession session =
788 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
789 final DisplayContent dc = createNewDisplay();
790 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700791 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800792 dc.computeImeParent());
793 }
794 }
795
796 @Test
797 public void testComputeImeParent_app_notFullscreen() throws Exception {
798 try (final InsetsModeSession session =
799 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
800 final DisplayContent dc = createNewDisplay();
801 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
802 dc.mInputMethodTarget.setWindowingMode(
803 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
804 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
805 }
806 }
807
808 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800809 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700810 spyOn(mAppWindow.mActivityRecord);
811 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800812 mDisplayContent.mInputMethodTarget = mAppWindow;
813 // The surface parent of IME should be the display instead of app window.
814 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
815 }
816
817 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800818 public void testComputeImeParent_noApp() throws Exception {
819 try (final InsetsModeSession session =
820 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
821 final DisplayContent dc = createNewDisplay();
822 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
823 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
824 }
825 }
826
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500827 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100828 public void testUpdateSystemGestureExclusion() throws Exception {
829 final DisplayContent dc = createNewDisplay();
830 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
831 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
832 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
833
Riddle Hsu12c05452020-01-09 00:39:52 +0800834 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100835
836 win.setHasSurface(true);
837 dc.updateSystemGestureExclusion();
838
Riddle Hsu73f53572019-09-23 23:13:01 +0800839 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100840 final ISystemGestureExclusionListener.Stub verifier =
841 new ISystemGestureExclusionListener.Stub() {
842 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200843 public void onSystemGestureExclusionChanged(int displayId, Region actual,
844 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100845 Region expected = Region.obtain();
846 expected.set(10, 20, 30, 40);
847 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800848 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100849 }
850 };
851 try {
852 dc.registerSystemGestureExclusionListener(verifier);
853 } finally {
854 dc.unregisterSystemGestureExclusionListener(verifier);
855 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800856 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100857 }
858
859 @Test
860 public void testCalculateSystemGestureExclusion() throws Exception {
861 final DisplayContent dc = createNewDisplay();
862 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
863 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
864 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
865
866 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
867 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
868 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
869
Riddle Hsu12c05452020-01-09 00:39:52 +0800870 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100871
872 win.setHasSurface(true);
873 win2.setHasSurface(true);
874
875 final Region expected = Region.obtain();
876 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200877 assertEquals(expected, calculateSystemGestureExclusion(dc));
878 }
879
880 private Region calculateSystemGestureExclusion(DisplayContent dc) {
881 Region out = Region.obtain();
882 Region unrestricted = Region.obtain();
883 dc.calculateSystemGestureExclusion(out, unrestricted);
884 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100885 }
886
887 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200888 public void testCalculateSystemGestureExclusion_modal() throws Exception {
889 final DisplayContent dc = createNewDisplay();
890 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
891 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
892 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
893
894 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
895 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
896 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
897 win2.getAttrs().width = 10;
898 win2.getAttrs().height = 10;
899 win2.setSystemGestureExclusion(Collections.emptyList());
900
Riddle Hsu12c05452020-01-09 00:39:52 +0800901 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200902
903 win.setHasSurface(true);
904 win2.setHasSurface(true);
905
906 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200907 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200908 }
909
910 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200911 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200912 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200913
Riddle Hsu73f53572019-09-23 23:13:01 +0800914 final DisplayContent dc = createNewDisplay();
915 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
916 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
917 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
918 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
919 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
920 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
921 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700922 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200923
Riddle Hsu12c05452020-01-09 00:39:52 +0800924 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +0200925
Riddle Hsu73f53572019-09-23 23:13:01 +0800926 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200927
Riddle Hsu73f53572019-09-23 23:13:01 +0800928 final Region expected = Region.obtain();
929 expected.set(dc.getBounds());
930 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200931
Riddle Hsu73f53572019-09-23 23:13:01 +0800932 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200933 }
934
935 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +0800936 public void testRequestResizeForEmptyFrames() {
937 final WindowState win = mChildAppWindowAbove;
938 makeWindowVisible(win, win.getParentWindow());
939 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
940 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
941 win.mAttrs.gravity = Gravity.CENTER;
942 performLayout(mDisplayContent);
943
944 // The frame is empty because the requested height is zero.
945 assertTrue(win.getFrameLw().isEmpty());
946 // The window should be scheduled to resize then the client may report a new non-empty size.
947 win.updateResizingWindowIfNeeded();
948 assertThat(mWm.mResizingWindows).contains(win);
949 }
950
951 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500952 public void testOrientationChangeLogging() {
953 MetricsLogger mockLogger = mock(MetricsLogger.class);
954 Configuration oldConfig = new Configuration();
955 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
956
957 Configuration newConfig = new Configuration();
958 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800959 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500960 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
961 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +0800962 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500963
964 displayContent.onConfigurationChanged(newConfig);
965
966 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
967 verify(mockLogger).write(logMakerCaptor.capture());
968 assertThat(logMakerCaptor.getValue().getCategory(),
969 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
970 assertThat(logMakerCaptor.getValue().getSubtype(),
971 is(Configuration.ORIENTATION_PORTRAIT));
972 }
973
Evan Rosky69cace42019-09-20 16:28:13 -0700974 @Test
975 public void testRemoteRotation() {
976 DisplayContent dc = createNewDisplay();
977
978 final DisplayRotation dr = dc.getDisplayRotation();
979 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
980 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
981 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +0800982 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -0700983 Mockito.doAnswer(
984 invocation -> {
985 continued[0] = true;
986 return true;
Louis Chang677921f2019-12-06 16:44:24 +0800987 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -0700988 final boolean[] called = new boolean[1];
989 mWm.mDisplayRotationController =
990 new IDisplayWindowRotationController.Stub() {
991 @Override
992 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
993 IDisplayWindowRotationCallback callback) {
994 called[0] = true;
995
996 try {
997 callback.continueRotateDisplay(toRotation, null);
998 } catch (RemoteException e) {
999 assertTrue(false);
1000 }
1001 }
1002 };
1003
1004 // kill any existing rotation animation (vestigial from test setup).
1005 dc.setRotationAnimation(null);
1006
1007 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1008 assertTrue(called[0]);
1009 waitUntilHandlersIdle();
1010 assertTrue(continued[0]);
1011 }
1012
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001013 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001014 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001015 }
1016
Bryce Lee27cec322017-03-21 09:41:37 -07001017 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1018 int expectedBaseHeight, int expectedBaseDensity) {
1019 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1020 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1021 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1022 }
1023
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001024 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001025 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001026 }
1027
Riddle Hsu12c05452020-01-09 00:39:52 +08001028 private void performLayout(DisplayContent dc) {
1029 dc.setLayoutNeeded();
1030 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1031 }
1032
Riddle Hsu654a6f92018-07-13 22:59:36 +08001033 /**
1034 * Create DisplayContent that does not update display base/initial values from device to keep
1035 * the values set by test.
1036 */
1037 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001038 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001039 doNothing().when(displayContent).updateDisplayInfo();
1040 return displayContent;
1041 }
1042
Adrian Roos0f9368c2018-04-08 10:59:08 -07001043 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1044 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001045
1046 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001047 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001048 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1049
1050 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001051
1052 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001053 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001054 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1055 }
1056
1057 private static List<WindowState> reverseList(List<WindowState> list) {
1058 final ArrayList<WindowState> result = new ArrayList<>(list);
1059 Collections.reverse(result);
1060 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001061 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001062
Arthur Hungbe5ce212018-09-13 18:41:56 +08001063 private void tapOnDisplay(final DisplayContent dc) {
1064 final DisplayMetrics dm = dc.getDisplayMetrics();
1065 final float x = dm.widthPixels / 2;
1066 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001067 final long downTime = SystemClock.uptimeMillis();
1068 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001069 // sending ACTION_DOWN
1070 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001071 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001072 downTime,
1073 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001074 x,
1075 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001076 0 /*metaState*/);
1077 downEvent.setDisplayId(dc.getDisplayId());
1078 dc.mTapDetector.onPointerEvent(downEvent);
1079
1080 // sending ACTION_UP
1081 final MotionEvent upEvent = MotionEvent.obtain(
1082 downTime,
1083 eventTime,
1084 MotionEvent.ACTION_UP,
1085 x,
1086 y,
1087 0 /*metaState*/);
1088 upEvent.setDisplayId(dc.getDisplayId());
1089 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001090 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001091}