blob: bbba0a00e861fa2c3fd91e6e2a1ae3a0f19b666c [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Andrii Kulian92c9a942017-10-10 00:41:41 -070019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080022import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080023import static android.os.Build.VERSION_CODES.P;
24import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080025import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020026import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
27import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010028import static android.view.DisplayCutout.fromBoundingRect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010029import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
30import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Wale Ogunwale34247952017-02-19 11:57:53 -080031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
32import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080033import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080034import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070035import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080036import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Brett Chabota26eda92018-07-23 13:08:30 -070037
Garfield Tan90b04282018-12-11 14:04:42 -080038import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
39import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090040import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080041import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080042import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
43import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
44import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090045import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080046import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090047import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
48import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070049import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080050import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080051
Adrian Roos5251b1d2018-03-23 18:57:43 +010052import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080053import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070054import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080055import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080056import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010057import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080058import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080059import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080060
Andrii Kulian92c9a942017-10-10 00:41:41 -070061import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080062import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080063import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010064import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010065import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050066import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070067import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070068import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070069import android.util.DisplayMetrics;
Adrian Roos4ffc8972019-02-07 20:45:11 +010070import android.util.MutableBoolean;
Adrian Roos1cf585052018-01-03 18:43:27 +010071import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080072import android.view.Gravity;
Adrian Roos4ffc8972019-02-07 20:45:11 +010073import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070074import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010075import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080076import android.view.ViewRootImpl;
77import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070078
Brett Chabota26eda92018-07-23 13:08:30 -070079import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070080
Garfield Tan90b04282018-12-11 14:04:42 -080081import com.android.dx.mockito.inline.extended.ExtendedMockito;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050082import com.android.internal.logging.MetricsLogger;
83import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010084import com.android.server.wm.utils.WmDisplayCutout;
85
Brett Chabota26eda92018-07-23 13:08:30 -070086import org.junit.Test;
Garfield Tan90b04282018-12-11 14:04:42 -080087import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050088import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070089
Adrian Roos0f9368c2018-04-08 10:59:08 -070090import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080091import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070092import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080093import java.util.LinkedList;
94import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070095
96/**
97 * Tests for the {@link DisplayContent} class.
98 *
99 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900100 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700101 */
102@SmallTest
103@Presubmit
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800104public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700105
106 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700107 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800108 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700109 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700110 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900111 // Wait until everything in animation handler get executed to prevent the exiting window
112 // from being removed during WindowSurfacePlacer Traversal.
113 waitUntilHandlersIdle();
114
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700115 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -0800116 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700117
Wale Ogunwale34247952017-02-19 11:57:53 -0800118 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700119 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800120 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700121 mChildAppWindowBelow,
122 mAppWindow,
123 mChildAppWindowAbove,
124 mDockedDividerWindow,
125 mStatusBarWindow,
126 mNavBarWindow,
127 mImeWindow,
128 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800129 }
130
131 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700132 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800133 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700134 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800135
lumarkff0ab692018-11-05 20:32:30 +0800136 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800137
Wale Ogunwale34247952017-02-19 11:57:53 -0800138 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700139 mWallpaperWindow,
140 mChildAppWindowBelow,
141 mAppWindow,
142 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800143 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700144 mImeWindow,
145 mImeDialogWindow,
146 mDockedDividerWindow,
147 mStatusBarWindow,
148 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800149 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800150
Wale Ogunwale34247952017-02-19 11:57:53 -0800151 @Test
lumarkff0ab692018-11-05 20:32:30 +0800152 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
153 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800154
Wale Ogunwale34247952017-02-19 11:57:53 -0800155 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700156 mWallpaperWindow,
157 mChildAppWindowBelow,
158 mAppWindow,
159 mChildAppWindowAbove,
160 mImeWindow,
161 mImeDialogWindow,
162 mDockedDividerWindow,
163 mStatusBarWindow,
164 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700165 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800166
167 @Test
lumarkff0ab692018-11-05 20:32:30 +0800168 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
169 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -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 mDockedDividerWindow,
177 mStatusBarWindow,
178 mImeWindow,
179 mImeDialogWindow,
180 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800181 }
182
183 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700184 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800185 // This window is set-up to be z-ordered between some windows that go in the same token like
186 // the nav bar and status bar.
187 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700188 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800189
Wale Ogunwale34247952017-02-19 11:57:53 -0800190 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700191 mWallpaperWindow,
192 mChildAppWindowBelow,
193 mAppWindow,
194 mChildAppWindowAbove,
195 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800196 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700197 mStatusBarWindow,
198 mNavBarWindow,
199 mImeWindow,
200 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800201 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800202
Wale Ogunwale34247952017-02-19 11:57:53 -0800203 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700204 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800205 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700206 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800207 appWin.setHasSurface(true);
208 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700209 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800210 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800211 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800212
Wale Ogunwale34247952017-02-19 11:57:53 -0800213 // Verify that an child window can be an ime target.
214 final WindowState childWin = createWindow(appWin,
215 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
216 childWin.setHasSurface(true);
217 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700218 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800219 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800220 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800221
Andrii Kuliand68501e2017-01-10 22:57:27 -0800222 /**
223 * This tests stack movement between displays and proper stack's, task's and app token's display
224 * container references updates.
225 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800226 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700227 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800228 // Create a second display.
229 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800230
231 // Add stack with activity.
232 final TaskStack stack = createTaskStackOnDisplay(dc);
233 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
234 assertEquals(dc, stack.getParent().getParent());
235 assertEquals(dc, stack.getDisplayContent());
236
237 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800238 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
239 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800240 task.addChild(token, 0);
241 assertEquals(dc, task.getDisplayContent());
242 assertEquals(dc, token.getDisplayContent());
243
244 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700245 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
246 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
247 assertEquals(mDisplayContent, stack.getParent().getParent());
248 assertEquals(mDisplayContent, stack.getDisplayContent());
249 assertEquals(mDisplayContent, task.getDisplayContent());
250 assertEquals(mDisplayContent, token.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800251 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800252
253 /**
254 * This tests override configuration updates for display content.
255 */
256 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700257 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700258 final Configuration currentOverrideConfig =
259 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800260
261 // Create new, slightly changed override configuration and apply it to the display.
262 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
263 newOverrideConfig.densityDpi += 120;
264 newOverrideConfig.fontScale += 0.3;
265
Evan Roskye747c3e2018-10-30 20:06:41 -0700266 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800267
268 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700269 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800270 }
271
272 /**
273 * This tests global configuration updates when default display config is updated.
274 */
275 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700276 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700277 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
278 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800279
280 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700281 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800282 newOverrideConfig.densityDpi += 120;
283 newOverrideConfig.fontScale += 0.3;
284
Evan Roskye747c3e2018-10-30 20:06:41 -0700285 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800286
287 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700288 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800289 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
290 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800291
292 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700293 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700294 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700295 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
296 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800297 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800298
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700299 /**
300 * Tests tapping on a stack in different display results in window gaining focus.
301 */
302 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700303 public void testInputEventBringsCorrectDisplayInFocus() {
304 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700305 // Create a second display
306 final DisplayContent dc1 = createNewDisplay();
307
308 // Add stack with activity.
309 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
310 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
311 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800312 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700313 task0.addChild(token, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800314 dc0.configureDisplayPolicy();
315 assertNotNull(dc0.mTapDetector);
316
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700317 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
318 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
319 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800320 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700321 task1.addChild(token1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800322 dc1.configureDisplayPolicy();
323 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700324
Arthur Hungbe5ce212018-09-13 18:41:56 +0800325 // tap on primary display.
326 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700327 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700328 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800329 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700330
Arthur Hungbe5ce212018-09-13 18:41:56 +0800331 // Tap on secondary display.
332 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700333 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700334 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800335 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700336 }
337
David Stevens46939562017-03-24 13:04:00 -0700338 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800340 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
341 }
342
343 @Test
344 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
345 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
346 }
347
348 @Test
349 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
350 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
351 }
352
353 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
354 int targetSdk) {
355 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
356
Andrii Kulian0214ed92017-05-16 13:44:05 -0700357 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700358 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700359 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800360 window1.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800361 updateFocusedWindow();
362 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700363 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700364
365 // Check that a new display doesn't affect focus
366 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800367 updateFocusedWindow();
368 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700369 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700370
371 // Add a window to the second display, and it should be focused
372 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800373 window2.mAppToken.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800374 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800375 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800376 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700377 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700378
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800379 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700380 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800381 updateFocusedWindow();
382 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800383 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700384 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Adrian Roos4163d622018-05-22 16:56:35 +0200385 }
386
Bryce Lee27cec322017-03-21 09:41:37 -0700387 /**
388 * This tests setting the maximum ui width on a display.
389 */
390 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700391 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800392 // Prevent base display metrics for test from being updated to the value of real display.
393 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700394 final int baseWidth = 1440;
395 final int baseHeight = 2560;
396 final int baseDensity = 300;
397
Riddle Hsu654a6f92018-07-13 22:59:36 +0800398 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700399
400 final int maxWidth = 300;
401 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
402 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
403
Riddle Hsu654a6f92018-07-13 22:59:36 +0800404 displayContent.setMaxUiWidth(maxWidth);
405 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700406
407 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800408 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
409 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700410
411 final int smallerWidth = 200;
412 final int smallerHeight = 400;
413 final int smallerDensity = 100;
414
415 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800416 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
417 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700418
419 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800420 displayContent.setMaxUiWidth(maxWidth);
421 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700422 }
423
Andrii Kulian92c9a942017-10-10 00:41:41 -0700424 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700425 public void testDisplayCutout_rot0() {
426 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100427 final DisplayContent dc = createNewDisplay();
428 dc.mInitialDisplayWidth = 200;
429 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100430 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100431 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200432 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100433 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100434
435 dc.mInitialDisplayCutout = cutout;
436 dc.setRotation(Surface.ROTATION_0);
437 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
438
439 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
440 }
441 }
442
443 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700444 public void testDisplayCutout_rot90() {
445 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800446 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
447 // if the device has no cutout).
448 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
449 // Rotation may use real display info to compute bound, so here also uses the
450 // same width and height.
451 final int displayWidth = dc.mInitialDisplayWidth;
452 final int displayHeight = dc.mInitialDisplayHeight;
453 final int cutoutWidth = 40;
454 final int cutoutHeight = 10;
455 final int left = (displayWidth - cutoutWidth) / 2;
456 final int top = 0;
457 final int right = (displayWidth + cutoutWidth) / 2;
458 final int bottom = cutoutHeight;
459
460 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100461 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700462 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
463 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800464 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100465
466 dc.mInitialDisplayCutout = cutout;
467 dc.setRotation(Surface.ROTATION_90);
468 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
469
Riddle Hsu654a6f92018-07-13 22:59:36 +0800470 // ----o---------- -------------
471 // | | | | |
472 // | ------o | o---
473 // | | | |
474 // | | -> | |
475 // | | ---o
476 // | | |
477 // | | -------------
478 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100479 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200480 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800481 .computeSafeInsets(displayHeight, displayWidth)
482 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100483 }
484 }
485
486 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700487 public void testLayoutSeq_assignedDuringLayout() {
488 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100489
490 final DisplayContent dc = createNewDisplay();
491 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
492
493 dc.setLayoutNeeded();
494 dc.performLayout(true /* initial */, false /* updateImeWindows */);
495
496 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
497 }
498 }
499
500 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700501 @SuppressLint("InlinedApi")
502 public void testOrientationDefinedByKeyguard() {
503 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800504
505 // When display content is created its configuration is not yet initialized, which could
506 // cause unnecessary configuration propagation, so initialize it here.
507 final Configuration config = new Configuration();
508 dc.computeScreenConfiguration(config);
509 dc.onRequestedOverrideConfigurationChanged(config);
510
Andrii Kulian92c9a942017-10-10 00:41:41 -0700511 // Create a window that requests landscape orientation. It will define device orientation
512 // by default.
513 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
514 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
515
516 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
517 keyguard.mHasSurface = true;
518 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
519
520 assertEquals("Screen orientation must be defined by the app window by default",
521 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
522
523 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
524 assertEquals("Visible keyguard must influence device orientation",
525 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
526
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700527 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700528 assertEquals("Keyguard that is going away must not influence device orientation",
529 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
530 }
531
Andrii Kulianf0379de2018-03-14 16:24:07 -0700532 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800533 public void testOrientationForAspectRatio() {
534 final DisplayContent dc = createNewDisplay();
535
536 // When display content is created its configuration is not yet initialized, which could
537 // cause unnecessary configuration propagation, so initialize it here.
538 final Configuration config = new Configuration();
539 dc.computeScreenConfiguration(config);
540 dc.onRequestedOverrideConfigurationChanged(config);
541
542 // Create a window that requests a fixed orientation. It will define device orientation
543 // by default.
544 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
545 "window");
546 window.mHasSurface = true;
547 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
548
549 // --------------------------------
550 // Test non-close-to-square display
551 // --------------------------------
552 dc.mBaseDisplayWidth = 1000;
553 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
554 dc.configureDisplayPolicy();
555
556 assertEquals("Screen orientation must be defined by the window by default.",
557 window.mAttrs.screenOrientation, dc.getOrientation());
558
559 // ----------------------------
560 // Test close-to-square display
561 // ----------------------------
562 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
563 dc.configureDisplayPolicy();
564
565 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
566 SCREEN_ORIENTATION_USER, dc.getOrientation());
567 }
568
569 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700570 public void testDisableDisplayInfoOverrideFromWindowManager() {
571 final DisplayContent dc = createNewDisplay();
572
573 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700574 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700575
576 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700577 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700578 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
579 }
580
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800581 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800582 public void testClearLastFocusWhenReparentingFocusedWindow() {
583 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
584 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
585 defaultDisplay, "window");
586 defaultDisplay.mLastFocus = window;
587 mDisplayContent.mCurrentFocus = window;
588 mDisplayContent.reParentWindowToken(window.mToken);
589
590 assertNull(defaultDisplay.mLastFocus);
591 }
592
593 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800594 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
595 final DisplayContent portraitDisplay = createNewDisplay();
596 portraitDisplay.mInitialDisplayHeight = 2000;
597 portraitDisplay.mInitialDisplayWidth = 1000;
598
599 portraitDisplay.setRotation(Surface.ROTATION_0);
600 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
601 portraitDisplay.setRotation(Surface.ROTATION_90);
602 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
603
604 final DisplayContent landscapeDisplay = createNewDisplay();
605 landscapeDisplay.mInitialDisplayHeight = 1000;
606 landscapeDisplay.mInitialDisplayWidth = 2000;
607
608 landscapeDisplay.setRotation(Surface.ROTATION_0);
609 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
610 landscapeDisplay.setRotation(Surface.ROTATION_90);
611 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
612 }
613
lumarkff0ab692018-11-05 20:32:30 +0800614 @Test
615 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
616 final DisplayContent newDisplay = createNewDisplay();
617
618 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
619 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
620 appWin.setHasSurface(true);
621 appWin1.setHasSurface(true);
622
623 // Set current input method window on default display, make sure the input method target
624 // is appWin & null on the other display.
625 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
626 newDisplay.setInputMethodWindowLocked(null);
627 assertTrue("appWin should be IME target window",
628 appWin.equals(mDisplayContent.mInputMethodTarget));
629 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
630
631 // Switch input method window on new display & make sure the input method target also
632 // switched as expected.
633 newDisplay.setInputMethodWindowLocked(mImeWindow);
634 mDisplayContent.setInputMethodWindowLocked(null);
635 assertTrue("appWin1 should be IME target window",
636 appWin1.equals(newDisplay.mInputMethodTarget));
637 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
638 }
639
Garfield Tan90b04282018-12-11 14:04:42 -0800640 @Test
641 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800642 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800643 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800644 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
645 ? SCREEN_ORIENTATION_PORTRAIT
646 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800647
648 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
649 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800650 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800651
652 ActivityRecord activityRecord = mock(ActivityRecord.class);
653
654 assertTrue("Display should rotate to handle orientation request by default.",
655 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
656
657 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
658 verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
659 same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
660 final Configuration newDisplayConfig = captor.getValue();
Garfield Tan49dae102019-02-04 09:51:59 -0800661 assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800662 }
663
664 @Test
665 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800666 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800667 dc.getDisplayRotation().setFixedToUserRotation(
668 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan90b04282018-12-11 14:04:42 -0800669 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800670 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
671 ? SCREEN_ORIENTATION_PORTRAIT
672 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800673
674 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
675 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800676 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800677
678 ActivityRecord activityRecord = mock(ActivityRecord.class);
679
680 assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
681 + " user rotation.",
682 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
683 verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
684 eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
685 }
686
Tarandeep Singha6f35612019-01-11 19:50:46 -0800687 @Test
688 public void testComputeImeParent_app() throws Exception {
689 try (final InsetsModeSession session =
690 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
691 final DisplayContent dc = createNewDisplay();
692 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
693 assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
694 dc.computeImeParent());
695 }
696 }
697
698 @Test
699 public void testComputeImeParent_app_notFullscreen() throws Exception {
700 try (final InsetsModeSession session =
701 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
702 final DisplayContent dc = createNewDisplay();
703 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
704 dc.mInputMethodTarget.setWindowingMode(
705 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
706 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
707 }
708 }
709
710 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800711 public void testComputeImeParent_app_notMatchParentBounds() {
712 spyOn(mAppWindow.mAppToken);
713 doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
714 mDisplayContent.mInputMethodTarget = mAppWindow;
715 // The surface parent of IME should be the display instead of app window.
716 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
717 }
718
719 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800720 public void testComputeImeParent_noApp() throws Exception {
721 try (final InsetsModeSession session =
722 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
723 final DisplayContent dc = createNewDisplay();
724 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
725 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
726 }
727 }
728
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500729 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100730 public void testUpdateSystemGestureExclusion() throws Exception {
731 final DisplayContent dc = createNewDisplay();
732 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
733 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
734 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
735
736 dc.setLayoutNeeded();
737 dc.performLayout(true /* initial */, false /* updateImeWindows */);
738
739 win.setHasSurface(true);
740 dc.updateSystemGestureExclusion();
741
742 final MutableBoolean invoked = new MutableBoolean(false);
743 final ISystemGestureExclusionListener.Stub verifier =
744 new ISystemGestureExclusionListener.Stub() {
745 @Override
746 public void onSystemGestureExclusionChanged(int displayId, Region actual) {
747 Region expected = Region.obtain();
748 expected.set(10, 20, 30, 40);
749 assertEquals(expected, actual);
750 invoked.value = true;
751 }
752 };
753 try {
754 dc.registerSystemGestureExclusionListener(verifier);
755 } finally {
756 dc.unregisterSystemGestureExclusionListener(verifier);
757 }
758 assertTrue("SystemGestureExclusionListener was not invoked", invoked.value);
759 }
760
761 @Test
762 public void testCalculateSystemGestureExclusion() throws Exception {
763 final DisplayContent dc = createNewDisplay();
764 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
765 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
766 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
767
768 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
769 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
770 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
771
772 dc.setLayoutNeeded();
773 dc.performLayout(true /* initial */, false /* updateImeWindows */);
774
775 win.setHasSurface(true);
776 win2.setHasSurface(true);
777
778 final Region expected = Region.obtain();
779 expected.set(20, 30, 40, 50);
780 assertEquals(expected, dc.calculateSystemGestureExclusion());
781 }
782
783 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500784 public void testOrientationChangeLogging() {
785 MetricsLogger mockLogger = mock(MetricsLogger.class);
786 Configuration oldConfig = new Configuration();
787 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
788
789 Configuration newConfig = new Configuration();
790 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
791 final DisplayContent displayContent = spy(createNewDisplay());
792 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
793 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
794
795 displayContent.onConfigurationChanged(newConfig);
796
797 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
798 verify(mockLogger).write(logMakerCaptor.capture());
799 assertThat(logMakerCaptor.getValue().getCategory(),
800 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
801 assertThat(logMakerCaptor.getValue().getSubtype(),
802 is(Configuration.ORIENTATION_PORTRAIT));
803 }
804
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800805 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700806 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800807 }
808
Bryce Lee27cec322017-03-21 09:41:37 -0700809 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
810 int expectedBaseHeight, int expectedBaseDensity) {
811 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
812 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
813 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
814 }
815
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800816 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700817 synchronized (mWm.mGlobalLock) {
818 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800819 }
820 }
821
Riddle Hsu654a6f92018-07-13 22:59:36 +0800822 /**
823 * Create DisplayContent that does not update display base/initial values from device to keep
824 * the values set by test.
825 */
826 private DisplayContent createDisplayNoUpdateDisplayInfo() {
827 final DisplayContent displayContent = spy(createNewDisplay());
828 doNothing().when(displayContent).updateDisplayInfo();
829 return displayContent;
830 }
831
Adrian Roos0f9368c2018-04-08 10:59:08 -0700832 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
833 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800834
835 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700836 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700837 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
838
839 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800840
841 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700842 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700843 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
844 }
845
846 private static List<WindowState> reverseList(List<WindowState> list) {
847 final ArrayList<WindowState> result = new ArrayList<>(list);
848 Collections.reverse(result);
849 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800850 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700851
Arthur Hungbe5ce212018-09-13 18:41:56 +0800852 private void tapOnDisplay(final DisplayContent dc) {
853 final DisplayMetrics dm = dc.getDisplayMetrics();
854 final float x = dm.widthPixels / 2;
855 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700856 final long downTime = SystemClock.uptimeMillis();
857 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800858 // sending ACTION_DOWN
859 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700860 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800861 downTime,
862 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700863 x,
864 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800865 0 /*metaState*/);
866 downEvent.setDisplayId(dc.getDisplayId());
867 dc.mTapDetector.onPointerEvent(downEvent);
868
869 // sending ACTION_UP
870 final MotionEvent upEvent = MotionEvent.obtain(
871 downTime,
872 eventTime,
873 MotionEvent.ACTION_UP,
874 x,
875 y,
876 0 /*metaState*/);
877 upEvent.setDisplayId(dc.getDisplayId());
878 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700879 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700880}