blob: 01489c6c8c1b736bf5134d8851196cebd315a4fd [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Andrii Kulian92c9a942017-10-10 00:41:41 -070019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080022import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080023import static android.os.Build.VERSION_CODES.P;
24import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080025import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020026import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
27import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010028import static android.view.DisplayCutout.fromBoundingRect;
Adrian Roos019a52b2019-07-02 16:47:44 +020029import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
30import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
31import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010032import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
33import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020034import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
35import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080036import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
37import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080039import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070040import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080041import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060042import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070043
Garfield Tan90b04282018-12-11 14:04:42 -080044import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
45import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090046import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080047import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080048import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
49import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060050import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080051import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080052import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090053import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
54import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070055import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080056import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080057
Adrian Roos5251b1d2018-03-23 18:57:43 +010058import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080059import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070060import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080061import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080062import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010063import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080064import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080065import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080066
Andrii Kulian92c9a942017-10-10 00:41:41 -070067import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080068import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080069import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010070import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010071import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050072import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070073import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070074import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070075import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010076import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080077import android.view.Gravity;
Adrian Roos4ffc8972019-02-07 20:45:11 +010078import android.view.ISystemGestureExclusionListener;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070079import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010080import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080081import android.view.ViewRootImpl;
82import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070083
Brett Chabota26eda92018-07-23 13:08:30 -070084import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070085
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050086import com.android.internal.logging.MetricsLogger;
87import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010088import com.android.server.wm.utils.WmDisplayCutout;
89
Brett Chabota26eda92018-07-23 13:08:30 -070090import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080091import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -080092import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050093import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070094
Adrian Roos0f9368c2018-04-08 10:59:08 -070095import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -080096import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -070097import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -080098import java.util.LinkedList;
99import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700100
101/**
102 * Tests for the {@link DisplayContent} class.
103 *
104 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900105 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700106 */
107@SmallTest
108@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800109@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800110public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700111
112 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700113 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800114 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700115 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700116 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900117 // Wait until everything in animation handler get executed to prevent the exiting window
118 // from being removed during WindowSurfacePlacer Traversal.
119 waitUntilHandlersIdle();
120
Garfield Tane8d84ab2019-10-11 09:49:40 -0700121 exitingApp.mIsExiting = true;
122 exitingApp.getTask().mStack.mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700123
Wale Ogunwale34247952017-02-19 11:57:53 -0800124 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700125 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800126 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700127 mChildAppWindowBelow,
128 mAppWindow,
129 mChildAppWindowAbove,
130 mDockedDividerWindow,
131 mStatusBarWindow,
132 mNavBarWindow,
133 mImeWindow,
134 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800135 }
136
137 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700138 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800139 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700140 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800141
lumarkff0ab692018-11-05 20:32:30 +0800142 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800143
Wale Ogunwale34247952017-02-19 11:57:53 -0800144 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700145 mWallpaperWindow,
146 mChildAppWindowBelow,
147 mAppWindow,
148 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800149 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700150 mImeWindow,
151 mImeDialogWindow,
152 mDockedDividerWindow,
153 mStatusBarWindow,
154 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800155 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800156
Wale Ogunwale34247952017-02-19 11:57:53 -0800157 @Test
lumarkff0ab692018-11-05 20:32:30 +0800158 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
159 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800160
Wale Ogunwale34247952017-02-19 11:57:53 -0800161 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700162 mWallpaperWindow,
163 mChildAppWindowBelow,
164 mAppWindow,
165 mChildAppWindowAbove,
166 mImeWindow,
167 mImeDialogWindow,
168 mDockedDividerWindow,
169 mStatusBarWindow,
170 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700171 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800172
173 @Test
lumarkff0ab692018-11-05 20:32:30 +0800174 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
175 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800176
Wale Ogunwale34247952017-02-19 11:57:53 -0800177 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700178 mWallpaperWindow,
179 mChildAppWindowBelow,
180 mAppWindow,
181 mChildAppWindowAbove,
182 mDockedDividerWindow,
183 mStatusBarWindow,
184 mImeWindow,
185 mImeDialogWindow,
186 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800187 }
188
189 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700190 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800191 // This window is set-up to be z-ordered between some windows that go in the same token like
192 // the nav bar and status bar.
193 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700194 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800195
Wale Ogunwale34247952017-02-19 11:57:53 -0800196 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700197 mWallpaperWindow,
198 mChildAppWindowBelow,
199 mAppWindow,
200 mChildAppWindowAbove,
201 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800202 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700203 mStatusBarWindow,
204 mNavBarWindow,
205 mImeWindow,
206 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800207 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800208
Wale Ogunwale34247952017-02-19 11:57:53 -0800209 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700210 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800211 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700212 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800213 appWin.setHasSurface(true);
214 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700215 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800216 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800217 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800218
Wale Ogunwale34247952017-02-19 11:57:53 -0800219 // Verify that an child window can be an ime target.
220 final WindowState childWin = createWindow(appWin,
221 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
222 childWin.setHasSurface(true);
223 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700224 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800225 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800226 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800227
Andrii Kuliand68501e2017-01-10 22:57:27 -0800228 /**
229 * This tests stack movement between displays and proper stack's, task's and app token's display
230 * container references updates.
231 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800232 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700233 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800234 // Create a second display.
235 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800236
237 // Add stack with activity.
238 final TaskStack stack = createTaskStackOnDisplay(dc);
239 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
240 assertEquals(dc, stack.getParent().getParent());
241 assertEquals(dc, stack.getDisplayContent());
242
243 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700244 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
245 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800246 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700247 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800248
249 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700250 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
251 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
252 assertEquals(mDisplayContent, stack.getParent().getParent());
253 assertEquals(mDisplayContent, stack.getDisplayContent());
254 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700255 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800256 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800257
258 /**
259 * This tests override configuration updates for display content.
260 */
261 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700262 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700263 final Configuration currentOverrideConfig =
264 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800265
266 // Create new, slightly changed override configuration and apply it to the display.
267 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
268 newOverrideConfig.densityDpi += 120;
269 newOverrideConfig.fontScale += 0.3;
270
Evan Roskye747c3e2018-10-30 20:06:41 -0700271 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800272
273 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700274 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800275 }
276
277 /**
278 * This tests global configuration updates when default display config is updated.
279 */
280 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700281 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700282 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
283 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800284
285 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700286 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800287 newOverrideConfig.densityDpi += 120;
288 newOverrideConfig.fontScale += 0.3;
289
Evan Roskye747c3e2018-10-30 20:06:41 -0700290 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800291
292 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700293 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800294 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
295 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800296
297 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700298 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700299 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700300 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
301 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800302 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800303
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700304 /**
305 * Tests tapping on a stack in different display results in window gaining focus.
306 */
307 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700308 public void testInputEventBringsCorrectDisplayInFocus() {
309 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700310 // Create a second display
311 final DisplayContent dc1 = createNewDisplay();
312
313 // Add stack with activity.
314 final TaskStack stack0 = createTaskStackOnDisplay(dc0);
315 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700316 final ActivityRecord activity =
317 WindowTestUtils.createTestActivityRecord(dc0);
318 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800319 dc0.configureDisplayPolicy();
320 assertNotNull(dc0.mTapDetector);
321
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700322 final TaskStack stack1 = createTaskStackOnDisplay(dc1);
323 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700324 final ActivityRecord activity1 =
325 WindowTestUtils.createTestActivityRecord(dc0);
326 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800327 dc1.configureDisplayPolicy();
328 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700329
Arthur Hungbe5ce212018-09-13 18:41:56 +0800330 // tap on primary display.
331 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700332 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700333 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800334 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700335
Arthur Hungbe5ce212018-09-13 18:41:56 +0800336 // Tap on secondary display.
337 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700338 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800340 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700341 }
342
David Stevens46939562017-03-24 13:04:00 -0700343 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700344 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800345 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
346 }
347
348 @Test
349 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
350 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
351 }
352
353 @Test
354 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
355 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
356 }
357
358 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
359 int targetSdk) {
360 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
361
Andrii Kulian0214ed92017-05-16 13:44:05 -0700362 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700363 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700364 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700365 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800366 updateFocusedWindow();
367 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700368 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700369
370 // Check that a new display doesn't affect focus
371 final DisplayContent dc = createNewDisplay();
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 // Add a window to the second display, and it should be focused
377 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700378 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800379 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800380 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800381 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700382 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700383
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800384 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700385 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800386 updateFocusedWindow();
387 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800388 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700389 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800390
391 // Make sure top focused display not changed if there is a focused app.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700392 window1.mActivityRecord.hiddenRequested = true;
393 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800394 updateFocusedWindow();
395 assertTrue(!window1.isFocused());
396 assertEquals(window1.getDisplayId(),
397 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200398 }
399
Riddle Hsub2297ad2019-07-26 23:37:25 -0600400 @Test
401 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
402 mWm.mSystemBooted = true;
403 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
404 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
405 TYPE_WALLPAPER, TYPE_APPLICATION);
406
407 // Verify waiting for windows to be drawn.
408 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
409
410 // Verify not waiting for drawn windows.
411 makeWindowsDrawn(windows);
412 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
413 }
414
415 @Test
416 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
417 mWm.mSystemBooted = true;
418 final DisplayContent secondaryDisplay = createNewDisplay();
419 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
420 TYPE_WALLPAPER, TYPE_APPLICATION);
421
422 // Verify not waiting for display without system decorations.
423 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
424 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
425
426 // Verify waiting for non-drawn windows on display with system decorations.
427 reset(secondaryDisplay);
428 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
429 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
430
431 // Verify not waiting for drawn windows on display with system decorations.
432 makeWindowsDrawn(windows);
433 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
434 }
435
436 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
437 final WindowState[] windows = new WindowState[types.length];
438 for (int i = 0; i < types.length; i++) {
439 final int type = types[i];
440 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
441 windows[i].mHasSurface = false;
442 }
443 return windows;
444 }
445
446 private static void makeWindowsDrawn(WindowState[] windows) {
447 for (WindowState window : windows) {
448 window.mHasSurface = true;
449 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
450 }
451 }
452
Bryce Lee27cec322017-03-21 09:41:37 -0700453 /**
454 * This tests setting the maximum ui width on a display.
455 */
456 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700457 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800458 // Prevent base display metrics for test from being updated to the value of real display.
459 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700460 final int baseWidth = 1440;
461 final int baseHeight = 2560;
462 final int baseDensity = 300;
463
Riddle Hsu654a6f92018-07-13 22:59:36 +0800464 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700465
466 final int maxWidth = 300;
467 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
468 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
469
Riddle Hsu654a6f92018-07-13 22:59:36 +0800470 displayContent.setMaxUiWidth(maxWidth);
471 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700472
473 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800474 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
475 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700476
477 final int smallerWidth = 200;
478 final int smallerHeight = 400;
479 final int smallerDensity = 100;
480
481 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800482 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
483 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700484
485 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800486 displayContent.setMaxUiWidth(maxWidth);
487 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700488 }
489
Andrii Kulian92c9a942017-10-10 00:41:41 -0700490 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700491 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800492 final DisplayContent dc = createNewDisplay();
493 dc.mInitialDisplayWidth = 200;
494 dc.mInitialDisplayHeight = 400;
495 final Rect r = new Rect(80, 0, 120, 10);
496 final DisplayCutout cutout = new WmDisplayCutout(
497 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
498 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100499
Riddle Hsu73f53572019-09-23 23:13:01 +0800500 dc.mInitialDisplayCutout = cutout;
501 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
502 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100503
Riddle Hsu73f53572019-09-23 23:13:01 +0800504 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100505 }
506
507 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700508 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800509 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
510 // if the device has no cutout).
511 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
512 // Rotation may use real display info to compute bound, so here also uses the
513 // same width and height.
514 final int displayWidth = dc.mInitialDisplayWidth;
515 final int displayHeight = dc.mInitialDisplayHeight;
516 final int cutoutWidth = 40;
517 final int cutoutHeight = 10;
518 final int left = (displayWidth - cutoutWidth) / 2;
519 final int top = 0;
520 final int right = (displayWidth + cutoutWidth) / 2;
521 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800522
Riddle Hsu73f53572019-09-23 23:13:01 +0800523 final Rect r1 = new Rect(left, top, right, bottom);
524 final DisplayCutout cutout = new WmDisplayCutout(
525 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
526 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100527
Riddle Hsu73f53572019-09-23 23:13:01 +0800528 dc.mInitialDisplayCutout = cutout;
529 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
530 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100531
Riddle Hsu73f53572019-09-23 23:13:01 +0800532 // ----o---------- -------------
533 // | | | | |
534 // | ------o | o---
535 // | | | |
536 // | | -> | |
537 // | | ---o
538 // | | |
539 // | | -------------
540 final Rect r = new Rect(top, left, bottom, right);
541 assertEquals(new WmDisplayCutout(
542 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
543 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
544 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100545 }
546
547 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700548 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800549 final DisplayContent dc = createNewDisplay();
550 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100551
Riddle Hsu73f53572019-09-23 23:13:01 +0800552 dc.setLayoutNeeded();
553 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100554
Riddle Hsu73f53572019-09-23 23:13:01 +0800555 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100556 }
557
558 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700559 @SuppressLint("InlinedApi")
560 public void testOrientationDefinedByKeyguard() {
561 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800562
563 // When display content is created its configuration is not yet initialized, which could
564 // cause unnecessary configuration propagation, so initialize it here.
565 final Configuration config = new Configuration();
566 dc.computeScreenConfiguration(config);
567 dc.onRequestedOverrideConfigurationChanged(config);
568
Andrii Kulian92c9a942017-10-10 00:41:41 -0700569 // Create a window that requests landscape orientation. It will define device orientation
570 // by default.
571 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700572 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700573
574 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
575 keyguard.mHasSurface = true;
576 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
577
578 assertEquals("Screen orientation must be defined by the app window by default",
579 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
580
581 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
582 assertEquals("Visible keyguard must influence device orientation",
583 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
584
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700585 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700586 assertEquals("Keyguard that is going away must not influence device orientation",
587 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
588 }
589
Andrii Kulianf0379de2018-03-14 16:24:07 -0700590 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800591 public void testOrientationForAspectRatio() {
592 final DisplayContent dc = createNewDisplay();
593
594 // When display content is created its configuration is not yet initialized, which could
595 // cause unnecessary configuration propagation, so initialize it here.
596 final Configuration config = new Configuration();
597 dc.computeScreenConfiguration(config);
598 dc.onRequestedOverrideConfigurationChanged(config);
599
600 // Create a window that requests a fixed orientation. It will define device orientation
601 // by default.
602 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
603 "window");
604 window.mHasSurface = true;
605 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
606
607 // --------------------------------
608 // Test non-close-to-square display
609 // --------------------------------
610 dc.mBaseDisplayWidth = 1000;
611 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
612 dc.configureDisplayPolicy();
613
614 assertEquals("Screen orientation must be defined by the window by default.",
615 window.mAttrs.screenOrientation, dc.getOrientation());
616
617 // ----------------------------
618 // Test close-to-square display
619 // ----------------------------
620 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
621 dc.configureDisplayPolicy();
622
623 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
624 SCREEN_ORIENTATION_USER, dc.getOrientation());
625 }
626
627 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700628 public void testDisableDisplayInfoOverrideFromWindowManager() {
629 final DisplayContent dc = createNewDisplay();
630
631 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700632 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700633
634 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700635 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700636 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
637 }
638
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800639 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800640 public void testClearLastFocusWhenReparentingFocusedWindow() {
641 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
642 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
643 defaultDisplay, "window");
644 defaultDisplay.mLastFocus = window;
645 mDisplayContent.mCurrentFocus = window;
646 mDisplayContent.reParentWindowToken(window.mToken);
647
648 assertNull(defaultDisplay.mLastFocus);
649 }
650
651 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800652 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
653 final DisplayContent portraitDisplay = createNewDisplay();
654 portraitDisplay.mInitialDisplayHeight = 2000;
655 portraitDisplay.mInitialDisplayWidth = 1000;
656
Riddle Hsuccf09402019-08-13 00:33:06 +0800657 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800658 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Riddle Hsuccf09402019-08-13 00:33:06 +0800659 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800660 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
661
662 final DisplayContent landscapeDisplay = createNewDisplay();
663 landscapeDisplay.mInitialDisplayHeight = 1000;
664 landscapeDisplay.mInitialDisplayWidth = 2000;
665
Riddle Hsuccf09402019-08-13 00:33:06 +0800666 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800667 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Riddle Hsuccf09402019-08-13 00:33:06 +0800668 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800669 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
670 }
671
lumarkff0ab692018-11-05 20:32:30 +0800672 @Test
673 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
674 final DisplayContent newDisplay = createNewDisplay();
675
676 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
677 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
678 appWin.setHasSurface(true);
679 appWin1.setHasSurface(true);
680
681 // Set current input method window on default display, make sure the input method target
682 // is appWin & null on the other display.
683 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
684 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200685 assertEquals("appWin should be IME target window",
686 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800687 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
688
689 // Switch input method window on new display & make sure the input method target also
690 // switched as expected.
691 newDisplay.setInputMethodWindowLocked(mImeWindow);
692 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200693 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800694 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
695 }
696
Garfield Tan90b04282018-12-11 14:04:42 -0800697 @Test
698 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800699 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700700 dc.getDisplayRotation().setFixedToUserRotation(
701 DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800702 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
703 ? SCREEN_ORIENTATION_PORTRAIT
704 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800705
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700706 final ActivityStack stack =
707 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Riddle Hsud1549d22019-10-07 17:00:47 +0800708 .setDisplay(dc.mActivityDisplay).build();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700709 final ActivityRecord activity = stack.topTask().getTopActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800710
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700711 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800712
713 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
Riddle Hsud1549d22019-10-07 17:00:47 +0800714 verify(dc.mActivityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700715 same(activity), anyBoolean(), same(null));
Garfield Tan90b04282018-12-11 14:04:42 -0800716 final Configuration newDisplayConfig = captor.getValue();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700717 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
718 ? Configuration.ORIENTATION_PORTRAIT
719 : Configuration.ORIENTATION_LANDSCAPE;
720 assertEquals(expectedOrientation, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800721 }
722
723 @Test
724 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800725 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800726 dc.getDisplayRotation().setFixedToUserRotation(
727 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800728 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
729 ? SCREEN_ORIENTATION_PORTRAIT
730 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800731
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700732 final ActivityStack stack =
733 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
Riddle Hsud1549d22019-10-07 17:00:47 +0800734 .setDisplay(dc.mActivityDisplay).build();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700735 final ActivityRecord activity = stack.topTask().getTopActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800736
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700737 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800738
Riddle Hsud1549d22019-10-07 17:00:47 +0800739 verify(dc.mActivityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700740 eq(activity), anyBoolean(), same(null));
741 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800742 }
743
Tarandeep Singha6f35612019-01-11 19:50:46 -0800744 @Test
745 public void testComputeImeParent_app() throws Exception {
746 try (final InsetsModeSession session =
747 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
748 final DisplayContent dc = createNewDisplay();
749 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700750 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800751 dc.computeImeParent());
752 }
753 }
754
755 @Test
756 public void testComputeImeParent_app_notFullscreen() throws Exception {
757 try (final InsetsModeSession session =
758 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
759 final DisplayContent dc = createNewDisplay();
760 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
761 dc.mInputMethodTarget.setWindowingMode(
762 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
763 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
764 }
765 }
766
767 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800768 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700769 spyOn(mAppWindow.mActivityRecord);
770 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800771 mDisplayContent.mInputMethodTarget = mAppWindow;
772 // The surface parent of IME should be the display instead of app window.
773 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
774 }
775
776 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800777 public void testComputeImeParent_noApp() throws Exception {
778 try (final InsetsModeSession session =
779 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
780 final DisplayContent dc = createNewDisplay();
781 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
782 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
783 }
784 }
785
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500786 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100787 public void testUpdateSystemGestureExclusion() throws Exception {
788 final DisplayContent dc = createNewDisplay();
789 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
790 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
791 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
792
793 dc.setLayoutNeeded();
794 dc.performLayout(true /* initial */, false /* updateImeWindows */);
795
796 win.setHasSurface(true);
797 dc.updateSystemGestureExclusion();
798
Riddle Hsu73f53572019-09-23 23:13:01 +0800799 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100800 final ISystemGestureExclusionListener.Stub verifier =
801 new ISystemGestureExclusionListener.Stub() {
802 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200803 public void onSystemGestureExclusionChanged(int displayId, Region actual,
804 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100805 Region expected = Region.obtain();
806 expected.set(10, 20, 30, 40);
807 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800808 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100809 }
810 };
811 try {
812 dc.registerSystemGestureExclusionListener(verifier);
813 } finally {
814 dc.unregisterSystemGestureExclusionListener(verifier);
815 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800816 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100817 }
818
819 @Test
820 public void testCalculateSystemGestureExclusion() throws Exception {
821 final DisplayContent dc = createNewDisplay();
822 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
823 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
824 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
825
826 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
827 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
828 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
829
830 dc.setLayoutNeeded();
831 dc.performLayout(true /* initial */, false /* updateImeWindows */);
832
833 win.setHasSurface(true);
834 win2.setHasSurface(true);
835
836 final Region expected = Region.obtain();
837 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200838 assertEquals(expected, calculateSystemGestureExclusion(dc));
839 }
840
841 private Region calculateSystemGestureExclusion(DisplayContent dc) {
842 Region out = Region.obtain();
843 Region unrestricted = Region.obtain();
844 dc.calculateSystemGestureExclusion(out, unrestricted);
845 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100846 }
847
848 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200849 public void testCalculateSystemGestureExclusion_modal() throws Exception {
850 final DisplayContent dc = createNewDisplay();
851 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
852 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
853 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
854
855 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
856 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
857 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
858 win2.getAttrs().width = 10;
859 win2.getAttrs().height = 10;
860 win2.setSystemGestureExclusion(Collections.emptyList());
861
862 dc.setLayoutNeeded();
863 dc.performLayout(true /* initial */, false /* updateImeWindows */);
864
865 win.setHasSurface(true);
866 win2.setHasSurface(true);
867
868 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200869 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200870 }
871
872 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200873 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Riddle Hsu73f53572019-09-23 23:13:01 +0800874 mWm.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200875
Riddle Hsu73f53572019-09-23 23:13:01 +0800876 final DisplayContent dc = createNewDisplay();
877 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
878 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
879 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
880 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
881 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
882 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
883 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700884 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200885
Riddle Hsu73f53572019-09-23 23:13:01 +0800886 dc.setLayoutNeeded();
887 dc.performLayout(true /* initial */, false /* updateImeWindows */);
Adrian Roos019a52b2019-07-02 16:47:44 +0200888
Riddle Hsu73f53572019-09-23 23:13:01 +0800889 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200890
Riddle Hsu73f53572019-09-23 23:13:01 +0800891 final Region expected = Region.obtain();
892 expected.set(dc.getBounds());
893 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200894
Riddle Hsu73f53572019-09-23 23:13:01 +0800895 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200896 }
897
898 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500899 public void testOrientationChangeLogging() {
900 MetricsLogger mockLogger = mock(MetricsLogger.class);
901 Configuration oldConfig = new Configuration();
902 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
903
904 Configuration newConfig = new Configuration();
905 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800906 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500907 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
908 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
909
910 displayContent.onConfigurationChanged(newConfig);
911
912 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
913 verify(mockLogger).write(logMakerCaptor.capture());
914 assertThat(logMakerCaptor.getValue().getCategory(),
915 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
916 assertThat(logMakerCaptor.getValue().getSubtype(),
917 is(Configuration.ORIENTATION_PORTRAIT));
918 }
919
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800920 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700921 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800922 }
923
Bryce Lee27cec322017-03-21 09:41:37 -0700924 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
925 int expectedBaseHeight, int expectedBaseDensity) {
926 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
927 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
928 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
929 }
930
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800931 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800932 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800933 }
934
Riddle Hsu654a6f92018-07-13 22:59:36 +0800935 /**
936 * Create DisplayContent that does not update display base/initial values from device to keep
937 * the values set by test.
938 */
939 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800940 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +0800941 doNothing().when(displayContent).updateDisplayInfo();
942 return displayContent;
943 }
944
Adrian Roos0f9368c2018-04-08 10:59:08 -0700945 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
946 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800947
948 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700949 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700950 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
951
952 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800953
954 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700955 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700956 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
957 }
958
959 private static List<WindowState> reverseList(List<WindowState> list) {
960 final ArrayList<WindowState> result = new ArrayList<>(list);
961 Collections.reverse(result);
962 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800963 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700964
Arthur Hungbe5ce212018-09-13 18:41:56 +0800965 private void tapOnDisplay(final DisplayContent dc) {
966 final DisplayMetrics dm = dc.getDisplayMetrics();
967 final float x = dm.widthPixels / 2;
968 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700969 final long downTime = SystemClock.uptimeMillis();
970 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800971 // sending ACTION_DOWN
972 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700973 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800974 downTime,
975 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700976 x,
977 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800978 0 /*metaState*/);
979 downEvent.setDisplayId(dc.getDisplayId());
980 dc.mTapDetector.onPointerEvent(downEvent);
981
982 // sending ACTION_UP
983 final MotionEvent upEvent = MotionEvent.obtain(
984 downTime,
985 eventTime,
986 MotionEvent.ACTION_UP,
987 x,
988 y,
989 0 /*metaState*/);
990 upEvent.setDisplayId(dc.getDisplayId());
991 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700992 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700993}