blob: 545901e550c1baca69619761cef7825358fd202a [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
Vadim Caena8849f22020-06-05 12:28:07 +020019import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
Riddle Hsu80653ea2020-05-14 22:36:59 +080020import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Garfield Tan98eead32019-11-18 13:24:53 -080021import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Riddle Hsu80653ea2020-05-14 22:36:59 +080022import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
23import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Andrii Kulian92c9a942017-10-10 00:41:41 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
26import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080027import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080028import static android.os.Build.VERSION_CODES.P;
29import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080030import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020031import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
32import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010033import static android.view.DisplayCutout.fromBoundingRect;
Riddle Hsu9239d7c62020-02-20 01:35:56 +080034import static android.view.Surface.ROTATION_0;
Evan Rosky69cace42019-09-20 16:28:13 -070035import static android.view.Surface.ROTATION_90;
Adrian Roos019a52b2019-07-02 16:47:44 +020036import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
37import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
38import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010039import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
40import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020041import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
42import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080043import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080045import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080046import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
wilsonshihe8321942019-10-18 18:39:46 +080047import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
Mark Renoufa9279292020-04-17 12:22:50 -040048import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
Andrii Kulian92c9a942017-10-10 00:41:41 -070049import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080050import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060051import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070052
Garfield Tan90b04282018-12-11 14:04:42 -080053import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
54import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090055import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080056import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080057import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
58import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060059import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080060import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080061import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090062import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
63import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Vadim Caen4b4fc232020-05-26 20:17:15 +080064import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;
David Stevens46939562017-03-24 13:04:00 -070065import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080066import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080067
Riddle Hsu12c05452020-01-09 00:39:52 +080068import static com.google.common.truth.Truth.assertThat;
69
Adrian Roos5251b1d2018-03-23 18:57:43 +010070import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080071import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070072import static org.junit.Assert.assertFalse;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020073import static org.junit.Assert.assertNotEquals;
Arthur Hungbe5ce212018-09-13 18:41:56 +080074import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080075import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010076import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080077import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070078import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080079import static org.mockito.ArgumentMatchers.eq;
Riddle Hsu80653ea2020-05-14 22:36:59 +080080import static org.mockito.Mockito.atLeastOnce;
81import static org.mockito.Mockito.clearInvocations;
Charles Chen770597c2020-05-18 19:58:23 +080082import static org.mockito.Mockito.doAnswer;
Vadim Caena8849f22020-06-05 12:28:07 +020083import static org.mockito.Mockito.doCallRealMethod;
Wale Ogunwale34247952017-02-19 11:57:53 -080084
Andrii Kulian92c9a942017-10-10 00:41:41 -070085import android.annotation.SuppressLint;
Mark Renoufa9279292020-04-17 12:22:50 -040086import android.app.ActivityTaskManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080087import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080088import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010089import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010090import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050091import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070092import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070093import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070094import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070095import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010096import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080097import android.view.Gravity;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020098import android.view.IDisplayWindowInsetsController;
Evan Rosky69cace42019-09-20 16:28:13 -070099import android.view.IDisplayWindowRotationCallback;
100import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100101import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -0800102import android.view.IWindowManager;
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200103import android.view.InsetsSourceControl;
104import android.view.InsetsState;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700105import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +0100106import android.view.Surface;
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +0800107import android.view.SurfaceControl.Transaction;
Riddle Hsu12c05452020-01-09 00:39:52 +0800108import android.view.WindowManager;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700109
Brett Chabota26eda92018-07-23 13:08:30 -0700110import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -0700111
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500112import com.android.internal.logging.MetricsLogger;
113import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100114import com.android.server.wm.utils.WmDisplayCutout;
115
Brett Chabota26eda92018-07-23 13:08:30 -0700116import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800117import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800118import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500119import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700120
Adrian Roos0f9368c2018-04-08 10:59:08 -0700121import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800122import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700123import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800124import java.util.LinkedList;
125import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700126
127/**
128 * Tests for the {@link DisplayContent} class.
129 *
130 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900131 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700132 */
133@SmallTest
134@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800135@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800136public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700137
138 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700139 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800140 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700141 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700142 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900143 // Wait until everything in animation handler get executed to prevent the exiting window
144 // from being removed during WindowSurfacePlacer Traversal.
145 waitUntilHandlersIdle();
146
Garfield Tane8d84ab2019-10-11 09:49:40 -0700147 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800148 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700149
Wale Ogunwale34247952017-02-19 11:57:53 -0800150 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700151 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800152 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 mChildAppWindowBelow,
154 mAppWindow,
155 mChildAppWindowAbove,
156 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200157 mImeWindow,
158 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700159 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800160 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200161 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800162 }
163
164 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700165 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800166 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700167 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800168
lumarkff0ab692018-11-05 20:32:30 +0800169 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800170
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700172 mWallpaperWindow,
173 mChildAppWindowBelow,
174 mAppWindow,
175 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800176 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700177 mImeWindow,
178 mImeDialogWindow,
179 mDockedDividerWindow,
180 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800181 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700182 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800183 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800184
Wale Ogunwale34247952017-02-19 11:57:53 -0800185 @Test
lumarkff0ab692018-11-05 20:32:30 +0800186 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
187 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800188
Wale Ogunwale34247952017-02-19 11:57:53 -0800189 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700190 mWallpaperWindow,
191 mChildAppWindowBelow,
192 mAppWindow,
193 mChildAppWindowAbove,
194 mImeWindow,
195 mImeDialogWindow,
196 mDockedDividerWindow,
197 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800198 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700199 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700200 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800201
202 @Test
lumarkff0ab692018-11-05 20:32:30 +0800203 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
204 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800205
Wale Ogunwale34247952017-02-19 11:57:53 -0800206 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700207 mWallpaperWindow,
208 mChildAppWindowBelow,
209 mAppWindow,
210 mChildAppWindowAbove,
211 mDockedDividerWindow,
212 mStatusBarWindow,
213 mImeWindow,
214 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800215 mNotificationShadeWindow,
216 mNavBarWindow));
217 }
218
219 @Test
220 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
221 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
222
223 assertForAllWindowsOrder(Arrays.asList(
224 mWallpaperWindow,
225 mChildAppWindowBelow,
226 mAppWindow,
227 mChildAppWindowAbove,
228 mDockedDividerWindow,
229 mStatusBarWindow,
230 mNotificationShadeWindow,
231 mImeWindow,
232 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700233 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800234 }
235
236 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700237 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800238 // This window is set-up to be z-ordered between some windows that go in the same token like
239 // the nav bar and status bar.
240 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700241 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800242
Wale Ogunwale34247952017-02-19 11:57:53 -0800243 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700244 mWallpaperWindow,
245 mChildAppWindowBelow,
246 mAppWindow,
247 mChildAppWindowAbove,
248 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800249 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200250 mImeWindow,
251 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700252 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800253 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200254 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800255 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800256
Wale Ogunwale34247952017-02-19 11:57:53 -0800257 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700258 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800259 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700260 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800261 appWin.setHasSurface(true);
262 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700263 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800264 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800265 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800266
Wale Ogunwale34247952017-02-19 11:57:53 -0800267 // Verify that an child window can be an ime target.
268 final WindowState childWin = createWindow(appWin,
269 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
270 childWin.setHasSurface(true);
271 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700272 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800273 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800274 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800275
Andrii Kuliand68501e2017-01-10 22:57:27 -0800276 /**
277 * This tests stack movement between displays and proper stack's, task's and app token's display
278 * container references updates.
279 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800280 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700281 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800282 // Create a second display.
283 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800284
285 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700286 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800287 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800288 assertEquals(dc, stack.getDisplayContent());
289
290 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700291 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
292 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800293 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700294 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800295
296 // Move stack to first display.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700297 stack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true /* onTop */);
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700298 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700299 assertEquals(mDisplayContent, stack.getDisplayContent());
300 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700301 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800302 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800303
304 /**
305 * This tests override configuration updates for display content.
306 */
307 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700308 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700309 final Configuration currentOverrideConfig =
310 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800311
312 // Create new, slightly changed override configuration and apply it to the display.
313 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
314 newOverrideConfig.densityDpi += 120;
315 newOverrideConfig.fontScale += 0.3;
316
Evan Roskye747c3e2018-10-30 20:06:41 -0700317 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800318
319 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700320 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800321 }
322
323 /**
324 * This tests global configuration updates when default display config is updated.
325 */
326 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700327 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700328 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
329 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800330
331 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700332 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800333 newOverrideConfig.densityDpi += 120;
334 newOverrideConfig.fontScale += 0.3;
335
Evan Roskye747c3e2018-10-30 20:06:41 -0700336 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800337
338 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800340 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
341 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800342
343 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700344 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700345 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700346 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
347 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800348 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800349
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700350 /**
351 * Tests tapping on a stack in different display results in window gaining focus.
352 */
353 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700354 public void testInputEventBringsCorrectDisplayInFocus() {
355 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700356 // Create a second display
357 final DisplayContent dc1 = createNewDisplay();
358
359 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700360 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700361 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700362 final ActivityRecord activity =
363 WindowTestUtils.createTestActivityRecord(dc0);
364 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800365 dc0.configureDisplayPolicy();
366 assertNotNull(dc0.mTapDetector);
367
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700368 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700369 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700370 final ActivityRecord activity1 =
371 WindowTestUtils.createTestActivityRecord(dc0);
372 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800373 dc1.configureDisplayPolicy();
374 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700375
Arthur Hungbe5ce212018-09-13 18:41:56 +0800376 // tap on primary display.
377 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700378 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700379 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800380 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700381
Arthur Hungbe5ce212018-09-13 18:41:56 +0800382 // Tap on secondary display.
383 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700384 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700385 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800386 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700387 }
388
David Stevens46939562017-03-24 13:04:00 -0700389 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700390 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800391 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
392 }
393
394 @Test
395 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
396 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
397 }
398
399 @Test
400 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
401 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
402 }
403
404 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
405 int targetSdk) {
406 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
407
Andrii Kulian0214ed92017-05-16 13:44:05 -0700408 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700409 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700410 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700411 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800412 updateFocusedWindow();
413 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700414 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700415
416 // Check that a new display doesn't affect focus
417 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800418 updateFocusedWindow();
419 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700420 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700421
422 // Add a window to the second display, and it should be focused
423 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700424 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800425 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800426 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800427 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700428 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700429
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800430 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700431 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800432 updateFocusedWindow();
433 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800434 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700435 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800436
437 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100438 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700439 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800440 updateFocusedWindow();
441 assertTrue(!window1.isFocused());
442 assertEquals(window1.getDisplayId(),
443 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200444 }
445
Riddle Hsub2297ad2019-07-26 23:37:25 -0600446 @Test
447 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
448 mWm.mSystemBooted = true;
449 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
450 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
451 TYPE_WALLPAPER, TYPE_APPLICATION);
452
453 // Verify waiting for windows to be drawn.
454 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
455
456 // Verify not waiting for drawn windows.
Lais Andrade57283fb2020-04-21 18:58:15 +0000457 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
Riddle Hsub2297ad2019-07-26 23:37:25 -0600458 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
459 }
460
461 @Test
462 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
463 mWm.mSystemBooted = true;
464 final DisplayContent secondaryDisplay = createNewDisplay();
465 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
466 TYPE_WALLPAPER, TYPE_APPLICATION);
467
468 // Verify not waiting for display without system decorations.
469 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
470 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
471
472 // Verify waiting for non-drawn windows on display with system decorations.
473 reset(secondaryDisplay);
474 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
475 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
476
477 // Verify not waiting for drawn windows on display with system decorations.
Lais Andrade57283fb2020-04-21 18:58:15 +0000478 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
Riddle Hsub2297ad2019-07-26 23:37:25 -0600479 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
480 }
481
Lais Andrade57283fb2020-04-21 18:58:15 +0000482 @Test
483 public void testShouldWaitForSystemDecorWindowsOnBoot_OnWindowReadyToShowAndDrawn() {
484 mWm.mSystemBooted = true;
485 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
486 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
487 TYPE_WALLPAPER, TYPE_APPLICATION);
488
489 // Verify waiting for windows to be drawn.
490 makeWindowsDrawnState(windows, WindowStateAnimator.READY_TO_SHOW);
491 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
492
493 // Verify not waiting for drawn windows.
494 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
495 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
496 }
497
Riddle Hsub2297ad2019-07-26 23:37:25 -0600498 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
499 final WindowState[] windows = new WindowState[types.length];
500 for (int i = 0; i < types.length; i++) {
501 final int type = types[i];
502 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
503 windows[i].mHasSurface = false;
504 }
505 return windows;
506 }
507
Lais Andrade57283fb2020-04-21 18:58:15 +0000508 private static void makeWindowsDrawnState(WindowState[] windows, int state) {
Riddle Hsub2297ad2019-07-26 23:37:25 -0600509 for (WindowState window : windows) {
510 window.mHasSurface = true;
Lais Andrade57283fb2020-04-21 18:58:15 +0000511 window.mWinAnimator.mDrawState = state;
Riddle Hsub2297ad2019-07-26 23:37:25 -0600512 }
513 }
514
Bryce Lee27cec322017-03-21 09:41:37 -0700515 /**
516 * This tests setting the maximum ui width on a display.
517 */
518 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700519 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800520 // Prevent base display metrics for test from being updated to the value of real display.
521 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700522 final int baseWidth = 1440;
523 final int baseHeight = 2560;
524 final int baseDensity = 300;
525
Riddle Hsu654a6f92018-07-13 22:59:36 +0800526 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700527
528 final int maxWidth = 300;
529 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
530 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
531
Riddle Hsu654a6f92018-07-13 22:59:36 +0800532 displayContent.setMaxUiWidth(maxWidth);
533 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700534
535 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800536 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
537 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700538
539 final int smallerWidth = 200;
540 final int smallerHeight = 400;
541 final int smallerDensity = 100;
542
543 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800544 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
545 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700546
547 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800548 displayContent.setMaxUiWidth(maxWidth);
549 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700550 }
551
Andrii Kulian92c9a942017-10-10 00:41:41 -0700552 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700553 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800554 final DisplayContent dc = createNewDisplay();
555 dc.mInitialDisplayWidth = 200;
556 dc.mInitialDisplayHeight = 400;
557 final Rect r = new Rect(80, 0, 120, 10);
558 final DisplayCutout cutout = new WmDisplayCutout(
559 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
560 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100561
Riddle Hsu73f53572019-09-23 23:13:01 +0800562 dc.mInitialDisplayCutout = cutout;
563 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
564 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100565
Riddle Hsu73f53572019-09-23 23:13:01 +0800566 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100567 }
568
569 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700570 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800571 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
572 // if the device has no cutout).
573 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800574 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
575 // landscape display let's rotate it.
576 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
577 int tmp = dc.mInitialDisplayHeight;
578 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
579 dc.mInitialDisplayWidth = tmp;
580 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800581 // Rotation may use real display info to compute bound, so here also uses the
582 // same width and height.
583 final int displayWidth = dc.mInitialDisplayWidth;
584 final int displayHeight = dc.mInitialDisplayHeight;
585 final int cutoutWidth = 40;
586 final int cutoutHeight = 10;
587 final int left = (displayWidth - cutoutWidth) / 2;
588 final int top = 0;
589 final int right = (displayWidth + cutoutWidth) / 2;
590 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800591
Riddle Hsu73f53572019-09-23 23:13:01 +0800592 final Rect r1 = new Rect(left, top, right, bottom);
593 final DisplayCutout cutout = new WmDisplayCutout(
594 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
595 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100596
Riddle Hsu73f53572019-09-23 23:13:01 +0800597 dc.mInitialDisplayCutout = cutout;
598 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
599 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100600
Riddle Hsu73f53572019-09-23 23:13:01 +0800601 // ----o---------- -------------
602 // | | | | |
603 // | ------o | o---
604 // | | | |
605 // | | -> | |
606 // | | ---o
607 // | | |
608 // | | -------------
609 final Rect r = new Rect(top, left, bottom, right);
610 assertEquals(new WmDisplayCutout(
611 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
612 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
613 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100614 }
615
616 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700617 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800618 final DisplayContent dc = createNewDisplay();
619 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100620
Riddle Hsu12c05452020-01-09 00:39:52 +0800621 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100622
Riddle Hsu73f53572019-09-23 23:13:01 +0800623 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100624 }
625
626 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700627 @SuppressLint("InlinedApi")
628 public void testOrientationDefinedByKeyguard() {
629 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800630
631 // When display content is created its configuration is not yet initialized, which could
632 // cause unnecessary configuration propagation, so initialize it here.
633 final Configuration config = new Configuration();
634 dc.computeScreenConfiguration(config);
635 dc.onRequestedOverrideConfigurationChanged(config);
636
Andrii Kulian92c9a942017-10-10 00:41:41 -0700637 // Create a window that requests landscape orientation. It will define device orientation
638 // by default.
639 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700640 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700641
wilsonshihe8321942019-10-18 18:39:46 +0800642 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700643 keyguard.mHasSurface = true;
644 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
645
646 assertEquals("Screen orientation must be defined by the app window by default",
647 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
648
649 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
650 assertEquals("Visible keyguard must influence device orientation",
651 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
652
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700653 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700654 assertEquals("Keyguard that is going away must not influence device orientation",
655 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
656 }
657
Andrii Kulianf0379de2018-03-14 16:24:07 -0700658 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800659 public void testOrientationForAspectRatio() {
660 final DisplayContent dc = createNewDisplay();
661
662 // When display content is created its configuration is not yet initialized, which could
663 // cause unnecessary configuration propagation, so initialize it here.
664 final Configuration config = new Configuration();
665 dc.computeScreenConfiguration(config);
666 dc.onRequestedOverrideConfigurationChanged(config);
667
668 // Create a window that requests a fixed orientation. It will define device orientation
669 // by default.
670 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
671 "window");
672 window.mHasSurface = true;
673 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
674
675 // --------------------------------
676 // Test non-close-to-square display
677 // --------------------------------
678 dc.mBaseDisplayWidth = 1000;
679 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
680 dc.configureDisplayPolicy();
681
682 assertEquals("Screen orientation must be defined by the window by default.",
683 window.mAttrs.screenOrientation, dc.getOrientation());
684
685 // ----------------------------
686 // Test close-to-square display
687 // ----------------------------
688 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
689 dc.configureDisplayPolicy();
690
691 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
692 SCREEN_ORIENTATION_USER, dc.getOrientation());
693 }
694
695 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700696 public void testDisableDisplayInfoOverrideFromWindowManager() {
697 final DisplayContent dc = createNewDisplay();
698
699 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700700 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700701
702 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700703 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700704 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
705 }
706
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800707 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800708 public void testClearLastFocusWhenReparentingFocusedWindow() {
709 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
710 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
711 defaultDisplay, "window");
712 defaultDisplay.mLastFocus = window;
713 mDisplayContent.mCurrentFocus = window;
714 mDisplayContent.reParentWindowToken(window.mToken);
715
716 assertNull(defaultDisplay.mLastFocus);
717 }
718
719 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800720 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
721 final DisplayContent portraitDisplay = createNewDisplay();
722 portraitDisplay.mInitialDisplayHeight = 2000;
723 portraitDisplay.mInitialDisplayWidth = 1000;
724
Riddle Hsuccf09402019-08-13 00:33:06 +0800725 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800726 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700727 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800728 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
729
730 final DisplayContent landscapeDisplay = createNewDisplay();
731 landscapeDisplay.mInitialDisplayHeight = 1000;
732 landscapeDisplay.mInitialDisplayWidth = 2000;
733
Riddle Hsuccf09402019-08-13 00:33:06 +0800734 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800735 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700736 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800737 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
738 }
739
lumarkff0ab692018-11-05 20:32:30 +0800740 @Test
741 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
742 final DisplayContent newDisplay = createNewDisplay();
743
744 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
745 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
746 appWin.setHasSurface(true);
747 appWin1.setHasSurface(true);
748
749 // Set current input method window on default display, make sure the input method target
750 // is appWin & null on the other display.
751 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
752 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200753 assertEquals("appWin should be IME target window",
754 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800755 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
756
757 // Switch input method window on new display & make sure the input method target also
758 // switched as expected.
759 newDisplay.setInputMethodWindowLocked(mImeWindow);
760 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200761 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800762 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
763 }
764
Garfield Tan90b04282018-12-11 14:04:42 -0800765 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800766 public void testAllowsTopmostFullscreenOrientation() {
767 final DisplayContent dc = createNewDisplay();
768 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800769 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800770
771 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800772 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800773 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800774 .build();
775 doReturn(true).when(stack).isVisible();
776
777 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800778 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800779 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800780 .setWindowingMode(WINDOWING_MODE_FREEFORM)
781 .build();
782 doReturn(true).when(freeformStack).isVisible();
783 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
784
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700785 assertTrue(dc.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM));
Garfield Tan98eead32019-11-18 13:24:53 -0800786
787 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
788 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
789 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
790
791 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
792 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
793 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
794 }
795
796 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800797 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800798 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700799 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800800 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Riddle Hsud4957432020-04-24 22:06:29 +0800801 final int newOrientation = getRotatedOrientation(dc);
Garfield Tan90b04282018-12-11 14:04:42 -0800802
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700803 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800804 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800805 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900806 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800807
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700808 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800809
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700810 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
811 ? Configuration.ORIENTATION_PORTRAIT
812 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700813 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800814 }
815
816 @Test
817 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800818 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800819 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800820 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Riddle Hsud4957432020-04-24 22:06:29 +0800821 final int newOrientation = getRotatedOrientation(dc);
Garfield Tan90b04282018-12-11 14:04:42 -0800822
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700823 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800824 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800825 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900826 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800827
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700828 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800829
Louis Chang677921f2019-12-06 16:44:24 +0800830 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
831 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700832 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800833 }
834
Tarandeep Singha6f35612019-01-11 19:50:46 -0800835 @Test
836 public void testComputeImeParent_app() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200837 final DisplayContent dc = createNewDisplay();
838 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
839 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
840 dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800841 }
842
843 @Test
844 public void testComputeImeParent_app_notFullscreen() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200845 final DisplayContent dc = createNewDisplay();
846 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
847 dc.mInputMethodTarget.setWindowingMode(
848 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
849 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800850 }
851
852 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800853 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700854 spyOn(mAppWindow.mActivityRecord);
855 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800856 mDisplayContent.mInputMethodTarget = mAppWindow;
857 // The surface parent of IME should be the display instead of app window.
Adrian Roos329cbd02020-04-14 15:42:41 +0200858 assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
859 mDisplayContent.computeImeParent());
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800860 }
861
862 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800863 public void testComputeImeParent_noApp() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200864 final DisplayContent dc = createNewDisplay();
865 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
866 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
867 }
868
869 @Test
870 public void testComputeImeControlTarget() throws Exception {
871 final DisplayContent dc = createNewDisplay();
872 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
873 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
874 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
875 assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
876 }
877
878 @Test
879 public void testComputeImeControlTarget_splitscreen() throws Exception {
880 final DisplayContent dc = createNewDisplay();
881 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
882 dc.mInputMethodInputTarget.setWindowingMode(
883 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
884 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
885 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
886 assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
887 }
888
889 @Test
890 public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
891 spyOn(mAppWindow.mActivityRecord);
892 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
893 mDisplayContent.mInputMethodInputTarget = mAppWindow;
894 mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
895 mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
896 assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
897 }
898
899 private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
900 return new IDisplayWindowInsetsController.Stub() {
901
902 @Override
903 public void insetsChanged(InsetsState insetsState) throws RemoteException {
904 }
905
906 @Override
907 public void insetsControlChanged(InsetsState insetsState,
908 InsetsSourceControl[] insetsSourceControls) throws RemoteException {
909 }
910
911 @Override
912 public void showInsets(int i, boolean b) throws RemoteException {
913 }
914
915 @Override
916 public void hideInsets(int i, boolean b) throws RemoteException {
917 }
918 };
Tarandeep Singha6f35612019-01-11 19:50:46 -0800919 }
920
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500921 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100922 public void testUpdateSystemGestureExclusion() throws Exception {
923 final DisplayContent dc = createNewDisplay();
924 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
925 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
926 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
927
Riddle Hsu12c05452020-01-09 00:39:52 +0800928 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100929
930 win.setHasSurface(true);
931 dc.updateSystemGestureExclusion();
932
Riddle Hsu73f53572019-09-23 23:13:01 +0800933 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100934 final ISystemGestureExclusionListener.Stub verifier =
935 new ISystemGestureExclusionListener.Stub() {
936 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200937 public void onSystemGestureExclusionChanged(int displayId, Region actual,
938 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100939 Region expected = Region.obtain();
940 expected.set(10, 20, 30, 40);
941 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800942 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100943 }
944 };
945 try {
946 dc.registerSystemGestureExclusionListener(verifier);
947 } finally {
948 dc.unregisterSystemGestureExclusionListener(verifier);
949 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800950 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100951 }
952
953 @Test
954 public void testCalculateSystemGestureExclusion() throws Exception {
955 final DisplayContent dc = createNewDisplay();
956 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
957 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
958 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
959
960 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
961 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
962 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
963
Riddle Hsu12c05452020-01-09 00:39:52 +0800964 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100965
966 win.setHasSurface(true);
967 win2.setHasSurface(true);
968
969 final Region expected = Region.obtain();
970 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200971 assertEquals(expected, calculateSystemGestureExclusion(dc));
972 }
973
974 private Region calculateSystemGestureExclusion(DisplayContent dc) {
975 Region out = Region.obtain();
976 Region unrestricted = Region.obtain();
977 dc.calculateSystemGestureExclusion(out, unrestricted);
978 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100979 }
980
981 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200982 public void testCalculateSystemGestureExclusion_modal() throws Exception {
983 final DisplayContent dc = createNewDisplay();
984 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
985 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
986 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
987
988 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
989 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
990 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
991 win2.getAttrs().width = 10;
992 win2.getAttrs().height = 10;
993 win2.setSystemGestureExclusion(Collections.emptyList());
994
Riddle Hsu12c05452020-01-09 00:39:52 +0800995 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200996
997 win.setHasSurface(true);
998 win2.setHasSurface(true);
999
1000 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +02001001 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +02001002 }
1003
1004 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +02001005 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +02001006 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +02001007
Riddle Hsu73f53572019-09-23 23:13:01 +08001008 final DisplayContent dc = createNewDisplay();
1009 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
1010 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
1011 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
1012 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
1013 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
1014 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
1015 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001016 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +02001017
Riddle Hsu12c05452020-01-09 00:39:52 +08001018 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +02001019
Riddle Hsu73f53572019-09-23 23:13:01 +08001020 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +02001021
Riddle Hsu73f53572019-09-23 23:13:01 +08001022 final Region expected = Region.obtain();
1023 expected.set(dc.getBounds());
1024 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +02001025
Riddle Hsu73f53572019-09-23 23:13:01 +08001026 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +02001027 }
1028
1029 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +08001030 public void testRequestResizeForEmptyFrames() {
1031 final WindowState win = mChildAppWindowAbove;
1032 makeWindowVisible(win, win.getParentWindow());
1033 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
1034 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
1035 win.mAttrs.gravity = Gravity.CENTER;
1036 performLayout(mDisplayContent);
1037
1038 // The frame is empty because the requested height is zero.
1039 assertTrue(win.getFrameLw().isEmpty());
1040 // The window should be scheduled to resize then the client may report a new non-empty size.
1041 win.updateResizingWindowIfNeeded();
1042 assertThat(mWm.mResizingWindows).contains(win);
1043 }
1044
1045 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001046 public void testOrientationChangeLogging() {
1047 MetricsLogger mockLogger = mock(MetricsLogger.class);
1048 Configuration oldConfig = new Configuration();
1049 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
1050
1051 Configuration newConfig = new Configuration();
1052 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +08001053 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001054 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
1055 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +08001056 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001057
1058 displayContent.onConfigurationChanged(newConfig);
1059
1060 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1061 verify(mockLogger).write(logMakerCaptor.capture());
1062 assertThat(logMakerCaptor.getValue().getCategory(),
1063 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
1064 assertThat(logMakerCaptor.getValue().getSubtype(),
1065 is(Configuration.ORIENTATION_PORTRAIT));
1066 }
1067
Evan Rosky69cace42019-09-20 16:28:13 -07001068 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +08001069 public void testApplyTopFixedRotationTransform() {
1070 mWm.mIsFixedRotationTransformEnabled = true;
Vadim Caen4b4fc232020-05-26 20:17:15 +08001071 final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
1072 // Only non-movable (gesture) navigation bar will be animated by fixed rotation animation.
1073 doReturn(false).when(displayPolicy).navigationBarCanMove();
1074 displayPolicy.addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs);
1075 displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001076 final Configuration config90 = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001077 mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001078
1079 final Configuration config = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001080 mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001081 mDisplayContent.computeScreenConfiguration(config);
1082 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1083
1084 final ActivityRecord app = mAppWindow.mActivityRecord;
1085 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1086 false /* alwaysKeepCurrent */);
1087 mDisplayContent.mOpeningApps.add(app);
Riddle Hsud4957432020-04-24 22:06:29 +08001088 final int newOrientation = getRotatedOrientation(mDisplayContent);
1089 app.setRequestedOrientation(newOrientation);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001090
1091 assertTrue(app.isFixedRotationTransforming());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001092 assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
1093 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
1094 false /* forceUpdate */));
Riddle Hsuf41034c2020-03-19 13:10:46 +08001095
Vadim Caen4b4fc232020-05-26 20:17:15 +08001096 assertNotNull(mDisplayContent.getFixedRotationAnimationController());
1097 assertTrue(mStatusBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS,
1098 ANIMATION_TYPE_FIXED_TRANSFORM));
1099 assertTrue(mNavBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS,
1100 ANIMATION_TYPE_FIXED_TRANSFORM));
1101
Riddle Hsuf41034c2020-03-19 13:10:46 +08001102 final Rect outFrame = new Rect();
1103 final Rect outInsets = new Rect();
1104 final Rect outStableInsets = new Rect();
1105 final Rect outSurfaceInsets = new Rect();
1106 mAppWindow.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
1107 // The animation frames should not be rotated because display hasn't rotated.
1108 assertEquals(mDisplayContent.getBounds(), outFrame);
1109
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001110 // The display should keep current orientation and the rotated configuration should apply
1111 // to the activity.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001112 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1113 assertEquals(config90.orientation, app.getConfiguration().orientation);
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001114 assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001115
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001116 // Make wallaper laid out with the fixed rotation transform.
1117 final WindowToken wallpaperToken = mWallpaperWindow.mToken;
1118 wallpaperToken.linkFixedRotationTransform(app);
1119 mWallpaperWindow.mLayoutNeeded = true;
1120 performLayout(mDisplayContent);
1121
Riddle Hsu6da58ac2020-04-02 01:04:40 +08001122 // Force the negative offset to verify it can be updated.
1123 mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
1124 assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
1125 false /* sync */));
1126 assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
1127 assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
1128
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001129 // The wallpaper need to animate with transformed position, so its surface position should
1130 // not be reset.
1131 final Transaction t = wallpaperToken.getPendingTransaction();
1132 spyOn(t);
1133 mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
1134 verify(t, never()).setPosition(any(), eq(0), eq(0));
1135
Riddle Hsud4957432020-04-24 22:06:29 +08001136 // Launch another activity before the transition is finished.
1137 final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
1138 .setDisplay(mDisplayContent).build().getTopMostActivity();
1139 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1140 false /* alwaysKeepCurrent */);
1141 mDisplayContent.mOpeningApps.add(app2);
1142 app2.setRequestedOrientation(newOrientation);
1143
Riddle Hsuf3ff9e72020-05-27 23:15:39 +08001144 // The activity should share the same transform state as the existing one. The activity
1145 // should also be the fixed rotation launching app because it is the latest top.
Riddle Hsud4957432020-04-24 22:06:29 +08001146 assertTrue(app.hasFixedRotationTransform(app2));
Riddle Hsuf3ff9e72020-05-27 23:15:39 +08001147 assertTrue(mDisplayContent.isFixedRotationLaunchingApp(app2));
Riddle Hsud4957432020-04-24 22:06:29 +08001148
Louis Chang242be902020-06-03 12:24:45 +08001149 // The fixed rotation transform can only be finished when all animation finished.
1150 doReturn(false).when(app2).isAnimating(anyInt(), anyInt());
1151 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app2.token);
1152 assertTrue(app.hasFixedRotationTransform());
1153 assertTrue(app2.hasFixedRotationTransform());
1154
Riddle Hsud4957432020-04-24 22:06:29 +08001155 // The display should be rotated after the launch is finished.
Louis Chang242be902020-06-03 12:24:45 +08001156 doReturn(false).when(app).isAnimating(anyInt(), anyInt());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001157 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1158
Riddle Hsud4957432020-04-24 22:06:29 +08001159 // The fixed rotation should be cleared and the new rotation is applied to display.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001160 assertFalse(app.hasFixedRotationTransform());
Riddle Hsud4957432020-04-24 22:06:29 +08001161 assertFalse(app2.hasFixedRotationTransform());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001162 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
Vadim Caen4b4fc232020-05-26 20:17:15 +08001163 assertNull(mDisplayContent.getFixedRotationAnimationController());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001164 }
1165
1166 @Test
Riddle Hsu08bc4ed2020-05-26 18:32:18 +08001167 public void testRotateSeamlesslyWithFixedRotation() {
1168 final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
1169 final ActivityRecord app = mAppWindow.mActivityRecord;
1170 mDisplayContent.setFixedRotationLaunchingAppUnchecked(app);
1171 mAppWindow.mAttrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
1172
1173 // Use seamless rotation if the top app is rotated.
1174 assertTrue(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
1175 ROTATION_90 /* newRotation */, false /* forceUpdate */));
1176
1177 mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(app);
1178
1179 // Use normal rotation because animating recents is an intermediate state.
1180 assertFalse(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
1181 ROTATION_90 /* newRotation */, false /* forceUpdate */));
1182 }
1183
1184 @Test
Riddle Hsu80653ea2020-05-14 22:36:59 +08001185 public void testNoFixedRotationWithPip() {
1186 mWm.mIsFixedRotationTransformEnabled = true;
1187 // Make resume-top really update the activity state.
1188 doReturn(false).when(mWm.mAtmService).isBooting();
1189 doReturn(true).when(mWm.mAtmService).isBooted();
1190 // Speed up the test by a few seconds.
1191 mWm.mAtmService.deferWindowLayout();
1192 doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
1193
1194 final DisplayContent displayContent = mWm.mRoot.getDefaultDisplay();
1195 final Configuration displayConfig = displayContent.getConfiguration();
1196 final ActivityRecord pinnedActivity = createActivityRecord(displayContent,
1197 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
1198 final Task pinnedTask = pinnedActivity.getRootTask();
1199 final ActivityRecord homeActivity = WindowTestUtils.createTestActivityRecord(
1200 displayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
1201 if (displayConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
1202 homeActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
1203 pinnedActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1204 } else {
1205 homeActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1206 pinnedActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
1207 }
1208 final int homeConfigOrientation = homeActivity.getRequestedConfigurationOrientation();
1209 final int pinnedConfigOrientation = pinnedActivity.getRequestedConfigurationOrientation();
1210
1211 assertEquals(homeConfigOrientation, displayConfig.orientation);
1212
1213 clearInvocations(mWm);
1214 // Leave PiP to fullscreen. The orientation can be updated from
1215 // ActivityRecord#reportDescendantOrientationChangeIfNeeded.
1216 pinnedTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
1217 homeActivity.setState(ActivityStack.ActivityState.STOPPED, "test");
1218
1219 assertFalse(displayContent.hasTopFixedRotationLaunchingApp());
1220 verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
1221 assertEquals(pinnedConfigOrientation, displayConfig.orientation);
1222 assertFalse(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
1223
1224 clearInvocations(mWm);
1225 // Enter PiP from fullscreen. The orientation can be updated from
1226 // ensure-visibility/resume-focused-stack -> ActivityRecord#makeActiveIfNeeded -> resume.
1227 pinnedTask.setWindowingMode(WINDOWING_MODE_PINNED);
1228
1229 assertFalse(displayContent.hasTopFixedRotationLaunchingApp());
1230 verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
1231 assertEquals(homeConfigOrientation, displayConfig.orientation);
1232 assertTrue(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
1233 }
1234
1235 @Test
Vadim Caena8849f22020-06-05 12:28:07 +02001236 public void testRecentsNotRotatingWithFixedRotation() {
1237 final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
1238 doCallRealMethod().when(displayRotation).updateRotationUnchecked(anyBoolean());
Riddle Hsu5d165032020-06-18 15:40:48 +08001239 // Skip freezing so the unrelated conditions in updateRotationUnchecked won't disturb.
1240 doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
Vadim Caena8849f22020-06-05 12:28:07 +02001241
1242 final ActivityRecord recentsActivity = createActivityRecord(mDisplayContent,
1243 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
1244 recentsActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
1245
Riddle Hsu5d165032020-06-18 15:40:48 +08001246 // Do not rotate if the recents animation is animating on top.
Vadim Caena8849f22020-06-05 12:28:07 +02001247 mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity);
1248 displayRotation.setRotation((displayRotation.getRotation() + 1) % 4);
1249 assertFalse(displayRotation.updateRotationUnchecked(false));
1250
Riddle Hsu5d165032020-06-18 15:40:48 +08001251 // Rotation can be updated if the recents animation is finished.
Vadim Caena8849f22020-06-05 12:28:07 +02001252 mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false);
1253 assertTrue(displayRotation.updateRotationUnchecked(false));
Riddle Hsu5d165032020-06-18 15:40:48 +08001254
1255 // Rotation can be updated if the recents animation is animating but it is not on top, e.g.
1256 // switching activities in different orientations by quickstep gesture.
1257 mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity);
1258 mDisplayContent.setFixedRotationLaunchingAppUnchecked(mAppWindow.mActivityRecord);
1259 displayRotation.setRotation((displayRotation.getRotation() + 1) % 4);
1260 assertTrue(displayRotation.updateRotationUnchecked(false));
Vadim Caena8849f22020-06-05 12:28:07 +02001261 }
1262
1263 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001264 public void testRemoteRotation() {
1265 DisplayContent dc = createNewDisplay();
1266
1267 final DisplayRotation dr = dc.getDisplayRotation();
Vadim Caena8849f22020-06-05 12:28:07 +02001268 doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
Evan Rosky69cace42019-09-20 16:28:13 -07001269 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1270 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001271 // TODO(display-merge): Remove cast
Charles Chen770597c2020-05-18 19:58:23 +08001272 doAnswer(
Evan Rosky69cace42019-09-20 16:28:13 -07001273 invocation -> {
1274 continued[0] = true;
1275 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001276 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001277 final boolean[] called = new boolean[1];
1278 mWm.mDisplayRotationController =
1279 new IDisplayWindowRotationController.Stub() {
1280 @Override
1281 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1282 IDisplayWindowRotationCallback callback) {
1283 called[0] = true;
1284
1285 try {
1286 callback.continueRotateDisplay(toRotation, null);
1287 } catch (RemoteException e) {
1288 assertTrue(false);
1289 }
1290 }
1291 };
1292
1293 // kill any existing rotation animation (vestigial from test setup).
1294 dc.setRotationAnimation(null);
1295
1296 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1297 assertTrue(called[0]);
1298 waitUntilHandlersIdle();
1299 assertTrue(continued[0]);
1300 }
1301
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001302 @Test
1303 public void testGetOrCreateRootHomeTask_defaultDisplay() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001304 TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001305
1306 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian86d676c2020-03-27 19:34:54 -07001307 ActivityStack homeTask = defaultTaskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001308 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001309 defaultTaskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001310 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001311 assertNull(defaultTaskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001312
Andrii Kulian86d676c2020-03-27 19:34:54 -07001313 assertNotNull(defaultTaskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001314 }
1315
1316 @Test
1317 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1318 DisplayContent display = createNewDisplay();
1319 doReturn(true).when(display).supportsSystemDecorations();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001320
1321 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001322 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Andrii Kulian86d676c2020-03-27 19:34:54 -07001323 ActivityStack homeTask = taskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001324 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001325 taskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001326 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001327 assertNull(taskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001328
Andrii Kulian86d676c2020-03-27 19:34:54 -07001329 assertNotNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001330 }
1331
1332 @Test
1333 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1334 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001335 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001336 doReturn(false).when(display).supportsSystemDecorations();
1337
Andrii Kulian86d676c2020-03-27 19:34:54 -07001338 assertNull(taskDisplayArea.getRootHomeTask());
1339 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001340 }
1341
1342 @Test
Charles Chenb28fb722020-05-21 17:19:32 +08001343 public void testGetOrCreateRootHomeTask_untrustedDisplay() {
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001344 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001345 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Charles Chenb28fb722020-05-21 17:19:32 +08001346 doReturn(false).when(display).isTrusted();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001347
Andrii Kulian86d676c2020-03-27 19:34:54 -07001348 assertNull(taskDisplayArea.getRootHomeTask());
1349 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001350 }
1351
Mark Renoufa9279292020-04-17 12:22:50 -04001352 @Test
1353 public void testFindScrollCaptureTargetWindow_behindWindow() {
1354 DisplayContent display = createNewDisplay();
1355 ActivityStack stack = createTaskStackOnDisplay(display);
1356 Task task = createTaskInStack(stack, 0 /* userId */);
1357 WindowState activityWindow = createAppWindow(task, TYPE_APPLICATION, "App Window");
1358 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1359
1360 WindowState result = display.findScrollCaptureTargetWindow(behindWindow,
1361 ActivityTaskManager.INVALID_TASK_ID);
1362 assertEquals(activityWindow, result);
1363 }
1364
1365 @Test
1366 public void testFindScrollCaptureTargetWindow_taskId() {
1367 DisplayContent display = createNewDisplay();
1368 ActivityStack stack = createTaskStackOnDisplay(display);
1369 Task task = createTaskInStack(stack, 0 /* userId */);
1370 WindowState window = createAppWindow(task, TYPE_APPLICATION, "App Window");
1371 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1372
1373 WindowState result = display.findScrollCaptureTargetWindow(null, task.mTaskId);
1374 assertEquals(window, result);
1375 }
1376
Charles Chen770597c2020-05-18 19:58:23 +08001377 @Test
1378 public void testEnsureActivitiesVisibleNotRecursive() {
1379 final TaskDisplayArea mockTda = mock(TaskDisplayArea.class);
1380 doReturn(mockTda).when(mDisplayContent).getTaskDisplayAreaAt(anyInt());
1381 final boolean[] called = { false };
1382 doAnswer(invocation -> {
1383 // The assertion will fail if DisplayArea#ensureActivitiesVisible is called twice.
1384 assertFalse(called[0]);
1385 called[0] = true;
1386 mDisplayContent.ensureActivitiesVisible(null, 0, false, false);
1387 return null;
1388 }).when(mockTda).ensureActivitiesVisible(any(), anyInt(), anyBoolean(), anyBoolean());
1389
1390 mDisplayContent.ensureActivitiesVisible(null, 0, false, false);
1391 }
1392
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001393 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001394 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001395 }
1396
Bryce Lee27cec322017-03-21 09:41:37 -07001397 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1398 int expectedBaseHeight, int expectedBaseDensity) {
1399 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1400 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1401 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1402 }
1403
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001404 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001405 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001406 }
1407
Riddle Hsu12c05452020-01-09 00:39:52 +08001408 private void performLayout(DisplayContent dc) {
1409 dc.setLayoutNeeded();
1410 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1411 }
1412
Riddle Hsu654a6f92018-07-13 22:59:36 +08001413 /**
1414 * Create DisplayContent that does not update display base/initial values from device to keep
1415 * the values set by test.
1416 */
1417 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001418 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001419 doNothing().when(displayContent).updateDisplayInfo();
1420 return displayContent;
1421 }
1422
Adrian Roos0f9368c2018-04-08 10:59:08 -07001423 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1424 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001425
1426 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001427 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001428 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1429
1430 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001431
1432 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001433 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001434 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1435 }
1436
Riddle Hsud4957432020-04-24 22:06:29 +08001437 private static int getRotatedOrientation(DisplayContent dc) {
Vadim Caen4b4fc232020-05-26 20:17:15 +08001438 return dc.mBaseDisplayWidth > dc.mBaseDisplayHeight
Riddle Hsud4957432020-04-24 22:06:29 +08001439 ? SCREEN_ORIENTATION_PORTRAIT
1440 : SCREEN_ORIENTATION_LANDSCAPE;
1441 }
1442
Adrian Roos0f9368c2018-04-08 10:59:08 -07001443 private static List<WindowState> reverseList(List<WindowState> list) {
1444 final ArrayList<WindowState> result = new ArrayList<>(list);
1445 Collections.reverse(result);
1446 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001447 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001448
Arthur Hungbe5ce212018-09-13 18:41:56 +08001449 private void tapOnDisplay(final DisplayContent dc) {
1450 final DisplayMetrics dm = dc.getDisplayMetrics();
1451 final float x = dm.widthPixels / 2;
1452 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001453 final long downTime = SystemClock.uptimeMillis();
1454 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001455 // sending ACTION_DOWN
1456 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001457 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001458 downTime,
1459 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001460 x,
1461 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001462 0 /*metaState*/);
1463 downEvent.setDisplayId(dc.getDisplayId());
1464 dc.mTapDetector.onPointerEvent(downEvent);
1465
1466 // sending ACTION_UP
1467 final MotionEvent upEvent = MotionEvent.obtain(
1468 downTime,
1469 eventTime,
1470 MotionEvent.ACTION_UP,
1471 x,
1472 y,
1473 0 /*metaState*/);
1474 upEvent.setDisplayId(dc.getDisplayId());
1475 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001476 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001477}