blob: f2e7dc6fecae0316d9e55468b21889086a9a3882 [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Andrii Kulian92c9a942017-10-10 00:41:41 -070019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080022import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080023import static android.os.Build.VERSION_CODES.P;
24import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080025import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020026import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
27import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010028import static android.view.DisplayCutout.fromBoundingRect;
Adrian Roos019a52b2019-07-02 16:47:44 +020029import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
30import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
31import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010032import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
33import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020034import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
35import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080036import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
37import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080039import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kulian92c9a942017-10-10 00:41:41 -070040import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080041import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Brett Chabota26eda92018-07-23 13:08:30 -070042
Garfield Tan90b04282018-12-11 14:04:42 -080043import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
44import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090045import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080046import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080047import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
48import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
49import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090050import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080051import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090052import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
53import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070054import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080055import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080056
Adrian Roos5251b1d2018-03-23 18:57:43 +010057import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080058import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070059import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080060import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080061import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010062import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080063import static org.junit.Assert.assertTrue;
Tarandeep Singha6f35612019-01-11 19:50:46 -080064import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080065
Andrii Kulian92c9a942017-10-10 00:41:41 -070066import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080067import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080068import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010069import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010070import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050071import android.metrics.LogMaker;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070072import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070073import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070074import android.util.DisplayMetrics;
Adrian Roos4ffc8972019-02-07 20:45:11 +010075import android.util.MutableBoolean;
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
Garfield Tan90b04282018-12-11 14:04:42 -080086import com.android.dx.mockito.inline.extended.ExtendedMockito;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050087import com.android.internal.logging.MetricsLogger;
88import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010089import com.android.server.wm.utils.WmDisplayCutout;
90
Brett Chabota26eda92018-07-23 13:08:30 -070091import org.junit.Test;
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
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800109public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700110
111 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700112 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800113 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700114 mDisplayContent, "exiting app");
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700115 final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900116 // Wait until everything in animation handler get executed to prevent the exiting window
117 // from being removed during WindowSurfacePlacer Traversal.
118 waitUntilHandlersIdle();
119
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700120 exitingAppToken.mIsExiting = true;
Bryce Lee6d410262017-02-28 15:30:17 -0800121 exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700122
Wale Ogunwale34247952017-02-19 11:57:53 -0800123 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700124 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800125 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700126 mChildAppWindowBelow,
127 mAppWindow,
128 mChildAppWindowAbove,
129 mDockedDividerWindow,
130 mStatusBarWindow,
131 mNavBarWindow,
132 mImeWindow,
133 mImeDialogWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800134 }
135
136 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700137 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800138 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700139 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800140
lumarkff0ab692018-11-05 20:32:30 +0800141 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800142
Wale Ogunwale34247952017-02-19 11:57:53 -0800143 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700144 mWallpaperWindow,
145 mChildAppWindowBelow,
146 mAppWindow,
147 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800148 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700149 mImeWindow,
150 mImeDialogWindow,
151 mDockedDividerWindow,
152 mStatusBarWindow,
153 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800154 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800155
Wale Ogunwale34247952017-02-19 11:57:53 -0800156 @Test
lumarkff0ab692018-11-05 20:32:30 +0800157 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
158 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800159
Wale Ogunwale34247952017-02-19 11:57:53 -0800160 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700161 mWallpaperWindow,
162 mChildAppWindowBelow,
163 mAppWindow,
164 mChildAppWindowAbove,
165 mImeWindow,
166 mImeDialogWindow,
167 mDockedDividerWindow,
168 mStatusBarWindow,
169 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700170 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800171
172 @Test
lumarkff0ab692018-11-05 20:32:30 +0800173 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
174 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800175
Wale Ogunwale34247952017-02-19 11:57:53 -0800176 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700177 mWallpaperWindow,
178 mChildAppWindowBelow,
179 mAppWindow,
180 mChildAppWindowAbove,
181 mDockedDividerWindow,
182 mStatusBarWindow,
183 mImeWindow,
184 mImeDialogWindow,
185 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800186 }
187
188 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700189 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800190 // This window is set-up to be z-ordered between some windows that go in the same token like
191 // the nav bar and status bar.
192 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700193 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800194
Wale Ogunwale34247952017-02-19 11:57:53 -0800195 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700196 mWallpaperWindow,
197 mChildAppWindowBelow,
198 mAppWindow,
199 mChildAppWindowAbove,
200 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800201 voiceInteractionWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700202 mStatusBarWindow,
203 mNavBarWindow,
204 mImeWindow,
205 mImeDialogWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800206 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800207
Wale Ogunwale34247952017-02-19 11:57:53 -0800208 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700209 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800210 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700211 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800212 appWin.setHasSurface(true);
213 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700214 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800215 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800216 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800217
Wale Ogunwale34247952017-02-19 11:57:53 -0800218 // Verify that an child window can be an ime target.
219 final WindowState childWin = createWindow(appWin,
220 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
221 childWin.setHasSurface(true);
222 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700223 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800224 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800225 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800226
Andrii Kuliand68501e2017-01-10 22:57:27 -0800227 /**
228 * This tests stack movement between displays and proper stack's, task's and app token's display
229 * container references updates.
230 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800231 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700232 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800233 // Create a second display.
234 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800235
236 // Add stack with activity.
237 final TaskStack stack = createTaskStackOnDisplay(dc);
238 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
239 assertEquals(dc, stack.getParent().getParent());
240 assertEquals(dc, stack.getDisplayContent());
241
242 final Task task = createTaskInStack(stack, 0 /* userId */);
chaviw97d28202018-02-27 16:23:53 -0800243 final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
244 dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800245 task.addChild(token, 0);
246 assertEquals(dc, task.getDisplayContent());
247 assertEquals(dc, token.getDisplayContent());
248
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());
255 assertEquals(mDisplayContent, token.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 */);
316 final WindowTestUtils.TestAppWindowToken token =
chaviw97d28202018-02-27 16:23:53 -0800317 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700318 task0.addChild(token, 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 */);
324 final WindowTestUtils.TestAppWindowToken token1 =
chaviw97d28202018-02-27 16:23:53 -0800325 WindowTestUtils.createTestAppWindowToken(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700326 task1.addChild(token1, 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");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800365 window1.mAppToken.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");
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800378 window2.mAppToken.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.
392 window1.mAppToken.hiddenRequested = true;
393 window1.getDisplayContent().setFocusedApp(window1.mAppToken);
394 updateFocusedWindow();
395 assertTrue(!window1.isFocused());
396 assertEquals(window1.getDisplayId(),
397 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200398 }
399
Bryce Lee27cec322017-03-21 09:41:37 -0700400 /**
401 * This tests setting the maximum ui width on a display.
402 */
403 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700404 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800405 // Prevent base display metrics for test from being updated to the value of real display.
406 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700407 final int baseWidth = 1440;
408 final int baseHeight = 2560;
409 final int baseDensity = 300;
410
Riddle Hsu654a6f92018-07-13 22:59:36 +0800411 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700412
413 final int maxWidth = 300;
414 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
415 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
416
Riddle Hsu654a6f92018-07-13 22:59:36 +0800417 displayContent.setMaxUiWidth(maxWidth);
418 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700419
420 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800421 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
422 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700423
424 final int smallerWidth = 200;
425 final int smallerHeight = 400;
426 final int smallerDensity = 100;
427
428 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800429 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
430 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700431
432 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800433 displayContent.setMaxUiWidth(maxWidth);
434 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700435 }
436
Andrii Kulian92c9a942017-10-10 00:41:41 -0700437 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700438 public void testDisplayCutout_rot0() {
439 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos1cf585052018-01-03 18:43:27 +0100440 final DisplayContent dc = createNewDisplay();
441 dc.mInitialDisplayWidth = 200;
442 dc.mInitialDisplayHeight = 400;
Adrian Roos24264212018-02-19 16:26:15 +0100443 Rect r = new Rect(80, 0, 120, 10);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100444 final DisplayCutout cutout = new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200445 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100446 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100447
448 dc.mInitialDisplayCutout = cutout;
449 dc.setRotation(Surface.ROTATION_0);
450 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
451
452 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
453 }
454 }
455
456 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700457 public void testDisplayCutout_rot90() {
458 synchronized (mWm.getWindowManagerLock()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800459 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
460 // if the device has no cutout).
461 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
462 // Rotation may use real display info to compute bound, so here also uses the
463 // same width and height.
464 final int displayWidth = dc.mInitialDisplayWidth;
465 final int displayHeight = dc.mInitialDisplayHeight;
466 final int cutoutWidth = 40;
467 final int cutoutHeight = 10;
468 final int left = (displayWidth - cutoutWidth) / 2;
469 final int top = 0;
470 final int right = (displayWidth + cutoutWidth) / 2;
471 final int bottom = cutoutHeight;
472
473 final Rect r1 = new Rect(left, top, right, bottom);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100474 final DisplayCutout cutout = new WmDisplayCutout(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700475 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP),
476 null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800477 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100478
479 dc.mInitialDisplayCutout = cutout;
480 dc.setRotation(Surface.ROTATION_90);
481 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
482
Riddle Hsu654a6f92018-07-13 22:59:36 +0800483 // ----o---------- -------------
484 // | | | | |
485 // | ------o | o---
486 // | | | |
487 // | | -> | |
488 // | | ---o
489 // | | |
490 // | | -------------
491 final Rect r = new Rect(top, left, bottom, right);
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100492 assertEquals(new WmDisplayCutout(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200493 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
Riddle Hsu654a6f92018-07-13 22:59:36 +0800494 .computeSafeInsets(displayHeight, displayWidth)
495 .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100496 }
497 }
498
499 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700500 public void testLayoutSeq_assignedDuringLayout() {
501 synchronized (mWm.getWindowManagerLock()) {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100502
503 final DisplayContent dc = createNewDisplay();
504 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
505
506 dc.setLayoutNeeded();
507 dc.performLayout(true /* initial */, false /* updateImeWindows */);
508
509 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
510 }
511 }
512
513 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700514 @SuppressLint("InlinedApi")
515 public void testOrientationDefinedByKeyguard() {
516 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800517
518 // When display content is created its configuration is not yet initialized, which could
519 // cause unnecessary configuration propagation, so initialize it here.
520 final Configuration config = new Configuration();
521 dc.computeScreenConfiguration(config);
522 dc.onRequestedOverrideConfigurationChanged(config);
523
Andrii Kulian92c9a942017-10-10 00:41:41 -0700524 // Create a window that requests landscape orientation. It will define device orientation
525 // by default.
526 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
527 window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
528
529 final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
530 keyguard.mHasSurface = true;
531 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
532
533 assertEquals("Screen orientation must be defined by the app window by default",
534 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
535
536 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
537 assertEquals("Visible keyguard must influence device orientation",
538 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
539
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700540 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700541 assertEquals("Keyguard that is going away must not influence device orientation",
542 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
543 }
544
Andrii Kulianf0379de2018-03-14 16:24:07 -0700545 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800546 public void testOrientationForAspectRatio() {
547 final DisplayContent dc = createNewDisplay();
548
549 // When display content is created its configuration is not yet initialized, which could
550 // cause unnecessary configuration propagation, so initialize it here.
551 final Configuration config = new Configuration();
552 dc.computeScreenConfiguration(config);
553 dc.onRequestedOverrideConfigurationChanged(config);
554
555 // Create a window that requests a fixed orientation. It will define device orientation
556 // by default.
557 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
558 "window");
559 window.mHasSurface = true;
560 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
561
562 // --------------------------------
563 // Test non-close-to-square display
564 // --------------------------------
565 dc.mBaseDisplayWidth = 1000;
566 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
567 dc.configureDisplayPolicy();
568
569 assertEquals("Screen orientation must be defined by the window by default.",
570 window.mAttrs.screenOrientation, dc.getOrientation());
571
572 // ----------------------------
573 // Test close-to-square display
574 // ----------------------------
575 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
576 dc.configureDisplayPolicy();
577
578 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
579 SCREEN_ORIENTATION_USER, dc.getOrientation());
580 }
581
582 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700583 public void testDisableDisplayInfoOverrideFromWindowManager() {
584 final DisplayContent dc = createNewDisplay();
585
586 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700587 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700588
589 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700590 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700591 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
592 }
593
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800594 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800595 public void testClearLastFocusWhenReparentingFocusedWindow() {
596 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
597 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
598 defaultDisplay, "window");
599 defaultDisplay.mLastFocus = window;
600 mDisplayContent.mCurrentFocus = window;
601 mDisplayContent.reParentWindowToken(window.mToken);
602
603 assertNull(defaultDisplay.mLastFocus);
604 }
605
606 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800607 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
608 final DisplayContent portraitDisplay = createNewDisplay();
609 portraitDisplay.mInitialDisplayHeight = 2000;
610 portraitDisplay.mInitialDisplayWidth = 1000;
611
612 portraitDisplay.setRotation(Surface.ROTATION_0);
613 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
614 portraitDisplay.setRotation(Surface.ROTATION_90);
615 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
616
617 final DisplayContent landscapeDisplay = createNewDisplay();
618 landscapeDisplay.mInitialDisplayHeight = 1000;
619 landscapeDisplay.mInitialDisplayWidth = 2000;
620
621 landscapeDisplay.setRotation(Surface.ROTATION_0);
622 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
623 landscapeDisplay.setRotation(Surface.ROTATION_90);
624 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
625 }
626
lumarkff0ab692018-11-05 20:32:30 +0800627 @Test
628 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
629 final DisplayContent newDisplay = createNewDisplay();
630
631 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
632 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
633 appWin.setHasSurface(true);
634 appWin1.setHasSurface(true);
635
636 // Set current input method window on default display, make sure the input method target
637 // is appWin & null on the other display.
638 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
639 newDisplay.setInputMethodWindowLocked(null);
640 assertTrue("appWin should be IME target window",
641 appWin.equals(mDisplayContent.mInputMethodTarget));
642 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
643
644 // Switch input method window on new display & make sure the input method target also
645 // switched as expected.
646 newDisplay.setInputMethodWindowLocked(mImeWindow);
647 mDisplayContent.setInputMethodWindowLocked(null);
648 assertTrue("appWin1 should be IME target window",
649 appWin1.equals(newDisplay.mInputMethodTarget));
650 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
651 }
652
Garfield Tan90b04282018-12-11 14:04:42 -0800653 @Test
654 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800655 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800656 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800657 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
658 ? SCREEN_ORIENTATION_PORTRAIT
659 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800660
661 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
662 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800663 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800664
665 ActivityRecord activityRecord = mock(ActivityRecord.class);
666
667 assertTrue("Display should rotate to handle orientation request by default.",
668 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
669
670 final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
671 verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
672 same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
673 final Configuration newDisplayConfig = captor.getValue();
Garfield Tan49dae102019-02-04 09:51:59 -0800674 assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800675 }
676
677 @Test
678 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800679 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800680 dc.getDisplayRotation().setFixedToUserRotation(
681 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan90b04282018-12-11 14:04:42 -0800682 mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
Garfield Tan49dae102019-02-04 09:51:59 -0800683 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
684 ? SCREEN_ORIENTATION_PORTRAIT
685 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800686
687 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
688 window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
Garfield Tan49dae102019-02-04 09:51:59 -0800689 window.mAppToken.setOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800690
691 ActivityRecord activityRecord = mock(ActivityRecord.class);
692
693 assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
694 + " user rotation.",
695 dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
696 verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
697 eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
698 }
699
Tarandeep Singha6f35612019-01-11 19:50:46 -0800700 @Test
701 public void testComputeImeParent_app() throws Exception {
702 try (final InsetsModeSession session =
703 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
704 final DisplayContent dc = createNewDisplay();
705 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
706 assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
707 dc.computeImeParent());
708 }
709 }
710
711 @Test
712 public void testComputeImeParent_app_notFullscreen() throws Exception {
713 try (final InsetsModeSession session =
714 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
715 final DisplayContent dc = createNewDisplay();
716 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
717 dc.mInputMethodTarget.setWindowingMode(
718 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
719 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
720 }
721 }
722
723 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800724 public void testComputeImeParent_app_notMatchParentBounds() {
725 spyOn(mAppWindow.mAppToken);
726 doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
727 mDisplayContent.mInputMethodTarget = mAppWindow;
728 // The surface parent of IME should be the display instead of app window.
729 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
730 }
731
732 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800733 public void testComputeImeParent_noApp() throws Exception {
734 try (final InsetsModeSession session =
735 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
736 final DisplayContent dc = createNewDisplay();
737 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
738 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
739 }
740 }
741
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500742 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100743 public void testUpdateSystemGestureExclusion() throws Exception {
744 final DisplayContent dc = createNewDisplay();
745 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
746 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
747 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
748
749 dc.setLayoutNeeded();
750 dc.performLayout(true /* initial */, false /* updateImeWindows */);
751
752 win.setHasSurface(true);
753 dc.updateSystemGestureExclusion();
754
755 final MutableBoolean invoked = new MutableBoolean(false);
756 final ISystemGestureExclusionListener.Stub verifier =
757 new ISystemGestureExclusionListener.Stub() {
758 @Override
759 public void onSystemGestureExclusionChanged(int displayId, Region actual) {
760 Region expected = Region.obtain();
761 expected.set(10, 20, 30, 40);
762 assertEquals(expected, actual);
763 invoked.value = true;
764 }
765 };
766 try {
767 dc.registerSystemGestureExclusionListener(verifier);
768 } finally {
769 dc.unregisterSystemGestureExclusionListener(verifier);
770 }
771 assertTrue("SystemGestureExclusionListener was not invoked", invoked.value);
772 }
773
774 @Test
775 public void testCalculateSystemGestureExclusion() throws Exception {
776 final DisplayContent dc = createNewDisplay();
777 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
778 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
779 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
780
781 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
782 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
783 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
784
785 dc.setLayoutNeeded();
786 dc.performLayout(true /* initial */, false /* updateImeWindows */);
787
788 win.setHasSurface(true);
789 win2.setHasSurface(true);
790
791 final Region expected = Region.obtain();
792 expected.set(20, 30, 40, 50);
793 assertEquals(expected, dc.calculateSystemGestureExclusion());
794 }
795
796 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200797 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
798 synchronized (mWm.mGlobalLock) {
799 mWm.mSystemGestureExcludedByPreQStickyImmersive = true;
800
801 final DisplayContent dc = createNewDisplay();
802 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
803 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
804 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
805 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
806 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
807 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
808 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
809 win.mAppToken.mTargetSdk = P;
810
811 dc.setLayoutNeeded();
812 dc.performLayout(true /* initial */, false /* updateImeWindows */);
813
814 win.setHasSurface(true);
815
816 final Region expected = Region.obtain();
817 expected.set(dc.getBounds());
818 assertEquals(expected, dc.calculateSystemGestureExclusion());
819
820 win.setHasSurface(false);
821 }
822 }
823
824 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500825 public void testOrientationChangeLogging() {
826 MetricsLogger mockLogger = mock(MetricsLogger.class);
827 Configuration oldConfig = new Configuration();
828 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
829
830 Configuration newConfig = new Configuration();
831 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
832 final DisplayContent displayContent = spy(createNewDisplay());
833 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
834 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
835
836 displayContent.onConfigurationChanged(newConfig);
837
838 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
839 verify(mockLogger).write(logMakerCaptor.capture());
840 assertThat(logMakerCaptor.getValue().getCategory(),
841 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
842 assertThat(logMakerCaptor.getValue().getSubtype(),
843 is(Configuration.ORIENTATION_PORTRAIT));
844 }
845
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800846 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700847 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800848 }
849
Bryce Lee27cec322017-03-21 09:41:37 -0700850 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
851 int expectedBaseHeight, int expectedBaseDensity) {
852 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
853 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
854 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
855 }
856
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800857 private void updateFocusedWindow() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700858 synchronized (mWm.mGlobalLock) {
859 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800860 }
861 }
862
Riddle Hsu654a6f92018-07-13 22:59:36 +0800863 /**
864 * Create DisplayContent that does not update display base/initial values from device to keep
865 * the values set by test.
866 */
867 private DisplayContent createDisplayNoUpdateDisplayInfo() {
868 final DisplayContent displayContent = spy(createNewDisplay());
869 doNothing().when(displayContent).updateDisplayInfo();
870 return displayContent;
871 }
872
Adrian Roos0f9368c2018-04-08 10:59:08 -0700873 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
874 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800875
876 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700877 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700878 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
879
880 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -0800881
882 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700883 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -0700884 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
885 }
886
887 private static List<WindowState> reverseList(List<WindowState> list) {
888 final ArrayList<WindowState> result = new ArrayList<>(list);
889 Collections.reverse(result);
890 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -0800891 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700892
Arthur Hungbe5ce212018-09-13 18:41:56 +0800893 private void tapOnDisplay(final DisplayContent dc) {
894 final DisplayMetrics dm = dc.getDisplayMetrics();
895 final float x = dm.widthPixels / 2;
896 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700897 final long downTime = SystemClock.uptimeMillis();
898 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +0800899 // sending ACTION_DOWN
900 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700901 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800902 downTime,
903 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700904 x,
905 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +0800906 0 /*metaState*/);
907 downEvent.setDisplayId(dc.getDisplayId());
908 dc.mTapDetector.onPointerEvent(downEvent);
909
910 // sending ACTION_UP
911 final MotionEvent upEvent = MotionEvent.obtain(
912 downTime,
913 eventTime,
914 MotionEvent.ACTION_UP,
915 x,
916 y,
917 0 /*metaState*/);
918 upEvent.setDisplayId(dc.getDisplayId());
919 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700920 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700921}