blob: 5fbfd7d33b5afc8e04394bced343fae965605839 [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
Adrian Roos5251b1d2018-03-23 18:57:43 +010060import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080061import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070062import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080063import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080064import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010065import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080066import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070067import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080068import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080069
Andrii Kulian92c9a942017-10-10 00:41:41 -070070import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080071import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080072import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010073import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010074import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050075import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070076import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070077import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070078import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070079import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010080import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080081import android.view.Gravity;
Evan Rosky69cace42019-09-20 16:28:13 -070082import android.view.IDisplayWindowRotationCallback;
83import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010084import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070085import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010086import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080087import android.view.ViewRootImpl;
88import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070089
Brett Chabota26eda92018-07-23 13:08:30 -070090import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070091
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050092import com.android.internal.logging.MetricsLogger;
93import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010094import com.android.server.wm.utils.WmDisplayCutout;
95
Brett Chabota26eda92018-07-23 13:08:30 -070096import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080097import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -080098import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050099import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700100
Adrian Roos0f9368c2018-04-08 10:59:08 -0700101import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800102import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700103import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800104import java.util.LinkedList;
105import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700106
107/**
108 * Tests for the {@link DisplayContent} class.
109 *
110 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900111 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700112 */
113@SmallTest
114@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800115@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800116public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700117
118 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700119 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800120 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700121 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700122 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900123 // Wait until everything in animation handler get executed to prevent the exiting window
124 // from being removed during WindowSurfacePlacer Traversal.
125 waitUntilHandlersIdle();
126
Garfield Tane8d84ab2019-10-11 09:49:40 -0700127 exitingApp.mIsExiting = true;
Wale Ogunwale8577a052019-10-26 23:22:34 -0700128 exitingApp.getTask().getTaskStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700129
Wale Ogunwale34247952017-02-19 11:57:53 -0800130 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700131 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800132 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700133 mChildAppWindowBelow,
134 mAppWindow,
135 mChildAppWindowAbove,
136 mDockedDividerWindow,
137 mStatusBarWindow,
138 mNavBarWindow,
139 mImeWindow,
140 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800141 }
142
143 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700144 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800145 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700146 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800147
lumarkff0ab692018-11-05 20:32:30 +0800148 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800149
Wale Ogunwale34247952017-02-19 11:57:53 -0800150 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700151 mWallpaperWindow,
152 mChildAppWindowBelow,
153 mAppWindow,
154 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800155 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700156 mImeWindow,
157 mImeDialogWindow,
158 mDockedDividerWindow,
159 mStatusBarWindow,
160 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800161 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800162
Wale Ogunwale34247952017-02-19 11:57:53 -0800163 @Test
lumarkff0ab692018-11-05 20:32:30 +0800164 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
165 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800166
Wale Ogunwale34247952017-02-19 11:57:53 -0800167 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700168 mWallpaperWindow,
169 mChildAppWindowBelow,
170 mAppWindow,
171 mChildAppWindowAbove,
172 mImeWindow,
173 mImeDialogWindow,
174 mDockedDividerWindow,
175 mStatusBarWindow,
176 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700177 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800178
179 @Test
lumarkff0ab692018-11-05 20:32:30 +0800180 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
181 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800182
Wale Ogunwale34247952017-02-19 11:57:53 -0800183 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700184 mWallpaperWindow,
185 mChildAppWindowBelow,
186 mAppWindow,
187 mChildAppWindowAbove,
188 mDockedDividerWindow,
189 mStatusBarWindow,
190 mImeWindow,
191 mImeDialogWindow,
192 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800193 }
194
195 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700196 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800197 // This window is set-up to be z-ordered between some windows that go in the same token like
198 // the nav bar and status bar.
199 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700200 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800201
Wale Ogunwale34247952017-02-19 11:57:53 -0800202 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700203 mWallpaperWindow,
204 mChildAppWindowBelow,
205 mAppWindow,
206 mChildAppWindowAbove,
207 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800208 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700209 mStatusBarWindow,
210 mNavBarWindow,
211 mImeWindow,
212 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800213 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800214
Wale Ogunwale34247952017-02-19 11:57:53 -0800215 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700216 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800217 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700218 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800219 appWin.setHasSurface(true);
220 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700221 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800222 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800223 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800224
Wale Ogunwale34247952017-02-19 11:57:53 -0800225 // Verify that an child window can be an ime target.
226 final WindowState childWin = createWindow(appWin,
227 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
228 childWin.setHasSurface(true);
229 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700230 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800231 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800232 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800233
Andrii Kuliand68501e2017-01-10 22:57:27 -0800234 /**
235 * This tests stack movement between displays and proper stack's, task's and app token's display
236 * container references updates.
237 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800238 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700239 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800240 // Create a second display.
241 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800242
243 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700244 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800245 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
246 assertEquals(dc, stack.getParent().getParent());
247 assertEquals(dc, stack.getDisplayContent());
248
249 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700250 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
251 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800252 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700253 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800254
255 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700256 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
257 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
258 assertEquals(mDisplayContent, stack.getParent().getParent());
259 assertEquals(mDisplayContent, stack.getDisplayContent());
260 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700261 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800262 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800263
264 /**
265 * This tests override configuration updates for display content.
266 */
267 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700268 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700269 final Configuration currentOverrideConfig =
270 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800271
272 // Create new, slightly changed override configuration and apply it to the display.
273 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
274 newOverrideConfig.densityDpi += 120;
275 newOverrideConfig.fontScale += 0.3;
276
Evan Roskye747c3e2018-10-30 20:06:41 -0700277 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800278
279 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700280 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800281 }
282
283 /**
284 * This tests global configuration updates when default display config is updated.
285 */
286 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700287 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700288 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
289 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800290
291 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700292 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800293 newOverrideConfig.densityDpi += 120;
294 newOverrideConfig.fontScale += 0.3;
295
Evan Roskye747c3e2018-10-30 20:06:41 -0700296 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800297
298 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700299 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800300 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
301 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800302
303 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700304 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700305 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700306 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
307 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800308 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800309
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700310 /**
311 * Tests tapping on a stack in different display results in window gaining focus.
312 */
313 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700314 public void testInputEventBringsCorrectDisplayInFocus() {
315 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700316 // Create a second display
317 final DisplayContent dc1 = createNewDisplay();
318
319 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700320 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700321 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700322 final ActivityRecord activity =
323 WindowTestUtils.createTestActivityRecord(dc0);
324 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800325 dc0.configureDisplayPolicy();
326 assertNotNull(dc0.mTapDetector);
327
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700328 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700329 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700330 final ActivityRecord activity1 =
331 WindowTestUtils.createTestActivityRecord(dc0);
332 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800333 dc1.configureDisplayPolicy();
334 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700335
Arthur Hungbe5ce212018-09-13 18:41:56 +0800336 // tap on primary display.
337 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700338 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800340 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700341
Arthur Hungbe5ce212018-09-13 18:41:56 +0800342 // Tap on secondary display.
343 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700344 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700345 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800346 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700347 }
348
David Stevens46939562017-03-24 13:04:00 -0700349 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700350 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800351 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
352 }
353
354 @Test
355 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
356 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
357 }
358
359 @Test
360 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
361 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
362 }
363
364 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
365 int targetSdk) {
366 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
367
Andrii Kulian0214ed92017-05-16 13:44:05 -0700368 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700369 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700370 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700371 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800372 updateFocusedWindow();
373 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700374 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700375
376 // Check that a new display doesn't affect focus
377 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800378 updateFocusedWindow();
379 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700380 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700381
382 // Add a window to the second display, and it should be focused
383 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700384 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800385 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800386 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800387 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700388 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700389
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800390 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700391 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800392 updateFocusedWindow();
393 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800394 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700395 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800396
397 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100398 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700399 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800400 updateFocusedWindow();
401 assertTrue(!window1.isFocused());
402 assertEquals(window1.getDisplayId(),
403 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200404 }
405
Riddle Hsub2297ad2019-07-26 23:37:25 -0600406 @Test
407 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
408 mWm.mSystemBooted = true;
409 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
410 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
411 TYPE_WALLPAPER, TYPE_APPLICATION);
412
413 // Verify waiting for windows to be drawn.
414 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
415
416 // Verify not waiting for drawn windows.
417 makeWindowsDrawn(windows);
418 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
419 }
420
421 @Test
422 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
423 mWm.mSystemBooted = true;
424 final DisplayContent secondaryDisplay = createNewDisplay();
425 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
426 TYPE_WALLPAPER, TYPE_APPLICATION);
427
428 // Verify not waiting for display without system decorations.
429 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
430 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
431
432 // Verify waiting for non-drawn windows on display with system decorations.
433 reset(secondaryDisplay);
434 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
435 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
436
437 // Verify not waiting for drawn windows on display with system decorations.
438 makeWindowsDrawn(windows);
439 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
440 }
441
442 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
443 final WindowState[] windows = new WindowState[types.length];
444 for (int i = 0; i < types.length; i++) {
445 final int type = types[i];
446 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
447 windows[i].mHasSurface = false;
448 }
449 return windows;
450 }
451
452 private static void makeWindowsDrawn(WindowState[] windows) {
453 for (WindowState window : windows) {
454 window.mHasSurface = true;
455 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
456 }
457 }
458
Bryce Lee27cec322017-03-21 09:41:37 -0700459 /**
460 * This tests setting the maximum ui width on a display.
461 */
462 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700463 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800464 // Prevent base display metrics for test from being updated to the value of real display.
465 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700466 final int baseWidth = 1440;
467 final int baseHeight = 2560;
468 final int baseDensity = 300;
469
Riddle Hsu654a6f92018-07-13 22:59:36 +0800470 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700471
472 final int maxWidth = 300;
473 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
474 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
475
Riddle Hsu654a6f92018-07-13 22:59:36 +0800476 displayContent.setMaxUiWidth(maxWidth);
477 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700478
479 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800480 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
481 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700482
483 final int smallerWidth = 200;
484 final int smallerHeight = 400;
485 final int smallerDensity = 100;
486
487 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800488 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
489 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700490
491 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800492 displayContent.setMaxUiWidth(maxWidth);
493 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700494 }
495
Andrii Kulian92c9a942017-10-10 00:41:41 -0700496 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700497 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800498 final DisplayContent dc = createNewDisplay();
499 dc.mInitialDisplayWidth = 200;
500 dc.mInitialDisplayHeight = 400;
501 final Rect r = new Rect(80, 0, 120, 10);
502 final DisplayCutout cutout = new WmDisplayCutout(
503 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
504 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100505
Riddle Hsu73f53572019-09-23 23:13:01 +0800506 dc.mInitialDisplayCutout = cutout;
507 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
508 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100509
Riddle Hsu73f53572019-09-23 23:13:01 +0800510 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100511 }
512
513 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700514 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800515 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
516 // if the device has no cutout).
517 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
518 // Rotation may use real display info to compute bound, so here also uses the
519 // same width and height.
520 final int displayWidth = dc.mInitialDisplayWidth;
521 final int displayHeight = dc.mInitialDisplayHeight;
522 final int cutoutWidth = 40;
523 final int cutoutHeight = 10;
524 final int left = (displayWidth - cutoutWidth) / 2;
525 final int top = 0;
526 final int right = (displayWidth + cutoutWidth) / 2;
527 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800528
Riddle Hsu73f53572019-09-23 23:13:01 +0800529 final Rect r1 = new Rect(left, top, right, bottom);
530 final DisplayCutout cutout = new WmDisplayCutout(
531 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
532 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100533
Riddle Hsu73f53572019-09-23 23:13:01 +0800534 dc.mInitialDisplayCutout = cutout;
535 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
536 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100537
Riddle Hsu73f53572019-09-23 23:13:01 +0800538 // ----o---------- -------------
539 // | | | | |
540 // | ------o | o---
541 // | | | |
542 // | | -> | |
543 // | | ---o
544 // | | |
545 // | | -------------
546 final Rect r = new Rect(top, left, bottom, right);
547 assertEquals(new WmDisplayCutout(
548 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
549 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
550 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100551 }
552
553 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700554 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800555 final DisplayContent dc = createNewDisplay();
556 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100557
Riddle Hsu73f53572019-09-23 23:13:01 +0800558 dc.setLayoutNeeded();
559 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100560
Riddle Hsu73f53572019-09-23 23:13:01 +0800561 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100562 }
563
564 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700565 @SuppressLint("InlinedApi")
566 public void testOrientationDefinedByKeyguard() {
567 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800568
569 // When display content is created its configuration is not yet initialized, which could
570 // cause unnecessary configuration propagation, so initialize it here.
571 final Configuration config = new Configuration();
572 dc.computeScreenConfiguration(config);
573 dc.onRequestedOverrideConfigurationChanged(config);
574
Andrii Kulian92c9a942017-10-10 00:41:41 -0700575 // Create a window that requests landscape orientation. It will define device orientation
576 // by default.
577 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700578 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700579
580 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
581 keyguard.mHasSurface = true;
582 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
583
584 assertEquals("Screen orientation must be defined by the app window by default",
585 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
586
587 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
588 assertEquals("Visible keyguard must influence device orientation",
589 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
590
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700591 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700592 assertEquals("Keyguard that is going away must not influence device orientation",
593 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
594 }
595
Andrii Kulianf0379de2018-03-14 16:24:07 -0700596 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800597 public void testOrientationForAspectRatio() {
598 final DisplayContent dc = createNewDisplay();
599
600 // When display content is created its configuration is not yet initialized, which could
601 // cause unnecessary configuration propagation, so initialize it here.
602 final Configuration config = new Configuration();
603 dc.computeScreenConfiguration(config);
604 dc.onRequestedOverrideConfigurationChanged(config);
605
606 // Create a window that requests a fixed orientation. It will define device orientation
607 // by default.
608 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
609 "window");
610 window.mHasSurface = true;
611 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
612
613 // --------------------------------
614 // Test non-close-to-square display
615 // --------------------------------
616 dc.mBaseDisplayWidth = 1000;
617 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
618 dc.configureDisplayPolicy();
619
620 assertEquals("Screen orientation must be defined by the window by default.",
621 window.mAttrs.screenOrientation, dc.getOrientation());
622
623 // ----------------------------
624 // Test close-to-square display
625 // ----------------------------
626 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
627 dc.configureDisplayPolicy();
628
629 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
630 SCREEN_ORIENTATION_USER, dc.getOrientation());
631 }
632
633 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700634 public void testDisableDisplayInfoOverrideFromWindowManager() {
635 final DisplayContent dc = createNewDisplay();
636
637 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700638 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700639
640 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700641 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700642 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
643 }
644
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800645 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800646 public void testClearLastFocusWhenReparentingFocusedWindow() {
647 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
648 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
649 defaultDisplay, "window");
650 defaultDisplay.mLastFocus = window;
651 mDisplayContent.mCurrentFocus = window;
652 mDisplayContent.reParentWindowToken(window.mToken);
653
654 assertNull(defaultDisplay.mLastFocus);
655 }
656
657 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800658 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
659 final DisplayContent portraitDisplay = createNewDisplay();
660 portraitDisplay.mInitialDisplayHeight = 2000;
661 portraitDisplay.mInitialDisplayWidth = 1000;
662
Riddle Hsuccf09402019-08-13 00:33:06 +0800663 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800664 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700665 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800666 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
667
668 final DisplayContent landscapeDisplay = createNewDisplay();
669 landscapeDisplay.mInitialDisplayHeight = 1000;
670 landscapeDisplay.mInitialDisplayWidth = 2000;
671
Riddle Hsuccf09402019-08-13 00:33:06 +0800672 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800673 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700674 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800675 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
676 }
677
lumarkff0ab692018-11-05 20:32:30 +0800678 @Test
679 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
680 final DisplayContent newDisplay = createNewDisplay();
681
682 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
683 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
684 appWin.setHasSurface(true);
685 appWin1.setHasSurface(true);
686
687 // Set current input method window on default display, make sure the input method target
688 // is appWin & null on the other display.
689 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
690 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200691 assertEquals("appWin should be IME target window",
692 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800693 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
694
695 // Switch input method window on new display & make sure the input method target also
696 // switched as expected.
697 newDisplay.setInputMethodWindowLocked(mImeWindow);
698 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200699 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800700 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
701 }
702
Garfield Tan90b04282018-12-11 14:04:42 -0800703 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800704 public void testAllowsTopmostFullscreenOrientation() {
705 final DisplayContent dc = createNewDisplay();
706 dc.getDisplayRotation().setFixedToUserRotation(
707 DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
708
709 final ActivityStack stack =
710 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800711 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800712 .build();
713 doReturn(true).when(stack).isVisible();
714
715 final ActivityStack freeformStack =
716 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800717 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800718 .setWindowingMode(WINDOWING_MODE_FREEFORM)
719 .build();
720 doReturn(true).when(freeformStack).isVisible();
721 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
722
723 assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
724
725 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
726 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
727 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
728
729 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
730 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
731 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
732 }
733
734 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800735 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800736 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700737 dc.getDisplayRotation().setFixedToUserRotation(
738 DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800739 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
740 ? SCREEN_ORIENTATION_PORTRAIT
741 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800742
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700743 final ActivityStack stack =
744 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800745 .setDisplay(dc).build();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800746 final ActivityRecord activity = stack.topTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800747
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700748 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800749
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700750 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
751 ? Configuration.ORIENTATION_PORTRAIT
752 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700753 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800754 }
755
756 @Test
757 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800758 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800759 dc.getDisplayRotation().setFixedToUserRotation(
760 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800761 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
762 ? SCREEN_ORIENTATION_PORTRAIT
763 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800764
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700765 final ActivityStack stack =
766 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800767 .setDisplay(dc).build();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800768 final ActivityRecord activity = stack.topTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800769
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700770 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800771
Louis Chang2453d062019-11-19 22:30:48 +0800772 // TODO(display-merge): Remove cast
773 verify((ActivityDisplay) dc, never()).updateDisplayOverrideConfigurationLocked(any(),
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700774 eq(activity), anyBoolean(), same(null));
775 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800776 }
777
Tarandeep Singha6f35612019-01-11 19:50:46 -0800778 @Test
779 public void testComputeImeParent_app() throws Exception {
780 try (final InsetsModeSession session =
781 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
782 final DisplayContent dc = createNewDisplay();
783 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700784 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800785 dc.computeImeParent());
786 }
787 }
788
789 @Test
790 public void testComputeImeParent_app_notFullscreen() throws Exception {
791 try (final InsetsModeSession session =
792 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
793 final DisplayContent dc = createNewDisplay();
794 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
795 dc.mInputMethodTarget.setWindowingMode(
796 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
797 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
798 }
799 }
800
801 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800802 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700803 spyOn(mAppWindow.mActivityRecord);
804 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800805 mDisplayContent.mInputMethodTarget = mAppWindow;
806 // The surface parent of IME should be the display instead of app window.
807 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
808 }
809
810 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800811 public void testComputeImeParent_noApp() throws Exception {
812 try (final InsetsModeSession session =
813 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
814 final DisplayContent dc = createNewDisplay();
815 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
816 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
817 }
818 }
819
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500820 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100821 public void testUpdateSystemGestureExclusion() throws Exception {
822 final DisplayContent dc = createNewDisplay();
823 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
824 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
825 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
826
827 dc.setLayoutNeeded();
828 dc.performLayout(true /* initial */, false /* updateImeWindows */);
829
830 win.setHasSurface(true);
831 dc.updateSystemGestureExclusion();
832
Riddle Hsu73f53572019-09-23 23:13:01 +0800833 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100834 final ISystemGestureExclusionListener.Stub verifier =
835 new ISystemGestureExclusionListener.Stub() {
836 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200837 public void onSystemGestureExclusionChanged(int displayId, Region actual,
838 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100839 Region expected = Region.obtain();
840 expected.set(10, 20, 30, 40);
841 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800842 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100843 }
844 };
845 try {
846 dc.registerSystemGestureExclusionListener(verifier);
847 } finally {
848 dc.unregisterSystemGestureExclusionListener(verifier);
849 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800850 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100851 }
852
853 @Test
854 public void testCalculateSystemGestureExclusion() throws Exception {
855 final DisplayContent dc = createNewDisplay();
856 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
857 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
858 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
859
860 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
861 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
862 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
863
864 dc.setLayoutNeeded();
865 dc.performLayout(true /* initial */, false /* updateImeWindows */);
866
867 win.setHasSurface(true);
868 win2.setHasSurface(true);
869
870 final Region expected = Region.obtain();
871 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200872 assertEquals(expected, calculateSystemGestureExclusion(dc));
873 }
874
875 private Region calculateSystemGestureExclusion(DisplayContent dc) {
876 Region out = Region.obtain();
877 Region unrestricted = Region.obtain();
878 dc.calculateSystemGestureExclusion(out, unrestricted);
879 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100880 }
881
882 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200883 public void testCalculateSystemGestureExclusion_modal() throws Exception {
884 final DisplayContent dc = createNewDisplay();
885 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
886 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
887 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
888
889 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
890 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
891 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
892 win2.getAttrs().width = 10;
893 win2.getAttrs().height = 10;
894 win2.setSystemGestureExclusion(Collections.emptyList());
895
896 dc.setLayoutNeeded();
897 dc.performLayout(true /* initial */, false /* updateImeWindows */);
898
899 win.setHasSurface(true);
900 win2.setHasSurface(true);
901
902 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200903 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200904 }
905
906 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200907 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200908 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200909
Riddle Hsu73f53572019-09-23 23:13:01 +0800910 final DisplayContent dc = createNewDisplay();
911 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
912 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
913 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
914 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
915 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
916 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
917 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700918 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200919
Riddle Hsu73f53572019-09-23 23:13:01 +0800920 dc.setLayoutNeeded();
921 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos019a52b2019-07-02 16:47:44 +0200922
Riddle Hsu73f53572019-09-23 23:13:01 +0800923 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200924
Riddle Hsu73f53572019-09-23 23:13:01 +0800925 final Region expected = Region.obtain();
926 expected.set(dc.getBounds());
927 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200928
Riddle Hsu73f53572019-09-23 23:13:01 +0800929 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200930 }
931
932 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500933 public void testOrientationChangeLogging() {
934 MetricsLogger mockLogger = mock(MetricsLogger.class);
935 Configuration oldConfig = new Configuration();
936 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
937
938 Configuration newConfig = new Configuration();
939 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800940 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500941 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
942 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +0800943 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500944
945 displayContent.onConfigurationChanged(newConfig);
946
947 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
948 verify(mockLogger).write(logMakerCaptor.capture());
949 assertThat(logMakerCaptor.getValue().getCategory(),
950 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
951 assertThat(logMakerCaptor.getValue().getSubtype(),
952 is(Configuration.ORIENTATION_PORTRAIT));
953 }
954
Evan Rosky69cace42019-09-20 16:28:13 -0700955 @Test
956 public void testRemoteRotation() {
957 DisplayContent dc = createNewDisplay();
958
959 final DisplayRotation dr = dc.getDisplayRotation();
960 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
961 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
962 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +0800963 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -0700964 Mockito.doAnswer(
965 invocation -> {
966 continued[0] = true;
967 return true;
Louis Chang2453d062019-11-19 22:30:48 +0800968 }).when((ActivityDisplay) dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -0700969 final boolean[] called = new boolean[1];
970 mWm.mDisplayRotationController =
971 new IDisplayWindowRotationController.Stub() {
972 @Override
973 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
974 IDisplayWindowRotationCallback callback) {
975 called[0] = true;
976
977 try {
978 callback.continueRotateDisplay(toRotation, null);
979 } catch (RemoteException e) {
980 assertTrue(false);
981 }
982 }
983 };
984
985 // kill any existing rotation animation (vestigial from test setup).
986 dc.setRotationAnimation(null);
987
988 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
989 assertTrue(called[0]);
990 waitUntilHandlersIdle();
991 assertTrue(continued[0]);
992 }
993
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800994 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700995 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800996 }
997
Bryce Lee27cec322017-03-21 09:41:37 -0700998 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
999 int expectedBaseHeight, int expectedBaseDensity) {
1000 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1001 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1002 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1003 }
1004
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001005 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001006 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001007 }
1008
Riddle Hsu654a6f92018-07-13 22:59:36 +08001009 /**
1010 * Create DisplayContent that does not update display base/initial values from device to keep
1011 * the values set by test.
1012 */
1013 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001014 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001015 doNothing().when(displayContent).updateDisplayInfo();
1016 return displayContent;
1017 }
1018
Adrian Roos0f9368c2018-04-08 10:59:08 -07001019 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1020 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001021
1022 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001023 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001024 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1025
1026 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001027
1028 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001029 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001030 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1031 }
1032
1033 private static List<WindowState> reverseList(List<WindowState> list) {
1034 final ArrayList<WindowState> result = new ArrayList<>(list);
1035 Collections.reverse(result);
1036 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001037 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001038
Arthur Hungbe5ce212018-09-13 18:41:56 +08001039 private void tapOnDisplay(final DisplayContent dc) {
1040 final DisplayMetrics dm = dc.getDisplayMetrics();
1041 final float x = dm.widthPixels / 2;
1042 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001043 final long downTime = SystemClock.uptimeMillis();
1044 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001045 // sending ACTION_DOWN
1046 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001047 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001048 downTime,
1049 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001050 x,
1051 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001052 0 /*metaState*/);
1053 downEvent.setDisplayId(dc.getDisplayId());
1054 dc.mTapDetector.onPointerEvent(downEvent);
1055
1056 // sending ACTION_UP
1057 final MotionEvent upEvent = MotionEvent.obtain(
1058 downTime,
1059 eventTime,
1060 MotionEvent.ACTION_UP,
1061 x,
1062 y,
1063 0 /*metaState*/);
1064 upEvent.setDisplayId(dc.getDisplayId());
1065 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001066 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001067}