blob: 80fcf2e121f4dbc0b301c6571f87aeecbeba1330 [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Garfield Tan98eead32019-11-18 13:24:53 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Andrii Kulian92c9a942017-10-10 00:41:41 -070020import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
22import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080024import static android.os.Build.VERSION_CODES.P;
25import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020027import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
28import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010029import static android.view.DisplayCutout.fromBoundingRect;
Riddle Hsu9239d7c62020-02-20 01:35:56 +080030import static android.view.Surface.ROTATION_0;
Evan Rosky69cace42019-09-20 16:28:13 -070031import static android.view.Surface.ROTATION_90;
Adrian Roos019a52b2019-07-02 16:47:44 +020032import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
33import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
34import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010035import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
36import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020037import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
38import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080039import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
40import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080041import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080042import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
wilsonshihe8321942019-10-18 18:39:46 +080043import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
Mark Renoufa9279292020-04-17 12:22:50 -040044import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
Andrii Kulian92c9a942017-10-10 00:41:41 -070045import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080046import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060047import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070048
Garfield Tan90b04282018-12-11 14:04:42 -080049import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
50import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090051import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080052import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080053import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
54import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060055import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080056import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080057import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090058import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
59import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Riddle Hsufc246d12020-03-20 18:28:11 +080060import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
David Stevens46939562017-03-24 13:04:00 -070061import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080062import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080063
Riddle Hsu12c05452020-01-09 00:39:52 +080064import static com.google.common.truth.Truth.assertThat;
65
Adrian Roos5251b1d2018-03-23 18:57:43 +010066import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080067import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070068import static org.junit.Assert.assertFalse;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020069import static org.junit.Assert.assertNotEquals;
Arthur Hungbe5ce212018-09-13 18:41:56 +080070import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080071import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010072import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080073import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070074import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080075import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080076
Andrii Kulian92c9a942017-10-10 00:41:41 -070077import android.annotation.SuppressLint;
Mark Renoufa9279292020-04-17 12:22:50 -040078import android.app.ActivityTaskManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080079import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080080import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010081import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010082import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050083import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070084import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070085import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070086import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070087import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010088import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080089import android.view.Gravity;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020090import android.view.IDisplayWindowInsetsController;
Evan Rosky69cace42019-09-20 16:28:13 -070091import android.view.IDisplayWindowRotationCallback;
92import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010093import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080094import android.view.IWindowManager;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020095import android.view.InsetsSourceControl;
96import android.view.InsetsState;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070097import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010098import android.view.Surface;
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +080099import android.view.SurfaceControl.Transaction;
Tarandeep Singha6f35612019-01-11 19:50:46 -0800100import android.view.ViewRootImpl;
Riddle Hsu12c05452020-01-09 00:39:52 +0800101import android.view.WindowManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -0800102import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700103
Brett Chabota26eda92018-07-23 13:08:30 -0700104import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -0700105
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500106import com.android.internal.logging.MetricsLogger;
107import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100108import com.android.server.wm.utils.WmDisplayCutout;
109
Brett Chabota26eda92018-07-23 13:08:30 -0700110import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800111import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800112import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500113import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700114
Adrian Roos0f9368c2018-04-08 10:59:08 -0700115import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800116import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700117import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800118import java.util.LinkedList;
119import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700120
121/**
122 * Tests for the {@link DisplayContent} class.
123 *
124 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900125 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700126 */
127@SmallTest
128@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800129@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800130public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700131
132 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700133 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800134 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700135 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700136 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900137 // Wait until everything in animation handler get executed to prevent the exiting window
138 // from being removed during WindowSurfacePlacer Traversal.
139 waitUntilHandlersIdle();
140
Garfield Tane8d84ab2019-10-11 09:49:40 -0700141 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800142 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700143
Wale Ogunwale34247952017-02-19 11:57:53 -0800144 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700145 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800146 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700147 mChildAppWindowBelow,
148 mAppWindow,
149 mChildAppWindowAbove,
150 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200151 mImeWindow,
152 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800154 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200155 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800156 }
157
158 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700159 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800160 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700161 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800162
lumarkff0ab692018-11-05 20:32:30 +0800163 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800164
Wale Ogunwale34247952017-02-19 11:57:53 -0800165 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700166 mWallpaperWindow,
167 mChildAppWindowBelow,
168 mAppWindow,
169 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800170 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700171 mImeWindow,
172 mImeDialogWindow,
173 mDockedDividerWindow,
174 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800175 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700176 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800177 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800178
Wale Ogunwale34247952017-02-19 11:57:53 -0800179 @Test
lumarkff0ab692018-11-05 20:32:30 +0800180 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
181 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800182
Wale Ogunwale34247952017-02-19 11:57:53 -0800183 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700184 mWallpaperWindow,
185 mChildAppWindowBelow,
186 mAppWindow,
187 mChildAppWindowAbove,
188 mImeWindow,
189 mImeDialogWindow,
190 mDockedDividerWindow,
191 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800192 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700193 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700194 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800195
196 @Test
lumarkff0ab692018-11-05 20:32:30 +0800197 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
198 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800199
Wale Ogunwale34247952017-02-19 11:57:53 -0800200 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700201 mWallpaperWindow,
202 mChildAppWindowBelow,
203 mAppWindow,
204 mChildAppWindowAbove,
205 mDockedDividerWindow,
206 mStatusBarWindow,
207 mImeWindow,
208 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800209 mNotificationShadeWindow,
210 mNavBarWindow));
211 }
212
213 @Test
214 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
215 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
216
217 assertForAllWindowsOrder(Arrays.asList(
218 mWallpaperWindow,
219 mChildAppWindowBelow,
220 mAppWindow,
221 mChildAppWindowAbove,
222 mDockedDividerWindow,
223 mStatusBarWindow,
224 mNotificationShadeWindow,
225 mImeWindow,
226 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700227 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800228 }
229
230 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700231 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800232 // This window is set-up to be z-ordered between some windows that go in the same token like
233 // the nav bar and status bar.
234 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700235 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800236
Wale Ogunwale34247952017-02-19 11:57:53 -0800237 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700238 mWallpaperWindow,
239 mChildAppWindowBelow,
240 mAppWindow,
241 mChildAppWindowAbove,
242 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800243 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200244 mImeWindow,
245 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700246 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800247 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200248 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800249 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800250
Wale Ogunwale34247952017-02-19 11:57:53 -0800251 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700252 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800253 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700254 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800255 appWin.setHasSurface(true);
256 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700257 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800258 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800259 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800260
Wale Ogunwale34247952017-02-19 11:57:53 -0800261 // Verify that an child window can be an ime target.
262 final WindowState childWin = createWindow(appWin,
263 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
264 childWin.setHasSurface(true);
265 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700266 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800267 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800268 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800269
Andrii Kuliand68501e2017-01-10 22:57:27 -0800270 /**
271 * This tests stack movement between displays and proper stack's, task's and app token's display
272 * container references updates.
273 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800274 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700275 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800276 // Create a second display.
277 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800278
279 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700280 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800281 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800282 assertEquals(dc, stack.getDisplayContent());
283
284 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700285 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
286 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800287 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700288 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800289
290 // Move stack to first display.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700291 stack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true /* onTop */);
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700292 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700293 assertEquals(mDisplayContent, stack.getDisplayContent());
294 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700295 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800296 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800297
298 /**
299 * This tests override configuration updates for display content.
300 */
301 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700302 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700303 final Configuration currentOverrideConfig =
304 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800305
306 // Create new, slightly changed override configuration and apply it to the display.
307 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
308 newOverrideConfig.densityDpi += 120;
309 newOverrideConfig.fontScale += 0.3;
310
Evan Roskye747c3e2018-10-30 20:06:41 -0700311 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800312
313 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700314 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800315 }
316
317 /**
318 * This tests global configuration updates when default display config is updated.
319 */
320 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700321 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700322 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
323 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800324
325 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700326 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800327 newOverrideConfig.densityDpi += 120;
328 newOverrideConfig.fontScale += 0.3;
329
Evan Roskye747c3e2018-10-30 20:06:41 -0700330 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800331
332 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700333 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800334 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
335 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800336
337 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700338 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700340 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
341 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800342 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800343
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700344 /**
345 * Tests tapping on a stack in different display results in window gaining focus.
346 */
347 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700348 public void testInputEventBringsCorrectDisplayInFocus() {
349 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700350 // Create a second display
351 final DisplayContent dc1 = createNewDisplay();
352
353 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700354 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700355 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700356 final ActivityRecord activity =
357 WindowTestUtils.createTestActivityRecord(dc0);
358 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800359 dc0.configureDisplayPolicy();
360 assertNotNull(dc0.mTapDetector);
361
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700362 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700363 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700364 final ActivityRecord activity1 =
365 WindowTestUtils.createTestActivityRecord(dc0);
366 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800367 dc1.configureDisplayPolicy();
368 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700369
Arthur Hungbe5ce212018-09-13 18:41:56 +0800370 // tap on primary display.
371 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700372 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700373 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800374 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700375
Arthur Hungbe5ce212018-09-13 18:41:56 +0800376 // Tap on secondary display.
377 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700378 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700379 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800380 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700381 }
382
David Stevens46939562017-03-24 13:04:00 -0700383 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700384 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800385 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
386 }
387
388 @Test
389 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
390 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
391 }
392
393 @Test
394 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
395 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
396 }
397
398 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
399 int targetSdk) {
400 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
401
Andrii Kulian0214ed92017-05-16 13:44:05 -0700402 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700403 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700404 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700405 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800406 updateFocusedWindow();
407 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700408 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700409
410 // Check that a new display doesn't affect focus
411 final DisplayContent dc = createNewDisplay();
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 // Add a window to the second display, and it should be focused
417 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700418 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800419 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800420 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800421 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700422 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700423
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800424 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700425 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800426 updateFocusedWindow();
427 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800428 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700429 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800430
431 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100432 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700433 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800434 updateFocusedWindow();
435 assertTrue(!window1.isFocused());
436 assertEquals(window1.getDisplayId(),
437 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200438 }
439
Riddle Hsub2297ad2019-07-26 23:37:25 -0600440 @Test
441 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
442 mWm.mSystemBooted = true;
443 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
444 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
445 TYPE_WALLPAPER, TYPE_APPLICATION);
446
447 // Verify waiting for windows to be drawn.
448 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
449
450 // Verify not waiting for drawn windows.
451 makeWindowsDrawn(windows);
452 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
453 }
454
455 @Test
456 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
457 mWm.mSystemBooted = true;
458 final DisplayContent secondaryDisplay = createNewDisplay();
459 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
460 TYPE_WALLPAPER, TYPE_APPLICATION);
461
462 // Verify not waiting for display without system decorations.
463 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
464 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
465
466 // Verify waiting for non-drawn windows on display with system decorations.
467 reset(secondaryDisplay);
468 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
469 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
470
471 // Verify not waiting for drawn windows on display with system decorations.
472 makeWindowsDrawn(windows);
473 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
474 }
475
476 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
477 final WindowState[] windows = new WindowState[types.length];
478 for (int i = 0; i < types.length; i++) {
479 final int type = types[i];
480 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
481 windows[i].mHasSurface = false;
482 }
483 return windows;
484 }
485
486 private static void makeWindowsDrawn(WindowState[] windows) {
487 for (WindowState window : windows) {
488 window.mHasSurface = true;
489 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
490 }
491 }
492
Bryce Lee27cec322017-03-21 09:41:37 -0700493 /**
494 * This tests setting the maximum ui width on a display.
495 */
496 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700497 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800498 // Prevent base display metrics for test from being updated to the value of real display.
499 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700500 final int baseWidth = 1440;
501 final int baseHeight = 2560;
502 final int baseDensity = 300;
503
Riddle Hsu654a6f92018-07-13 22:59:36 +0800504 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700505
506 final int maxWidth = 300;
507 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
508 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
509
Riddle Hsu654a6f92018-07-13 22:59:36 +0800510 displayContent.setMaxUiWidth(maxWidth);
511 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700512
513 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800514 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
515 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700516
517 final int smallerWidth = 200;
518 final int smallerHeight = 400;
519 final int smallerDensity = 100;
520
521 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800522 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
523 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700524
525 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800526 displayContent.setMaxUiWidth(maxWidth);
527 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700528 }
529
Andrii Kulian92c9a942017-10-10 00:41:41 -0700530 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700531 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800532 final DisplayContent dc = createNewDisplay();
533 dc.mInitialDisplayWidth = 200;
534 dc.mInitialDisplayHeight = 400;
535 final Rect r = new Rect(80, 0, 120, 10);
536 final DisplayCutout cutout = new WmDisplayCutout(
537 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
538 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100539
Riddle Hsu73f53572019-09-23 23:13:01 +0800540 dc.mInitialDisplayCutout = cutout;
541 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
542 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100543
Riddle Hsu73f53572019-09-23 23:13:01 +0800544 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100545 }
546
547 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700548 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800549 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
550 // if the device has no cutout).
551 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800552 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
553 // landscape display let's rotate it.
554 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
555 int tmp = dc.mInitialDisplayHeight;
556 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
557 dc.mInitialDisplayWidth = tmp;
558 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800559 // Rotation may use real display info to compute bound, so here also uses the
560 // same width and height.
561 final int displayWidth = dc.mInitialDisplayWidth;
562 final int displayHeight = dc.mInitialDisplayHeight;
563 final int cutoutWidth = 40;
564 final int cutoutHeight = 10;
565 final int left = (displayWidth - cutoutWidth) / 2;
566 final int top = 0;
567 final int right = (displayWidth + cutoutWidth) / 2;
568 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800569
Riddle Hsu73f53572019-09-23 23:13:01 +0800570 final Rect r1 = new Rect(left, top, right, bottom);
571 final DisplayCutout cutout = new WmDisplayCutout(
572 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
573 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100574
Riddle Hsu73f53572019-09-23 23:13:01 +0800575 dc.mInitialDisplayCutout = cutout;
576 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
577 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100578
Riddle Hsu73f53572019-09-23 23:13:01 +0800579 // ----o---------- -------------
580 // | | | | |
581 // | ------o | o---
582 // | | | |
583 // | | -> | |
584 // | | ---o
585 // | | |
586 // | | -------------
587 final Rect r = new Rect(top, left, bottom, right);
588 assertEquals(new WmDisplayCutout(
589 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
590 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
591 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100592 }
593
594 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700595 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800596 final DisplayContent dc = createNewDisplay();
597 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100598
Riddle Hsu12c05452020-01-09 00:39:52 +0800599 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100600
Riddle Hsu73f53572019-09-23 23:13:01 +0800601 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100602 }
603
604 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700605 @SuppressLint("InlinedApi")
606 public void testOrientationDefinedByKeyguard() {
607 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800608
609 // When display content is created its configuration is not yet initialized, which could
610 // cause unnecessary configuration propagation, so initialize it here.
611 final Configuration config = new Configuration();
612 dc.computeScreenConfiguration(config);
613 dc.onRequestedOverrideConfigurationChanged(config);
614
Andrii Kulian92c9a942017-10-10 00:41:41 -0700615 // Create a window that requests landscape orientation. It will define device orientation
616 // by default.
617 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700618 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700619
wilsonshihe8321942019-10-18 18:39:46 +0800620 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700621 keyguard.mHasSurface = true;
622 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
623
624 assertEquals("Screen orientation must be defined by the app window by default",
625 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
626
627 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
628 assertEquals("Visible keyguard must influence device orientation",
629 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
630
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700631 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700632 assertEquals("Keyguard that is going away must not influence device orientation",
633 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
634 }
635
Andrii Kulianf0379de2018-03-14 16:24:07 -0700636 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800637 public void testOrientationForAspectRatio() {
638 final DisplayContent dc = createNewDisplay();
639
640 // When display content is created its configuration is not yet initialized, which could
641 // cause unnecessary configuration propagation, so initialize it here.
642 final Configuration config = new Configuration();
643 dc.computeScreenConfiguration(config);
644 dc.onRequestedOverrideConfigurationChanged(config);
645
646 // Create a window that requests a fixed orientation. It will define device orientation
647 // by default.
648 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
649 "window");
650 window.mHasSurface = true;
651 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
652
653 // --------------------------------
654 // Test non-close-to-square display
655 // --------------------------------
656 dc.mBaseDisplayWidth = 1000;
657 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
658 dc.configureDisplayPolicy();
659
660 assertEquals("Screen orientation must be defined by the window by default.",
661 window.mAttrs.screenOrientation, dc.getOrientation());
662
663 // ----------------------------
664 // Test close-to-square display
665 // ----------------------------
666 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
667 dc.configureDisplayPolicy();
668
669 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
670 SCREEN_ORIENTATION_USER, dc.getOrientation());
671 }
672
673 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700674 public void testDisableDisplayInfoOverrideFromWindowManager() {
675 final DisplayContent dc = createNewDisplay();
676
677 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700678 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700679
680 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700681 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700682 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
683 }
684
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800685 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800686 public void testClearLastFocusWhenReparentingFocusedWindow() {
687 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
688 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
689 defaultDisplay, "window");
690 defaultDisplay.mLastFocus = window;
691 mDisplayContent.mCurrentFocus = window;
692 mDisplayContent.reParentWindowToken(window.mToken);
693
694 assertNull(defaultDisplay.mLastFocus);
695 }
696
697 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800698 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
699 final DisplayContent portraitDisplay = createNewDisplay();
700 portraitDisplay.mInitialDisplayHeight = 2000;
701 portraitDisplay.mInitialDisplayWidth = 1000;
702
Riddle Hsuccf09402019-08-13 00:33:06 +0800703 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800704 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700705 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800706 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
707
708 final DisplayContent landscapeDisplay = createNewDisplay();
709 landscapeDisplay.mInitialDisplayHeight = 1000;
710 landscapeDisplay.mInitialDisplayWidth = 2000;
711
Riddle Hsuccf09402019-08-13 00:33:06 +0800712 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800713 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700714 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800715 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
716 }
717
lumarkff0ab692018-11-05 20:32:30 +0800718 @Test
719 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
720 final DisplayContent newDisplay = createNewDisplay();
721
722 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
723 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
724 appWin.setHasSurface(true);
725 appWin1.setHasSurface(true);
726
727 // Set current input method window on default display, make sure the input method target
728 // is appWin & null on the other display.
729 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
730 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200731 assertEquals("appWin should be IME target window",
732 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800733 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
734
735 // Switch input method window on new display & make sure the input method target also
736 // switched as expected.
737 newDisplay.setInputMethodWindowLocked(mImeWindow);
738 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200739 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800740 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
741 }
742
Garfield Tan90b04282018-12-11 14:04:42 -0800743 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800744 public void testAllowsTopmostFullscreenOrientation() {
745 final DisplayContent dc = createNewDisplay();
746 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800747 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800748
749 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800750 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800751 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800752 .build();
753 doReturn(true).when(stack).isVisible();
754
755 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800756 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800757 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800758 .setWindowingMode(WINDOWING_MODE_FREEFORM)
759 .build();
760 doReturn(true).when(freeformStack).isVisible();
761 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
762
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700763 assertTrue(dc.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM));
Garfield Tan98eead32019-11-18 13:24:53 -0800764
765 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
766 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
767 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
768
769 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
770 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
771 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
772 }
773
774 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800775 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800776 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700777 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800778 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800779 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
780 ? SCREEN_ORIENTATION_PORTRAIT
781 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800782
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700783 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800784 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800785 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900786 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800787
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700788 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800789
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700790 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
791 ? Configuration.ORIENTATION_PORTRAIT
792 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700793 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800794 }
795
796 @Test
797 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800798 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800799 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800800 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800801 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
802 ? SCREEN_ORIENTATION_PORTRAIT
803 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800804
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700805 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800806 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800807 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900808 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800809
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700810 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800811
Louis Chang677921f2019-12-06 16:44:24 +0800812 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
813 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700814 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800815 }
816
Tarandeep Singha6f35612019-01-11 19:50:46 -0800817 @Test
818 public void testComputeImeParent_app() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200819 final DisplayContent dc = createNewDisplay();
820 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
821 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
822 dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800823 }
824
825 @Test
826 public void testComputeImeParent_app_notFullscreen() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200827 final DisplayContent dc = createNewDisplay();
828 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
829 dc.mInputMethodTarget.setWindowingMode(
830 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
831 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800832 }
833
834 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800835 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700836 spyOn(mAppWindow.mActivityRecord);
837 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800838 mDisplayContent.mInputMethodTarget = mAppWindow;
839 // The surface parent of IME should be the display instead of app window.
Adrian Roos329cbd02020-04-14 15:42:41 +0200840 assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
841 mDisplayContent.computeImeParent());
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800842 }
843
844 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800845 public void testComputeImeParent_noApp() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200846 final DisplayContent dc = createNewDisplay();
847 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
848 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
849 }
850
851 @Test
852 public void testComputeImeControlTarget() throws Exception {
853 final DisplayContent dc = createNewDisplay();
854 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
855 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
856 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
857 assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
858 }
859
860 @Test
861 public void testComputeImeControlTarget_splitscreen() throws Exception {
862 final DisplayContent dc = createNewDisplay();
863 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
864 dc.mInputMethodInputTarget.setWindowingMode(
865 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
866 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
867 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
868 assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
869 }
870
871 @Test
872 public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
873 spyOn(mAppWindow.mActivityRecord);
874 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
875 mDisplayContent.mInputMethodInputTarget = mAppWindow;
876 mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
877 mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
878 assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
879 }
880
881 private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
882 return new IDisplayWindowInsetsController.Stub() {
883
884 @Override
885 public void insetsChanged(InsetsState insetsState) throws RemoteException {
886 }
887
888 @Override
889 public void insetsControlChanged(InsetsState insetsState,
890 InsetsSourceControl[] insetsSourceControls) throws RemoteException {
891 }
892
893 @Override
894 public void showInsets(int i, boolean b) throws RemoteException {
895 }
896
897 @Override
898 public void hideInsets(int i, boolean b) throws RemoteException {
899 }
900 };
Tarandeep Singha6f35612019-01-11 19:50:46 -0800901 }
902
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500903 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100904 public void testUpdateSystemGestureExclusion() throws Exception {
905 final DisplayContent dc = createNewDisplay();
906 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
907 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
908 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
909
Riddle Hsu12c05452020-01-09 00:39:52 +0800910 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100911
912 win.setHasSurface(true);
913 dc.updateSystemGestureExclusion();
914
Riddle Hsu73f53572019-09-23 23:13:01 +0800915 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100916 final ISystemGestureExclusionListener.Stub verifier =
917 new ISystemGestureExclusionListener.Stub() {
918 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200919 public void onSystemGestureExclusionChanged(int displayId, Region actual,
920 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100921 Region expected = Region.obtain();
922 expected.set(10, 20, 30, 40);
923 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800924 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100925 }
926 };
927 try {
928 dc.registerSystemGestureExclusionListener(verifier);
929 } finally {
930 dc.unregisterSystemGestureExclusionListener(verifier);
931 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800932 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100933 }
934
935 @Test
936 public void testCalculateSystemGestureExclusion() throws Exception {
937 final DisplayContent dc = createNewDisplay();
938 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
939 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
940 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
941
942 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
943 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
944 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
945
Riddle Hsu12c05452020-01-09 00:39:52 +0800946 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100947
948 win.setHasSurface(true);
949 win2.setHasSurface(true);
950
951 final Region expected = Region.obtain();
952 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200953 assertEquals(expected, calculateSystemGestureExclusion(dc));
954 }
955
956 private Region calculateSystemGestureExclusion(DisplayContent dc) {
957 Region out = Region.obtain();
958 Region unrestricted = Region.obtain();
959 dc.calculateSystemGestureExclusion(out, unrestricted);
960 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100961 }
962
963 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200964 public void testCalculateSystemGestureExclusion_modal() throws Exception {
965 final DisplayContent dc = createNewDisplay();
966 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
967 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
968 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
969
970 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
971 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
972 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
973 win2.getAttrs().width = 10;
974 win2.getAttrs().height = 10;
975 win2.setSystemGestureExclusion(Collections.emptyList());
976
Riddle Hsu12c05452020-01-09 00:39:52 +0800977 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200978
979 win.setHasSurface(true);
980 win2.setHasSurface(true);
981
982 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200983 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200984 }
985
986 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200987 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200988 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200989
Riddle Hsu73f53572019-09-23 23:13:01 +0800990 final DisplayContent dc = createNewDisplay();
991 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
992 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
993 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
994 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
995 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
996 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
997 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700998 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200999
Riddle Hsu12c05452020-01-09 00:39:52 +08001000 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +02001001
Riddle Hsu73f53572019-09-23 23:13:01 +08001002 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +02001003
Riddle Hsu73f53572019-09-23 23:13:01 +08001004 final Region expected = Region.obtain();
1005 expected.set(dc.getBounds());
1006 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +02001007
Riddle Hsu73f53572019-09-23 23:13:01 +08001008 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +02001009 }
1010
1011 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +08001012 public void testRequestResizeForEmptyFrames() {
1013 final WindowState win = mChildAppWindowAbove;
1014 makeWindowVisible(win, win.getParentWindow());
1015 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
1016 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
1017 win.mAttrs.gravity = Gravity.CENTER;
1018 performLayout(mDisplayContent);
1019
1020 // The frame is empty because the requested height is zero.
1021 assertTrue(win.getFrameLw().isEmpty());
1022 // The window should be scheduled to resize then the client may report a new non-empty size.
1023 win.updateResizingWindowIfNeeded();
1024 assertThat(mWm.mResizingWindows).contains(win);
1025 }
1026
1027 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001028 public void testOrientationChangeLogging() {
1029 MetricsLogger mockLogger = mock(MetricsLogger.class);
1030 Configuration oldConfig = new Configuration();
1031 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
1032
1033 Configuration newConfig = new Configuration();
1034 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +08001035 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001036 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
1037 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +08001038 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001039
1040 displayContent.onConfigurationChanged(newConfig);
1041
1042 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1043 verify(mockLogger).write(logMakerCaptor.capture());
1044 assertThat(logMakerCaptor.getValue().getCategory(),
1045 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
1046 assertThat(logMakerCaptor.getValue().getSubtype(),
1047 is(Configuration.ORIENTATION_PORTRAIT));
1048 }
1049
Evan Rosky69cace42019-09-20 16:28:13 -07001050 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +08001051 public void testApplyTopFixedRotationTransform() {
1052 mWm.mIsFixedRotationTransformEnabled = true;
1053 final Configuration config90 = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001054 mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001055
1056 final Configuration config = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001057 mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001058 mDisplayContent.computeScreenConfiguration(config);
1059 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1060
Riddle Hsufc246d12020-03-20 18:28:11 +08001061 final ActivityRecord closingApp = new ActivityTestsBase.StackBuilder(mWm.mRoot)
1062 .setDisplay(mDisplayContent).setOnTop(false).build().getTopMostActivity();
1063 closingApp.nowVisible = true;
1064 closingApp.startAnimation(closingApp.getPendingTransaction(), mock(AnimationAdapter.class),
1065 false /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
1066 assertTrue(closingApp.isAnimating());
1067
Riddle Hsu6f548e92020-01-13 13:34:09 +08001068 final ActivityRecord app = mAppWindow.mActivityRecord;
1069 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1070 false /* alwaysKeepCurrent */);
1071 mDisplayContent.mOpeningApps.add(app);
1072 app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1073
1074 assertTrue(app.isFixedRotationTransforming());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001075 assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
1076 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
1077 false /* forceUpdate */));
Riddle Hsuf41034c2020-03-19 13:10:46 +08001078
1079 final Rect outFrame = new Rect();
1080 final Rect outInsets = new Rect();
1081 final Rect outStableInsets = new Rect();
1082 final Rect outSurfaceInsets = new Rect();
1083 mAppWindow.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
1084 // The animation frames should not be rotated because display hasn't rotated.
1085 assertEquals(mDisplayContent.getBounds(), outFrame);
1086
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001087 // The display should keep current orientation and the rotated configuration should apply
1088 // to the activity.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001089 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1090 assertEquals(config90.orientation, app.getConfiguration().orientation);
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001091 assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001092
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001093 // Make wallaper laid out with the fixed rotation transform.
1094 final WindowToken wallpaperToken = mWallpaperWindow.mToken;
1095 wallpaperToken.linkFixedRotationTransform(app);
1096 mWallpaperWindow.mLayoutNeeded = true;
1097 performLayout(mDisplayContent);
1098
Riddle Hsu6da58ac2020-04-02 01:04:40 +08001099 // Force the negative offset to verify it can be updated.
1100 mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
1101 assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
1102 false /* sync */));
1103 assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
1104 assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
1105
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001106 // The wallpaper need to animate with transformed position, so its surface position should
1107 // not be reset.
1108 final Transaction t = wallpaperToken.getPendingTransaction();
1109 spyOn(t);
1110 mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
1111 verify(t, never()).setPosition(any(), eq(0), eq(0));
1112
Riddle Hsu6f548e92020-01-13 13:34:09 +08001113 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1114
Riddle Hsufc246d12020-03-20 18:28:11 +08001115 // The animation in old rotation should be cancelled.
1116 assertFalse(closingApp.isAnimating());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001117 // The display should be rotated after the launch is finished.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001118 assertFalse(app.hasFixedRotationTransform());
1119 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
1120 }
1121
1122 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001123 public void testRemoteRotation() {
1124 DisplayContent dc = createNewDisplay();
1125
1126 final DisplayRotation dr = dc.getDisplayRotation();
1127 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
1128 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1129 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001130 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -07001131 Mockito.doAnswer(
1132 invocation -> {
1133 continued[0] = true;
1134 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001135 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001136 final boolean[] called = new boolean[1];
1137 mWm.mDisplayRotationController =
1138 new IDisplayWindowRotationController.Stub() {
1139 @Override
1140 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1141 IDisplayWindowRotationCallback callback) {
1142 called[0] = true;
1143
1144 try {
1145 callback.continueRotateDisplay(toRotation, null);
1146 } catch (RemoteException e) {
1147 assertTrue(false);
1148 }
1149 }
1150 };
1151
1152 // kill any existing rotation animation (vestigial from test setup).
1153 dc.setRotationAnimation(null);
1154
1155 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1156 assertTrue(called[0]);
1157 waitUntilHandlersIdle();
1158 assertTrue(continued[0]);
1159 }
1160
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001161 @Test
1162 public void testGetOrCreateRootHomeTask_defaultDisplay() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001163 TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001164
1165 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian86d676c2020-03-27 19:34:54 -07001166 ActivityStack homeTask = defaultTaskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001167 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001168 defaultTaskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001169 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001170 assertNull(defaultTaskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001171
Andrii Kulian86d676c2020-03-27 19:34:54 -07001172 assertNotNull(defaultTaskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001173 }
1174
1175 @Test
1176 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1177 DisplayContent display = createNewDisplay();
1178 doReturn(true).when(display).supportsSystemDecorations();
1179 doReturn(false).when(display).isUntrustedVirtualDisplay();
1180
1181 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001182 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Andrii Kulian86d676c2020-03-27 19:34:54 -07001183 ActivityStack homeTask = taskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001184 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001185 taskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001186 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001187 assertNull(taskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001188
Andrii Kulian86d676c2020-03-27 19:34:54 -07001189 assertNotNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001190 }
1191
1192 @Test
1193 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1194 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001195 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001196 doReturn(false).when(display).supportsSystemDecorations();
1197
Andrii Kulian86d676c2020-03-27 19:34:54 -07001198 assertNull(taskDisplayArea.getRootHomeTask());
1199 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001200 }
1201
1202 @Test
1203 public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
1204 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001205 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001206 doReturn(true).when(display).isUntrustedVirtualDisplay();
1207
Andrii Kulian86d676c2020-03-27 19:34:54 -07001208 assertNull(taskDisplayArea.getRootHomeTask());
1209 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001210 }
1211
Mark Renoufa9279292020-04-17 12:22:50 -04001212 @Test
1213 public void testFindScrollCaptureTargetWindow_behindWindow() {
1214 DisplayContent display = createNewDisplay();
1215 ActivityStack stack = createTaskStackOnDisplay(display);
1216 Task task = createTaskInStack(stack, 0 /* userId */);
1217 WindowState activityWindow = createAppWindow(task, TYPE_APPLICATION, "App Window");
1218 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1219
1220 WindowState result = display.findScrollCaptureTargetWindow(behindWindow,
1221 ActivityTaskManager.INVALID_TASK_ID);
1222 assertEquals(activityWindow, result);
1223 }
1224
1225 @Test
1226 public void testFindScrollCaptureTargetWindow_taskId() {
1227 DisplayContent display = createNewDisplay();
1228 ActivityStack stack = createTaskStackOnDisplay(display);
1229 Task task = createTaskInStack(stack, 0 /* userId */);
1230 WindowState window = createAppWindow(task, TYPE_APPLICATION, "App Window");
1231 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1232
1233 WindowState result = display.findScrollCaptureTargetWindow(null, task.mTaskId);
1234 assertEquals(window, result);
1235 }
1236
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001237 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001238 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001239 }
1240
Bryce Lee27cec322017-03-21 09:41:37 -07001241 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1242 int expectedBaseHeight, int expectedBaseDensity) {
1243 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1244 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1245 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1246 }
1247
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001248 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001249 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001250 }
1251
Riddle Hsu12c05452020-01-09 00:39:52 +08001252 private void performLayout(DisplayContent dc) {
1253 dc.setLayoutNeeded();
1254 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1255 }
1256
Riddle Hsu654a6f92018-07-13 22:59:36 +08001257 /**
1258 * Create DisplayContent that does not update display base/initial values from device to keep
1259 * the values set by test.
1260 */
1261 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001262 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001263 doNothing().when(displayContent).updateDisplayInfo();
1264 return displayContent;
1265 }
1266
Adrian Roos0f9368c2018-04-08 10:59:08 -07001267 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1268 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001269
1270 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001271 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001272 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1273
1274 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001275
1276 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001277 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001278 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1279 }
1280
1281 private static List<WindowState> reverseList(List<WindowState> list) {
1282 final ArrayList<WindowState> result = new ArrayList<>(list);
1283 Collections.reverse(result);
1284 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001285 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001286
Arthur Hungbe5ce212018-09-13 18:41:56 +08001287 private void tapOnDisplay(final DisplayContent dc) {
1288 final DisplayMetrics dm = dc.getDisplayMetrics();
1289 final float x = dm.widthPixels / 2;
1290 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001291 final long downTime = SystemClock.uptimeMillis();
1292 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001293 // sending ACTION_DOWN
1294 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001295 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001296 downTime,
1297 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001298 x,
1299 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001300 0 /*metaState*/);
1301 downEvent.setDisplayId(dc.getDisplayId());
1302 dc.mTapDetector.onPointerEvent(downEvent);
1303
1304 // sending ACTION_UP
1305 final MotionEvent upEvent = MotionEvent.obtain(
1306 downTime,
1307 eventTime,
1308 MotionEvent.ACTION_UP,
1309 x,
1310 y,
1311 0 /*metaState*/);
1312 upEvent.setDisplayId(dc.getDisplayId());
1313 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001314 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001315}