blob: 1a8f2a6b65f537a1e12ceef8541eafb34793ba69 [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;
Evan Rosky69cace42019-09-20 16:28:13 -070030import static android.view.Surface.ROTATION_90;
Adrian Roos019a52b2019-07-02 16:47:44 +020031import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
32import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
33import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010034import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
35import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020036import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
37import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
39import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080040import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080041import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
wilsonshihe8321942019-10-18 18:39:46 +080042import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
Andrii Kulian92c9a942017-10-10 00:41:41 -070043import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080044import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060045import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070046
Garfield Tan90b04282018-12-11 14:04:42 -080047import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
48import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090049import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080050import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080051import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
52import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060053import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080054import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080055import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090056import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
57import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070058import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080059import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080060
Riddle Hsu12c05452020-01-09 00:39:52 +080061import static com.google.common.truth.Truth.assertThat;
62
Adrian Roos5251b1d2018-03-23 18:57:43 +010063import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080064import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070065import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080066import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080067import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010068import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080069import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070070import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080071import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080072
Andrii Kulian92c9a942017-10-10 00:41:41 -070073import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080074import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080075import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010076import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010077import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050078import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070079import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070080import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070081import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070082import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010083import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080084import android.view.Gravity;
Evan Rosky69cace42019-09-20 16:28:13 -070085import android.view.IDisplayWindowRotationCallback;
86import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010087import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080088import android.view.IWindowManager;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070089import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010090import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080091import android.view.ViewRootImpl;
Riddle Hsu12c05452020-01-09 00:39:52 +080092import android.view.WindowManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080093import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070094
Brett Chabota26eda92018-07-23 13:08:30 -070095import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070096
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050097import com.android.internal.logging.MetricsLogger;
98import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010099import com.android.server.wm.utils.WmDisplayCutout;
100
Brett Chabota26eda92018-07-23 13:08:30 -0700101import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800102import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800103import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500104import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700105
Adrian Roos0f9368c2018-04-08 10:59:08 -0700106import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800107import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700108import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800109import java.util.LinkedList;
110import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700111
112/**
113 * Tests for the {@link DisplayContent} class.
114 *
115 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900116 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700117 */
118@SmallTest
119@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800120@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800121public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700122
123 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700124 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800125 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700126 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700127 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900128 // Wait until everything in animation handler get executed to prevent the exiting window
129 // from being removed during WindowSurfacePlacer Traversal.
130 waitUntilHandlersIdle();
131
Garfield Tane8d84ab2019-10-11 09:49:40 -0700132 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800133 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700134
Wale Ogunwale34247952017-02-19 11:57:53 -0800135 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700136 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800137 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700138 mChildAppWindowBelow,
139 mAppWindow,
140 mChildAppWindowAbove,
141 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200142 mImeWindow,
143 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700144 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800145 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200146 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800147 }
148
149 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700150 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800151 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700152 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800153
lumarkff0ab692018-11-05 20:32:30 +0800154 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800155
Wale Ogunwale34247952017-02-19 11:57:53 -0800156 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700157 mWallpaperWindow,
158 mChildAppWindowBelow,
159 mAppWindow,
160 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800161 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700162 mImeWindow,
163 mImeDialogWindow,
164 mDockedDividerWindow,
165 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800166 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700167 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800168 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800169
Wale Ogunwale34247952017-02-19 11:57:53 -0800170 @Test
lumarkff0ab692018-11-05 20:32:30 +0800171 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
172 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800173
Wale Ogunwale34247952017-02-19 11:57:53 -0800174 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700175 mWallpaperWindow,
176 mChildAppWindowBelow,
177 mAppWindow,
178 mChildAppWindowAbove,
179 mImeWindow,
180 mImeDialogWindow,
181 mDockedDividerWindow,
182 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800183 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700184 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700185 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800186
187 @Test
lumarkff0ab692018-11-05 20:32:30 +0800188 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
189 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800190
Wale Ogunwale34247952017-02-19 11:57:53 -0800191 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700192 mWallpaperWindow,
193 mChildAppWindowBelow,
194 mAppWindow,
195 mChildAppWindowAbove,
196 mDockedDividerWindow,
197 mStatusBarWindow,
198 mImeWindow,
199 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800200 mNotificationShadeWindow,
201 mNavBarWindow));
202 }
203
204 @Test
205 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
206 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
207
208 assertForAllWindowsOrder(Arrays.asList(
209 mWallpaperWindow,
210 mChildAppWindowBelow,
211 mAppWindow,
212 mChildAppWindowAbove,
213 mDockedDividerWindow,
214 mStatusBarWindow,
215 mNotificationShadeWindow,
216 mImeWindow,
217 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700218 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800219 }
220
221 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700222 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800223 // This window is set-up to be z-ordered between some windows that go in the same token like
224 // the nav bar and status bar.
225 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700226 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800227
Wale Ogunwale34247952017-02-19 11:57:53 -0800228 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700229 mWallpaperWindow,
230 mChildAppWindowBelow,
231 mAppWindow,
232 mChildAppWindowAbove,
233 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800234 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200235 mImeWindow,
236 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700237 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800238 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200239 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800240 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800241
Wale Ogunwale34247952017-02-19 11:57:53 -0800242 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700243 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800244 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700245 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800246 appWin.setHasSurface(true);
247 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700248 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800249 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800250 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800251
Wale Ogunwale34247952017-02-19 11:57:53 -0800252 // Verify that an child window can be an ime target.
253 final WindowState childWin = createWindow(appWin,
254 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
255 childWin.setHasSurface(true);
256 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700257 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800258 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800259 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800260
Andrii Kuliand68501e2017-01-10 22:57:27 -0800261 /**
262 * This tests stack movement between displays and proper stack's, task's and app token's display
263 * container references updates.
264 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800265 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700266 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800267 // Create a second display.
268 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800269
270 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700271 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800272 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800273 assertEquals(dc, stack.getDisplayContent());
274
275 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700276 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
277 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800278 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700279 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800280
281 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700282 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
283 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700284 assertEquals(mDisplayContent, stack.getDisplayContent());
285 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700286 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800287 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800288
289 /**
290 * This tests override configuration updates for display content.
291 */
292 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700293 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700294 final Configuration currentOverrideConfig =
295 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800296
297 // Create new, slightly changed override configuration and apply it to the display.
298 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
299 newOverrideConfig.densityDpi += 120;
300 newOverrideConfig.fontScale += 0.3;
301
Evan Roskye747c3e2018-10-30 20:06:41 -0700302 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800303
304 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700305 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800306 }
307
308 /**
309 * This tests global configuration updates when default display config is updated.
310 */
311 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700312 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700313 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
314 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800315
316 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700317 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800318 newOverrideConfig.densityDpi += 120;
319 newOverrideConfig.fontScale += 0.3;
320
Evan Roskye747c3e2018-10-30 20:06:41 -0700321 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800322
323 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700324 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800325 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
326 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800327
328 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700329 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700330 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700331 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
332 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800333 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800334
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700335 /**
336 * Tests tapping on a stack in different display results in window gaining focus.
337 */
338 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700339 public void testInputEventBringsCorrectDisplayInFocus() {
340 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700341 // Create a second display
342 final DisplayContent dc1 = createNewDisplay();
343
344 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700345 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700346 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700347 final ActivityRecord activity =
348 WindowTestUtils.createTestActivityRecord(dc0);
349 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800350 dc0.configureDisplayPolicy();
351 assertNotNull(dc0.mTapDetector);
352
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700353 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700354 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700355 final ActivityRecord activity1 =
356 WindowTestUtils.createTestActivityRecord(dc0);
357 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800358 dc1.configureDisplayPolicy();
359 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700360
Arthur Hungbe5ce212018-09-13 18:41:56 +0800361 // tap on primary display.
362 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700363 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700364 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800365 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700366
Arthur Hungbe5ce212018-09-13 18:41:56 +0800367 // Tap on secondary display.
368 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700369 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700370 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800371 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700372 }
373
David Stevens46939562017-03-24 13:04:00 -0700374 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700375 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800376 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
377 }
378
379 @Test
380 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
381 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
382 }
383
384 @Test
385 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
386 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
387 }
388
389 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
390 int targetSdk) {
391 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
392
Andrii Kulian0214ed92017-05-16 13:44:05 -0700393 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700394 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700395 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700396 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800397 updateFocusedWindow();
398 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700399 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700400
401 // Check that a new display doesn't affect focus
402 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800403 updateFocusedWindow();
404 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700405 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700406
407 // Add a window to the second display, and it should be focused
408 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700409 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800410 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800411 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800412 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700413 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700414
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800415 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700416 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800417 updateFocusedWindow();
418 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800419 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700420 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800421
422 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100423 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700424 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800425 updateFocusedWindow();
426 assertTrue(!window1.isFocused());
427 assertEquals(window1.getDisplayId(),
428 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200429 }
430
Riddle Hsub2297ad2019-07-26 23:37:25 -0600431 @Test
432 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
433 mWm.mSystemBooted = true;
434 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
435 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
436 TYPE_WALLPAPER, TYPE_APPLICATION);
437
438 // Verify waiting for windows to be drawn.
439 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
440
441 // Verify not waiting for drawn windows.
442 makeWindowsDrawn(windows);
443 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
444 }
445
446 @Test
447 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
448 mWm.mSystemBooted = true;
449 final DisplayContent secondaryDisplay = createNewDisplay();
450 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
451 TYPE_WALLPAPER, TYPE_APPLICATION);
452
453 // Verify not waiting for display without system decorations.
454 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
455 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
456
457 // Verify waiting for non-drawn windows on display with system decorations.
458 reset(secondaryDisplay);
459 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
460 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
461
462 // Verify not waiting for drawn windows on display with system decorations.
463 makeWindowsDrawn(windows);
464 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
465 }
466
467 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
468 final WindowState[] windows = new WindowState[types.length];
469 for (int i = 0; i < types.length; i++) {
470 final int type = types[i];
471 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
472 windows[i].mHasSurface = false;
473 }
474 return windows;
475 }
476
477 private static void makeWindowsDrawn(WindowState[] windows) {
478 for (WindowState window : windows) {
479 window.mHasSurface = true;
480 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
481 }
482 }
483
Bryce Lee27cec322017-03-21 09:41:37 -0700484 /**
485 * This tests setting the maximum ui width on a display.
486 */
487 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700488 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800489 // Prevent base display metrics for test from being updated to the value of real display.
490 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700491 final int baseWidth = 1440;
492 final int baseHeight = 2560;
493 final int baseDensity = 300;
494
Riddle Hsu654a6f92018-07-13 22:59:36 +0800495 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700496
497 final int maxWidth = 300;
498 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
499 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
500
Riddle Hsu654a6f92018-07-13 22:59:36 +0800501 displayContent.setMaxUiWidth(maxWidth);
502 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700503
504 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800505 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
506 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700507
508 final int smallerWidth = 200;
509 final int smallerHeight = 400;
510 final int smallerDensity = 100;
511
512 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800513 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
514 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700515
516 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800517 displayContent.setMaxUiWidth(maxWidth);
518 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700519 }
520
Andrii Kulian92c9a942017-10-10 00:41:41 -0700521 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700522 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800523 final DisplayContent dc = createNewDisplay();
524 dc.mInitialDisplayWidth = 200;
525 dc.mInitialDisplayHeight = 400;
526 final Rect r = new Rect(80, 0, 120, 10);
527 final DisplayCutout cutout = new WmDisplayCutout(
528 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
529 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100530
Riddle Hsu73f53572019-09-23 23:13:01 +0800531 dc.mInitialDisplayCutout = cutout;
532 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
533 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100534
Riddle Hsu73f53572019-09-23 23:13:01 +0800535 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100536 }
537
538 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700539 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800540 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
541 // if the device has no cutout).
542 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800543 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
544 // landscape display let's rotate it.
545 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
546 int tmp = dc.mInitialDisplayHeight;
547 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
548 dc.mInitialDisplayWidth = tmp;
549 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800550 // Rotation may use real display info to compute bound, so here also uses the
551 // same width and height.
552 final int displayWidth = dc.mInitialDisplayWidth;
553 final int displayHeight = dc.mInitialDisplayHeight;
554 final int cutoutWidth = 40;
555 final int cutoutHeight = 10;
556 final int left = (displayWidth - cutoutWidth) / 2;
557 final int top = 0;
558 final int right = (displayWidth + cutoutWidth) / 2;
559 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800560
Riddle Hsu73f53572019-09-23 23:13:01 +0800561 final Rect r1 = new Rect(left, top, right, bottom);
562 final DisplayCutout cutout = new WmDisplayCutout(
563 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
564 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100565
Riddle Hsu73f53572019-09-23 23:13:01 +0800566 dc.mInitialDisplayCutout = cutout;
567 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
568 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100569
Riddle Hsu73f53572019-09-23 23:13:01 +0800570 // ----o---------- -------------
571 // | | | | |
572 // | ------o | o---
573 // | | | |
574 // | | -> | |
575 // | | ---o
576 // | | |
577 // | | -------------
578 final Rect r = new Rect(top, left, bottom, right);
579 assertEquals(new WmDisplayCutout(
580 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
581 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
582 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100583 }
584
585 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700586 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800587 final DisplayContent dc = createNewDisplay();
588 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100589
Riddle Hsu12c05452020-01-09 00:39:52 +0800590 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100591
Riddle Hsu73f53572019-09-23 23:13:01 +0800592 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100593 }
594
595 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700596 @SuppressLint("InlinedApi")
597 public void testOrientationDefinedByKeyguard() {
598 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800599
600 // When display content is created its configuration is not yet initialized, which could
601 // cause unnecessary configuration propagation, so initialize it here.
602 final Configuration config = new Configuration();
603 dc.computeScreenConfiguration(config);
604 dc.onRequestedOverrideConfigurationChanged(config);
605
Andrii Kulian92c9a942017-10-10 00:41:41 -0700606 // Create a window that requests landscape orientation. It will define device orientation
607 // by default.
608 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700609 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700610
wilsonshihe8321942019-10-18 18:39:46 +0800611 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700612 keyguard.mHasSurface = true;
613 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
614
615 assertEquals("Screen orientation must be defined by the app window by default",
616 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
617
618 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
619 assertEquals("Visible keyguard must influence device orientation",
620 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
621
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700622 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700623 assertEquals("Keyguard that is going away must not influence device orientation",
624 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
625 }
626
Andrii Kulianf0379de2018-03-14 16:24:07 -0700627 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800628 public void testOrientationForAspectRatio() {
629 final DisplayContent dc = createNewDisplay();
630
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
637 // Create a window that requests a fixed orientation. It will define device orientation
638 // by default.
639 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
640 "window");
641 window.mHasSurface = true;
642 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
643
644 // --------------------------------
645 // Test non-close-to-square display
646 // --------------------------------
647 dc.mBaseDisplayWidth = 1000;
648 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
649 dc.configureDisplayPolicy();
650
651 assertEquals("Screen orientation must be defined by the window by default.",
652 window.mAttrs.screenOrientation, dc.getOrientation());
653
654 // ----------------------------
655 // Test close-to-square display
656 // ----------------------------
657 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
658 dc.configureDisplayPolicy();
659
660 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
661 SCREEN_ORIENTATION_USER, dc.getOrientation());
662 }
663
664 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700665 public void testDisableDisplayInfoOverrideFromWindowManager() {
666 final DisplayContent dc = createNewDisplay();
667
668 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700669 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700670
671 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700672 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700673 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
674 }
675
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800676 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800677 public void testClearLastFocusWhenReparentingFocusedWindow() {
678 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
679 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
680 defaultDisplay, "window");
681 defaultDisplay.mLastFocus = window;
682 mDisplayContent.mCurrentFocus = window;
683 mDisplayContent.reParentWindowToken(window.mToken);
684
685 assertNull(defaultDisplay.mLastFocus);
686 }
687
688 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800689 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
690 final DisplayContent portraitDisplay = createNewDisplay();
691 portraitDisplay.mInitialDisplayHeight = 2000;
692 portraitDisplay.mInitialDisplayWidth = 1000;
693
Riddle Hsuccf09402019-08-13 00:33:06 +0800694 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800695 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700696 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800697 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
698
699 final DisplayContent landscapeDisplay = createNewDisplay();
700 landscapeDisplay.mInitialDisplayHeight = 1000;
701 landscapeDisplay.mInitialDisplayWidth = 2000;
702
Riddle Hsuccf09402019-08-13 00:33:06 +0800703 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800704 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700705 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800706 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
707 }
708
lumarkff0ab692018-11-05 20:32:30 +0800709 @Test
710 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
711 final DisplayContent newDisplay = createNewDisplay();
712
713 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
714 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
715 appWin.setHasSurface(true);
716 appWin1.setHasSurface(true);
717
718 // Set current input method window on default display, make sure the input method target
719 // is appWin & null on the other display.
720 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
721 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200722 assertEquals("appWin should be IME target window",
723 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800724 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
725
726 // Switch input method window on new display & make sure the input method target also
727 // switched as expected.
728 newDisplay.setInputMethodWindowLocked(mImeWindow);
729 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200730 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800731 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
732 }
733
Garfield Tan90b04282018-12-11 14:04:42 -0800734 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800735 public void testAllowsTopmostFullscreenOrientation() {
736 final DisplayContent dc = createNewDisplay();
737 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800738 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800739
740 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800741 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800742 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800743 .build();
744 doReturn(true).when(stack).isVisible();
745
746 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800747 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800748 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800749 .setWindowingMode(WINDOWING_MODE_FREEFORM)
750 .build();
751 doReturn(true).when(freeformStack).isVisible();
752 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
753
754 assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
755
756 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
757 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
758 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
759
760 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
761 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
762 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
763 }
764
765 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800766 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800767 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700768 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800769 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800770 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
771 ? SCREEN_ORIENTATION_PORTRAIT
772 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800773
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700774 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800775 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800776 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900777 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800778
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700779 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800780
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700781 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
782 ? Configuration.ORIENTATION_PORTRAIT
783 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700784 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800785 }
786
787 @Test
788 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800789 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800790 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800791 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800792 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
793 ? SCREEN_ORIENTATION_PORTRAIT
794 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800795
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700796 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800797 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800798 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900799 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800800
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700801 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800802
Louis Chang677921f2019-12-06 16:44:24 +0800803 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
804 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700805 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800806 }
807
Tarandeep Singha6f35612019-01-11 19:50:46 -0800808 @Test
809 public void testComputeImeParent_app() throws Exception {
810 try (final InsetsModeSession session =
811 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
812 final DisplayContent dc = createNewDisplay();
813 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700814 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800815 dc.computeImeParent());
816 }
817 }
818
819 @Test
820 public void testComputeImeParent_app_notFullscreen() throws Exception {
821 try (final InsetsModeSession session =
822 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
823 final DisplayContent dc = createNewDisplay();
824 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
825 dc.mInputMethodTarget.setWindowingMode(
826 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
827 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
828 }
829 }
830
831 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800832 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700833 spyOn(mAppWindow.mActivityRecord);
834 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800835 mDisplayContent.mInputMethodTarget = mAppWindow;
836 // The surface parent of IME should be the display instead of app window.
837 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
838 }
839
840 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800841 public void testComputeImeParent_noApp() throws Exception {
842 try (final InsetsModeSession session =
843 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
844 final DisplayContent dc = createNewDisplay();
845 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
846 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
847 }
848 }
849
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500850 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100851 public void testUpdateSystemGestureExclusion() throws Exception {
852 final DisplayContent dc = createNewDisplay();
853 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
854 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
855 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
856
Riddle Hsu12c05452020-01-09 00:39:52 +0800857 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100858
859 win.setHasSurface(true);
860 dc.updateSystemGestureExclusion();
861
Riddle Hsu73f53572019-09-23 23:13:01 +0800862 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100863 final ISystemGestureExclusionListener.Stub verifier =
864 new ISystemGestureExclusionListener.Stub() {
865 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200866 public void onSystemGestureExclusionChanged(int displayId, Region actual,
867 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100868 Region expected = Region.obtain();
869 expected.set(10, 20, 30, 40);
870 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800871 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100872 }
873 };
874 try {
875 dc.registerSystemGestureExclusionListener(verifier);
876 } finally {
877 dc.unregisterSystemGestureExclusionListener(verifier);
878 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800879 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100880 }
881
882 @Test
883 public void testCalculateSystemGestureExclusion() throws Exception {
884 final DisplayContent dc = createNewDisplay();
885 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
886 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
887 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
888
889 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
890 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
891 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
892
Riddle Hsu12c05452020-01-09 00:39:52 +0800893 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100894
895 win.setHasSurface(true);
896 win2.setHasSurface(true);
897
898 final Region expected = Region.obtain();
899 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200900 assertEquals(expected, calculateSystemGestureExclusion(dc));
901 }
902
903 private Region calculateSystemGestureExclusion(DisplayContent dc) {
904 Region out = Region.obtain();
905 Region unrestricted = Region.obtain();
906 dc.calculateSystemGestureExclusion(out, unrestricted);
907 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100908 }
909
910 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200911 public void testCalculateSystemGestureExclusion_modal() throws Exception {
912 final DisplayContent dc = createNewDisplay();
913 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
914 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
915 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
916
917 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
918 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
919 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
920 win2.getAttrs().width = 10;
921 win2.getAttrs().height = 10;
922 win2.setSystemGestureExclusion(Collections.emptyList());
923
Riddle Hsu12c05452020-01-09 00:39:52 +0800924 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200925
926 win.setHasSurface(true);
927 win2.setHasSurface(true);
928
929 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200930 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200931 }
932
933 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200934 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200935 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200936
Riddle Hsu73f53572019-09-23 23:13:01 +0800937 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.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
941 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
942 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
943 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
944 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700945 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200946
Riddle Hsu12c05452020-01-09 00:39:52 +0800947 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +0200948
Riddle Hsu73f53572019-09-23 23:13:01 +0800949 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200950
Riddle Hsu73f53572019-09-23 23:13:01 +0800951 final Region expected = Region.obtain();
952 expected.set(dc.getBounds());
953 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200954
Riddle Hsu73f53572019-09-23 23:13:01 +0800955 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200956 }
957
958 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +0800959 public void testRequestResizeForEmptyFrames() {
960 final WindowState win = mChildAppWindowAbove;
961 makeWindowVisible(win, win.getParentWindow());
962 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
963 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
964 win.mAttrs.gravity = Gravity.CENTER;
965 performLayout(mDisplayContent);
966
967 // The frame is empty because the requested height is zero.
968 assertTrue(win.getFrameLw().isEmpty());
969 // The window should be scheduled to resize then the client may report a new non-empty size.
970 win.updateResizingWindowIfNeeded();
971 assertThat(mWm.mResizingWindows).contains(win);
972 }
973
974 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500975 public void testOrientationChangeLogging() {
976 MetricsLogger mockLogger = mock(MetricsLogger.class);
977 Configuration oldConfig = new Configuration();
978 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
979
980 Configuration newConfig = new Configuration();
981 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800982 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500983 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
984 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +0800985 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500986
987 displayContent.onConfigurationChanged(newConfig);
988
989 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
990 verify(mockLogger).write(logMakerCaptor.capture());
991 assertThat(logMakerCaptor.getValue().getCategory(),
992 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
993 assertThat(logMakerCaptor.getValue().getSubtype(),
994 is(Configuration.ORIENTATION_PORTRAIT));
995 }
996
Evan Rosky69cace42019-09-20 16:28:13 -0700997 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +0800998 public void testApplyTopFixedRotationTransform() {
999 mWm.mIsFixedRotationTransformEnabled = true;
1000 final Configuration config90 = new Configuration();
1001 mDisplayContent.getDisplayRotation().setRotation(ROTATION_90);
1002 mDisplayContent.computeScreenConfiguration(config90);
1003 mDisplayContent.onRequestedOverrideConfigurationChanged(config90);
1004
1005 final Configuration config = new Configuration();
1006 mDisplayContent.getDisplayRotation().setRotation(Surface.ROTATION_0);
1007 mDisplayContent.computeScreenConfiguration(config);
1008 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1009
1010 final ActivityRecord app = mAppWindow.mActivityRecord;
1011 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1012 false /* alwaysKeepCurrent */);
1013 mDisplayContent.mOpeningApps.add(app);
1014 app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1015
1016 assertTrue(app.isFixedRotationTransforming());
1017 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1018 assertEquals(config90.orientation, app.getConfiguration().orientation);
1019
1020 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1021
1022 assertFalse(app.hasFixedRotationTransform());
1023 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
1024 }
1025
1026 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001027 public void testRemoteRotation() {
1028 DisplayContent dc = createNewDisplay();
1029
1030 final DisplayRotation dr = dc.getDisplayRotation();
1031 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
1032 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1033 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001034 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -07001035 Mockito.doAnswer(
1036 invocation -> {
1037 continued[0] = true;
1038 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001039 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001040 final boolean[] called = new boolean[1];
1041 mWm.mDisplayRotationController =
1042 new IDisplayWindowRotationController.Stub() {
1043 @Override
1044 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1045 IDisplayWindowRotationCallback callback) {
1046 called[0] = true;
1047
1048 try {
1049 callback.continueRotateDisplay(toRotation, null);
1050 } catch (RemoteException e) {
1051 assertTrue(false);
1052 }
1053 }
1054 };
1055
1056 // kill any existing rotation animation (vestigial from test setup).
1057 dc.setRotationAnimation(null);
1058
1059 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1060 assertTrue(called[0]);
1061 waitUntilHandlersIdle();
1062 assertTrue(continued[0]);
1063 }
1064
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001065 @Test
1066 public void testGetOrCreateRootHomeTask_defaultDisplay() {
1067 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
1068
1069 // Remove the current home stack if it exists so a new one can be created below.
1070 ActivityStack homeTask = defaultDisplay.getRootHomeTask();
1071 if (homeTask != null) {
1072 defaultDisplay.removeStack(homeTask);
1073 }
1074 assertNull(defaultDisplay.getRootHomeTask());
1075
1076 assertNotNull(defaultDisplay.getOrCreateRootHomeTask());
1077 }
1078
1079 @Test
1080 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1081 DisplayContent display = createNewDisplay();
1082 doReturn(true).when(display).supportsSystemDecorations();
1083 doReturn(false).when(display).isUntrustedVirtualDisplay();
1084
1085 // Remove the current home stack if it exists so a new one can be created below.
1086 ActivityStack homeTask = display.getRootHomeTask();
1087 if (homeTask != null) {
1088 display.removeStack(homeTask);
1089 }
1090 assertNull(display.getRootHomeTask());
1091
1092 assertNotNull(display.getOrCreateRootHomeTask());
1093 }
1094
1095 @Test
1096 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1097 DisplayContent display = createNewDisplay();
1098 doReturn(false).when(display).supportsSystemDecorations();
1099
1100 assertNull(display.getRootHomeTask());
1101 assertNull(display.getOrCreateRootHomeTask());
1102 }
1103
1104 @Test
1105 public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
1106 DisplayContent display = createNewDisplay();
1107 doReturn(true).when(display).isUntrustedVirtualDisplay();
1108
1109 assertNull(display.getRootHomeTask());
1110 assertNull(display.getOrCreateRootHomeTask());
1111 }
1112
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001113 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001114 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001115 }
1116
Bryce Lee27cec322017-03-21 09:41:37 -07001117 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1118 int expectedBaseHeight, int expectedBaseDensity) {
1119 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1120 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1121 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1122 }
1123
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001124 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001125 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001126 }
1127
Riddle Hsu12c05452020-01-09 00:39:52 +08001128 private void performLayout(DisplayContent dc) {
1129 dc.setLayoutNeeded();
1130 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1131 }
1132
Riddle Hsu654a6f92018-07-13 22:59:36 +08001133 /**
1134 * Create DisplayContent that does not update display base/initial values from device to keep
1135 * the values set by test.
1136 */
1137 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001138 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001139 doNothing().when(displayContent).updateDisplayInfo();
1140 return displayContent;
1141 }
1142
Adrian Roos0f9368c2018-04-08 10:59:08 -07001143 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1144 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001145
1146 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001147 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001148 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1149
1150 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001151
1152 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001153 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001154 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1155 }
1156
1157 private static List<WindowState> reverseList(List<WindowState> list) {
1158 final ArrayList<WindowState> result = new ArrayList<>(list);
1159 Collections.reverse(result);
1160 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001161 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001162
Arthur Hungbe5ce212018-09-13 18:41:56 +08001163 private void tapOnDisplay(final DisplayContent dc) {
1164 final DisplayMetrics dm = dc.getDisplayMetrics();
1165 final float x = dm.widthPixels / 2;
1166 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001167 final long downTime = SystemClock.uptimeMillis();
1168 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001169 // sending ACTION_DOWN
1170 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001171 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001172 downTime,
1173 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001174 x,
1175 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001176 0 /*metaState*/);
1177 downEvent.setDisplayId(dc.getDisplayId());
1178 dc.mTapDetector.onPointerEvent(downEvent);
1179
1180 // sending ACTION_UP
1181 final MotionEvent upEvent = MotionEvent.obtain(
1182 downTime,
1183 eventTime,
1184 MotionEvent.ACTION_UP,
1185 x,
1186 y,
1187 0 /*metaState*/);
1188 upEvent.setDisplayId(dc.getDisplayId());
1189 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001190 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001191}