blob: 218c8169e7e608ba5899a9562468fd1d0fc5250c [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;
Andrii Kulian92c9a942017-10-10 00:41:41 -070044import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080045import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060046import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070047
Garfield Tan90b04282018-12-11 14:04:42 -080048import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
49import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090050import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080051import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080052import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
53import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060054import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080055import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080056import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090057import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
58import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070059import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080060import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080061
Riddle Hsu12c05452020-01-09 00:39:52 +080062import static com.google.common.truth.Truth.assertThat;
63
Adrian Roos5251b1d2018-03-23 18:57:43 +010064import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080065import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070066import static org.junit.Assert.assertFalse;
Arthur Hungbe5ce212018-09-13 18:41:56 +080067import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080068import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010069import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080070import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070071import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080072import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080073
Andrii Kulian92c9a942017-10-10 00:41:41 -070074import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080075import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080076import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010077import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010078import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050079import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070080import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070081import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070082import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070083import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010084import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080085import android.view.Gravity;
Evan Rosky69cace42019-09-20 16:28:13 -070086import android.view.IDisplayWindowRotationCallback;
87import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010088import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080089import android.view.IWindowManager;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070090import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010091import android.view.Surface;
Tarandeep Singha6f35612019-01-11 19:50:46 -080092import android.view.ViewRootImpl;
Riddle Hsu12c05452020-01-09 00:39:52 +080093import android.view.WindowManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080094import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070095
Brett Chabota26eda92018-07-23 13:08:30 -070096import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070097
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050098import com.android.internal.logging.MetricsLogger;
99import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100100import com.android.server.wm.utils.WmDisplayCutout;
101
Brett Chabota26eda92018-07-23 13:08:30 -0700102import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800103import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800104import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500105import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700106
Adrian Roos0f9368c2018-04-08 10:59:08 -0700107import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800108import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700109import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800110import java.util.LinkedList;
111import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700112
113/**
114 * Tests for the {@link DisplayContent} class.
115 *
116 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900117 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700118 */
119@SmallTest
120@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800121@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800122public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700123
124 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700125 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800126 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700127 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700128 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900129 // Wait until everything in animation handler get executed to prevent the exiting window
130 // from being removed during WindowSurfacePlacer Traversal.
131 waitUntilHandlersIdle();
132
Garfield Tane8d84ab2019-10-11 09:49:40 -0700133 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800134 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700135
Wale Ogunwale34247952017-02-19 11:57:53 -0800136 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700137 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800138 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700139 mChildAppWindowBelow,
140 mAppWindow,
141 mChildAppWindowAbove,
142 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200143 mImeWindow,
144 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700145 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800146 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200147 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800148 }
149
150 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700151 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800152 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700153 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800154
lumarkff0ab692018-11-05 20:32:30 +0800155 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800156
Wale Ogunwale34247952017-02-19 11:57:53 -0800157 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700158 mWallpaperWindow,
159 mChildAppWindowBelow,
160 mAppWindow,
161 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800162 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700163 mImeWindow,
164 mImeDialogWindow,
165 mDockedDividerWindow,
166 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800167 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700168 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800169 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800170
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 @Test
lumarkff0ab692018-11-05 20:32:30 +0800172 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
173 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800174
Wale Ogunwale34247952017-02-19 11:57:53 -0800175 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700176 mWallpaperWindow,
177 mChildAppWindowBelow,
178 mAppWindow,
179 mChildAppWindowAbove,
180 mImeWindow,
181 mImeDialogWindow,
182 mDockedDividerWindow,
183 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800184 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700185 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700186 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800187
188 @Test
lumarkff0ab692018-11-05 20:32:30 +0800189 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
190 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800191
Wale Ogunwale34247952017-02-19 11:57:53 -0800192 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700193 mWallpaperWindow,
194 mChildAppWindowBelow,
195 mAppWindow,
196 mChildAppWindowAbove,
197 mDockedDividerWindow,
198 mStatusBarWindow,
199 mImeWindow,
200 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800201 mNotificationShadeWindow,
202 mNavBarWindow));
203 }
204
205 @Test
206 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
207 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
208
209 assertForAllWindowsOrder(Arrays.asList(
210 mWallpaperWindow,
211 mChildAppWindowBelow,
212 mAppWindow,
213 mChildAppWindowAbove,
214 mDockedDividerWindow,
215 mStatusBarWindow,
216 mNotificationShadeWindow,
217 mImeWindow,
218 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700219 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800220 }
221
222 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700223 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800224 // This window is set-up to be z-ordered between some windows that go in the same token like
225 // the nav bar and status bar.
226 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700227 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800228
Wale Ogunwale34247952017-02-19 11:57:53 -0800229 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700230 mWallpaperWindow,
231 mChildAppWindowBelow,
232 mAppWindow,
233 mChildAppWindowAbove,
234 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800235 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200236 mImeWindow,
237 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700238 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800239 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200240 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800241 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800242
Wale Ogunwale34247952017-02-19 11:57:53 -0800243 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700244 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800245 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700246 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800247 appWin.setHasSurface(true);
248 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700249 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800250 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800251 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800252
Wale Ogunwale34247952017-02-19 11:57:53 -0800253 // Verify that an child window can be an ime target.
254 final WindowState childWin = createWindow(appWin,
255 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
256 childWin.setHasSurface(true);
257 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700258 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800259 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800260 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800261
Andrii Kuliand68501e2017-01-10 22:57:27 -0800262 /**
263 * This tests stack movement between displays and proper stack's, task's and app token's display
264 * container references updates.
265 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800266 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700267 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800268 // Create a second display.
269 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800270
271 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700272 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800273 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800274 assertEquals(dc, stack.getDisplayContent());
275
276 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700277 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
278 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800279 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700280 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800281
282 // Move stack to first display.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700283 mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
284 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700285 assertEquals(mDisplayContent, stack.getDisplayContent());
286 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700287 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800288 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800289
290 /**
291 * This tests override configuration updates for display content.
292 */
293 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700294 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700295 final Configuration currentOverrideConfig =
296 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800297
298 // Create new, slightly changed override configuration and apply it to the display.
299 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
300 newOverrideConfig.densityDpi += 120;
301 newOverrideConfig.fontScale += 0.3;
302
Evan Roskye747c3e2018-10-30 20:06:41 -0700303 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800304
305 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700306 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800307 }
308
309 /**
310 * This tests global configuration updates when default display config is updated.
311 */
312 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700313 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700314 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
315 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800316
317 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700318 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800319 newOverrideConfig.densityDpi += 120;
320 newOverrideConfig.fontScale += 0.3;
321
Evan Roskye747c3e2018-10-30 20:06:41 -0700322 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800323
324 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700325 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800326 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
327 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800328
329 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700330 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700331 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700332 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
333 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800334 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800335
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700336 /**
337 * Tests tapping on a stack in different display results in window gaining focus.
338 */
339 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700340 public void testInputEventBringsCorrectDisplayInFocus() {
341 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700342 // Create a second display
343 final DisplayContent dc1 = createNewDisplay();
344
345 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700346 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700347 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700348 final ActivityRecord activity =
349 WindowTestUtils.createTestActivityRecord(dc0);
350 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800351 dc0.configureDisplayPolicy();
352 assertNotNull(dc0.mTapDetector);
353
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700354 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700355 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700356 final ActivityRecord activity1 =
357 WindowTestUtils.createTestActivityRecord(dc0);
358 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800359 dc1.configureDisplayPolicy();
360 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700361
Arthur Hungbe5ce212018-09-13 18:41:56 +0800362 // tap on primary display.
363 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700364 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700365 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800366 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700367
Arthur Hungbe5ce212018-09-13 18:41:56 +0800368 // Tap on secondary display.
369 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700370 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700371 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800372 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700373 }
374
David Stevens46939562017-03-24 13:04:00 -0700375 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700376 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800377 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
378 }
379
380 @Test
381 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
382 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
383 }
384
385 @Test
386 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
387 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
388 }
389
390 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
391 int targetSdk) {
392 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
393
Andrii Kulian0214ed92017-05-16 13:44:05 -0700394 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700395 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700396 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700397 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800398 updateFocusedWindow();
399 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700400 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700401
402 // Check that a new display doesn't affect focus
403 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800404 updateFocusedWindow();
405 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700406 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700407
408 // Add a window to the second display, and it should be focused
409 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700410 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800411 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800412 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800413 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700414 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700415
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800416 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700417 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800418 updateFocusedWindow();
419 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800420 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700421 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800422
423 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100424 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700425 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800426 updateFocusedWindow();
427 assertTrue(!window1.isFocused());
428 assertEquals(window1.getDisplayId(),
429 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200430 }
431
Riddle Hsub2297ad2019-07-26 23:37:25 -0600432 @Test
433 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
434 mWm.mSystemBooted = true;
435 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
436 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
437 TYPE_WALLPAPER, TYPE_APPLICATION);
438
439 // Verify waiting for windows to be drawn.
440 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
441
442 // Verify not waiting for drawn windows.
443 makeWindowsDrawn(windows);
444 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
445 }
446
447 @Test
448 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
449 mWm.mSystemBooted = true;
450 final DisplayContent secondaryDisplay = createNewDisplay();
451 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
452 TYPE_WALLPAPER, TYPE_APPLICATION);
453
454 // Verify not waiting for display without system decorations.
455 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
456 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
457
458 // Verify waiting for non-drawn windows on display with system decorations.
459 reset(secondaryDisplay);
460 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
461 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
462
463 // Verify not waiting for drawn windows on display with system decorations.
464 makeWindowsDrawn(windows);
465 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
466 }
467
468 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
469 final WindowState[] windows = new WindowState[types.length];
470 for (int i = 0; i < types.length; i++) {
471 final int type = types[i];
472 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
473 windows[i].mHasSurface = false;
474 }
475 return windows;
476 }
477
478 private static void makeWindowsDrawn(WindowState[] windows) {
479 for (WindowState window : windows) {
480 window.mHasSurface = true;
481 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
482 }
483 }
484
Bryce Lee27cec322017-03-21 09:41:37 -0700485 /**
486 * This tests setting the maximum ui width on a display.
487 */
488 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700489 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800490 // Prevent base display metrics for test from being updated to the value of real display.
491 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700492 final int baseWidth = 1440;
493 final int baseHeight = 2560;
494 final int baseDensity = 300;
495
Riddle Hsu654a6f92018-07-13 22:59:36 +0800496 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700497
498 final int maxWidth = 300;
499 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
500 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
501
Riddle Hsu654a6f92018-07-13 22:59:36 +0800502 displayContent.setMaxUiWidth(maxWidth);
503 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700504
505 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800506 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
507 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700508
509 final int smallerWidth = 200;
510 final int smallerHeight = 400;
511 final int smallerDensity = 100;
512
513 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800514 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
515 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700516
517 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800518 displayContent.setMaxUiWidth(maxWidth);
519 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700520 }
521
Andrii Kulian92c9a942017-10-10 00:41:41 -0700522 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700523 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800524 final DisplayContent dc = createNewDisplay();
525 dc.mInitialDisplayWidth = 200;
526 dc.mInitialDisplayHeight = 400;
527 final Rect r = new Rect(80, 0, 120, 10);
528 final DisplayCutout cutout = new WmDisplayCutout(
529 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
530 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100531
Riddle Hsu73f53572019-09-23 23:13:01 +0800532 dc.mInitialDisplayCutout = cutout;
533 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
534 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100535
Riddle Hsu73f53572019-09-23 23:13:01 +0800536 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100537 }
538
539 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700540 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800541 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
542 // if the device has no cutout).
543 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800544 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
545 // landscape display let's rotate it.
546 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
547 int tmp = dc.mInitialDisplayHeight;
548 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
549 dc.mInitialDisplayWidth = tmp;
550 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800551 // Rotation may use real display info to compute bound, so here also uses the
552 // same width and height.
553 final int displayWidth = dc.mInitialDisplayWidth;
554 final int displayHeight = dc.mInitialDisplayHeight;
555 final int cutoutWidth = 40;
556 final int cutoutHeight = 10;
557 final int left = (displayWidth - cutoutWidth) / 2;
558 final int top = 0;
559 final int right = (displayWidth + cutoutWidth) / 2;
560 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800561
Riddle Hsu73f53572019-09-23 23:13:01 +0800562 final Rect r1 = new Rect(left, top, right, bottom);
563 final DisplayCutout cutout = new WmDisplayCutout(
564 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
565 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100566
Riddle Hsu73f53572019-09-23 23:13:01 +0800567 dc.mInitialDisplayCutout = cutout;
568 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
569 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100570
Riddle Hsu73f53572019-09-23 23:13:01 +0800571 // ----o---------- -------------
572 // | | | | |
573 // | ------o | o---
574 // | | | |
575 // | | -> | |
576 // | | ---o
577 // | | |
578 // | | -------------
579 final Rect r = new Rect(top, left, bottom, right);
580 assertEquals(new WmDisplayCutout(
581 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
582 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
583 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100584 }
585
586 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700587 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800588 final DisplayContent dc = createNewDisplay();
589 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100590
Riddle Hsu12c05452020-01-09 00:39:52 +0800591 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100592
Riddle Hsu73f53572019-09-23 23:13:01 +0800593 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100594 }
595
596 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700597 @SuppressLint("InlinedApi")
598 public void testOrientationDefinedByKeyguard() {
599 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800600
601 // When display content is created its configuration is not yet initialized, which could
602 // cause unnecessary configuration propagation, so initialize it here.
603 final Configuration config = new Configuration();
604 dc.computeScreenConfiguration(config);
605 dc.onRequestedOverrideConfigurationChanged(config);
606
Andrii Kulian92c9a942017-10-10 00:41:41 -0700607 // Create a window that requests landscape orientation. It will define device orientation
608 // by default.
609 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700610 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700611
wilsonshihe8321942019-10-18 18:39:46 +0800612 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700613 keyguard.mHasSurface = true;
614 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
615
616 assertEquals("Screen orientation must be defined by the app window by default",
617 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
618
619 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
620 assertEquals("Visible keyguard must influence device orientation",
621 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
622
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700623 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700624 assertEquals("Keyguard that is going away must not influence device orientation",
625 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
626 }
627
Andrii Kulianf0379de2018-03-14 16:24:07 -0700628 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800629 public void testOrientationForAspectRatio() {
630 final DisplayContent dc = createNewDisplay();
631
632 // When display content is created its configuration is not yet initialized, which could
633 // cause unnecessary configuration propagation, so initialize it here.
634 final Configuration config = new Configuration();
635 dc.computeScreenConfiguration(config);
636 dc.onRequestedOverrideConfigurationChanged(config);
637
638 // Create a window that requests a fixed orientation. It will define device orientation
639 // by default.
640 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
641 "window");
642 window.mHasSurface = true;
643 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
644
645 // --------------------------------
646 // Test non-close-to-square display
647 // --------------------------------
648 dc.mBaseDisplayWidth = 1000;
649 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
650 dc.configureDisplayPolicy();
651
652 assertEquals("Screen orientation must be defined by the window by default.",
653 window.mAttrs.screenOrientation, dc.getOrientation());
654
655 // ----------------------------
656 // Test close-to-square display
657 // ----------------------------
658 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
659 dc.configureDisplayPolicy();
660
661 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
662 SCREEN_ORIENTATION_USER, dc.getOrientation());
663 }
664
665 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700666 public void testDisableDisplayInfoOverrideFromWindowManager() {
667 final DisplayContent dc = createNewDisplay();
668
669 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700670 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700671
672 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700673 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700674 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
675 }
676
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800677 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800678 public void testClearLastFocusWhenReparentingFocusedWindow() {
679 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
680 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
681 defaultDisplay, "window");
682 defaultDisplay.mLastFocus = window;
683 mDisplayContent.mCurrentFocus = window;
684 mDisplayContent.reParentWindowToken(window.mToken);
685
686 assertNull(defaultDisplay.mLastFocus);
687 }
688
689 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800690 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
691 final DisplayContent portraitDisplay = createNewDisplay();
692 portraitDisplay.mInitialDisplayHeight = 2000;
693 portraitDisplay.mInitialDisplayWidth = 1000;
694
Riddle Hsuccf09402019-08-13 00:33:06 +0800695 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800696 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700697 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800698 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
699
700 final DisplayContent landscapeDisplay = createNewDisplay();
701 landscapeDisplay.mInitialDisplayHeight = 1000;
702 landscapeDisplay.mInitialDisplayWidth = 2000;
703
Riddle Hsuccf09402019-08-13 00:33:06 +0800704 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800705 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700706 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800707 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
708 }
709
lumarkff0ab692018-11-05 20:32:30 +0800710 @Test
711 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
712 final DisplayContent newDisplay = createNewDisplay();
713
714 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
715 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
716 appWin.setHasSurface(true);
717 appWin1.setHasSurface(true);
718
719 // Set current input method window on default display, make sure the input method target
720 // is appWin & null on the other display.
721 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
722 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200723 assertEquals("appWin should be IME target window",
724 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800725 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
726
727 // Switch input method window on new display & make sure the input method target also
728 // switched as expected.
729 newDisplay.setInputMethodWindowLocked(mImeWindow);
730 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200731 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800732 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
733 }
734
Garfield Tan90b04282018-12-11 14:04:42 -0800735 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800736 public void testAllowsTopmostFullscreenOrientation() {
737 final DisplayContent dc = createNewDisplay();
738 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800739 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800740
741 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800742 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800743 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800744 .build();
745 doReturn(true).when(stack).isVisible();
746
747 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800748 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800749 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800750 .setWindowingMode(WINDOWING_MODE_FREEFORM)
751 .build();
752 doReturn(true).when(freeformStack).isVisible();
753 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
754
755 assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
756
757 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
758 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
759 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
760
761 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
762 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
763 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
764 }
765
766 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800767 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800768 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700769 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800770 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800771 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
772 ? SCREEN_ORIENTATION_PORTRAIT
773 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800774
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700775 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800776 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800777 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900778 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800779
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700780 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800781
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700782 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
783 ? Configuration.ORIENTATION_PORTRAIT
784 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700785 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800786 }
787
788 @Test
789 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800790 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800791 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800792 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800793 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
794 ? SCREEN_ORIENTATION_PORTRAIT
795 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800796
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700797 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800798 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800799 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900800 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800801
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700802 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800803
Louis Chang677921f2019-12-06 16:44:24 +0800804 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
805 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700806 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800807 }
808
Tarandeep Singha6f35612019-01-11 19:50:46 -0800809 @Test
810 public void testComputeImeParent_app() throws Exception {
811 try (final InsetsModeSession session =
812 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
813 final DisplayContent dc = createNewDisplay();
814 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700815 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800816 dc.computeImeParent());
817 }
818 }
819
820 @Test
821 public void testComputeImeParent_app_notFullscreen() throws Exception {
822 try (final InsetsModeSession session =
823 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
824 final DisplayContent dc = createNewDisplay();
825 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
826 dc.mInputMethodTarget.setWindowingMode(
827 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
828 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
829 }
830 }
831
832 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800833 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700834 spyOn(mAppWindow.mActivityRecord);
835 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800836 mDisplayContent.mInputMethodTarget = mAppWindow;
837 // The surface parent of IME should be the display instead of app window.
838 assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
839 }
840
841 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800842 public void testComputeImeParent_noApp() throws Exception {
843 try (final InsetsModeSession session =
844 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
845 final DisplayContent dc = createNewDisplay();
846 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
847 assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
848 }
849 }
850
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500851 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100852 public void testUpdateSystemGestureExclusion() throws Exception {
853 final DisplayContent dc = createNewDisplay();
854 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
855 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
856 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
857
Riddle Hsu12c05452020-01-09 00:39:52 +0800858 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100859
860 win.setHasSurface(true);
861 dc.updateSystemGestureExclusion();
862
Riddle Hsu73f53572019-09-23 23:13:01 +0800863 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100864 final ISystemGestureExclusionListener.Stub verifier =
865 new ISystemGestureExclusionListener.Stub() {
866 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200867 public void onSystemGestureExclusionChanged(int displayId, Region actual,
868 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100869 Region expected = Region.obtain();
870 expected.set(10, 20, 30, 40);
871 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800872 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100873 }
874 };
875 try {
876 dc.registerSystemGestureExclusionListener(verifier);
877 } finally {
878 dc.unregisterSystemGestureExclusionListener(verifier);
879 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800880 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100881 }
882
883 @Test
884 public void testCalculateSystemGestureExclusion() throws Exception {
885 final DisplayContent dc = createNewDisplay();
886 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
887 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
888 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
889
890 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
891 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
892 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
893
Riddle Hsu12c05452020-01-09 00:39:52 +0800894 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100895
896 win.setHasSurface(true);
897 win2.setHasSurface(true);
898
899 final Region expected = Region.obtain();
900 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200901 assertEquals(expected, calculateSystemGestureExclusion(dc));
902 }
903
904 private Region calculateSystemGestureExclusion(DisplayContent dc) {
905 Region out = Region.obtain();
906 Region unrestricted = Region.obtain();
907 dc.calculateSystemGestureExclusion(out, unrestricted);
908 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100909 }
910
911 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200912 public void testCalculateSystemGestureExclusion_modal() throws Exception {
913 final DisplayContent dc = createNewDisplay();
914 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
915 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
916 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
917
918 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
919 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
920 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
921 win2.getAttrs().width = 10;
922 win2.getAttrs().height = 10;
923 win2.setSystemGestureExclusion(Collections.emptyList());
924
Riddle Hsu12c05452020-01-09 00:39:52 +0800925 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200926
927 win.setHasSurface(true);
928 win2.setHasSurface(true);
929
930 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200931 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200932 }
933
934 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200935 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200936 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200937
Riddle Hsu73f53572019-09-23 23:13:01 +0800938 final DisplayContent dc = createNewDisplay();
939 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
940 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
941 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
942 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
943 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
944 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
945 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700946 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200947
Riddle Hsu12c05452020-01-09 00:39:52 +0800948 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +0200949
Riddle Hsu73f53572019-09-23 23:13:01 +0800950 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200951
Riddle Hsu73f53572019-09-23 23:13:01 +0800952 final Region expected = Region.obtain();
953 expected.set(dc.getBounds());
954 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200955
Riddle Hsu73f53572019-09-23 23:13:01 +0800956 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200957 }
958
959 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +0800960 public void testRequestResizeForEmptyFrames() {
961 final WindowState win = mChildAppWindowAbove;
962 makeWindowVisible(win, win.getParentWindow());
963 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
964 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
965 win.mAttrs.gravity = Gravity.CENTER;
966 performLayout(mDisplayContent);
967
968 // The frame is empty because the requested height is zero.
969 assertTrue(win.getFrameLw().isEmpty());
970 // The window should be scheduled to resize then the client may report a new non-empty size.
971 win.updateResizingWindowIfNeeded();
972 assertThat(mWm.mResizingWindows).contains(win);
973 }
974
975 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500976 public void testOrientationChangeLogging() {
977 MetricsLogger mockLogger = mock(MetricsLogger.class);
978 Configuration oldConfig = new Configuration();
979 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
980
981 Configuration newConfig = new Configuration();
982 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800983 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500984 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
985 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +0800986 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500987
988 displayContent.onConfigurationChanged(newConfig);
989
990 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
991 verify(mockLogger).write(logMakerCaptor.capture());
992 assertThat(logMakerCaptor.getValue().getCategory(),
993 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
994 assertThat(logMakerCaptor.getValue().getSubtype(),
995 is(Configuration.ORIENTATION_PORTRAIT));
996 }
997
Evan Rosky69cace42019-09-20 16:28:13 -0700998 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +0800999 public void testApplyTopFixedRotationTransform() {
1000 mWm.mIsFixedRotationTransformEnabled = true;
1001 final Configuration config90 = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001002 mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001003
1004 final Configuration config = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001005 mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001006 mDisplayContent.computeScreenConfiguration(config);
1007 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1008
1009 final ActivityRecord app = mAppWindow.mActivityRecord;
1010 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1011 false /* alwaysKeepCurrent */);
1012 mDisplayContent.mOpeningApps.add(app);
1013 app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1014
1015 assertTrue(app.isFixedRotationTransforming());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001016 assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
1017 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
1018 false /* forceUpdate */));
Riddle Hsuf41034c2020-03-19 13:10:46 +08001019
1020 final Rect outFrame = new Rect();
1021 final Rect outInsets = new Rect();
1022 final Rect outStableInsets = new Rect();
1023 final Rect outSurfaceInsets = new Rect();
1024 mAppWindow.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
1025 // The animation frames should not be rotated because display hasn't rotated.
1026 assertEquals(mDisplayContent.getBounds(), outFrame);
1027
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001028 // The display should keep current orientation and the rotated configuration should apply
1029 // to the activity.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001030 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1031 assertEquals(config90.orientation, app.getConfiguration().orientation);
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001032 assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001033
1034 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1035
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001036 // The display should be rotated after the launch is finished.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001037 assertFalse(app.hasFixedRotationTransform());
1038 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
1039 }
1040
1041 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001042 public void testRemoteRotation() {
1043 DisplayContent dc = createNewDisplay();
1044
1045 final DisplayRotation dr = dc.getDisplayRotation();
1046 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
1047 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1048 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001049 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -07001050 Mockito.doAnswer(
1051 invocation -> {
1052 continued[0] = true;
1053 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001054 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001055 final boolean[] called = new boolean[1];
1056 mWm.mDisplayRotationController =
1057 new IDisplayWindowRotationController.Stub() {
1058 @Override
1059 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1060 IDisplayWindowRotationCallback callback) {
1061 called[0] = true;
1062
1063 try {
1064 callback.continueRotateDisplay(toRotation, null);
1065 } catch (RemoteException e) {
1066 assertTrue(false);
1067 }
1068 }
1069 };
1070
1071 // kill any existing rotation animation (vestigial from test setup).
1072 dc.setRotationAnimation(null);
1073
1074 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1075 assertTrue(called[0]);
1076 waitUntilHandlersIdle();
1077 assertTrue(continued[0]);
1078 }
1079
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001080 @Test
1081 public void testGetOrCreateRootHomeTask_defaultDisplay() {
1082 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
1083
1084 // Remove the current home stack if it exists so a new one can be created below.
1085 ActivityStack homeTask = defaultDisplay.getRootHomeTask();
1086 if (homeTask != null) {
1087 defaultDisplay.removeStack(homeTask);
1088 }
1089 assertNull(defaultDisplay.getRootHomeTask());
1090
1091 assertNotNull(defaultDisplay.getOrCreateRootHomeTask());
1092 }
1093
1094 @Test
1095 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1096 DisplayContent display = createNewDisplay();
1097 doReturn(true).when(display).supportsSystemDecorations();
1098 doReturn(false).when(display).isUntrustedVirtualDisplay();
1099
1100 // Remove the current home stack if it exists so a new one can be created below.
1101 ActivityStack homeTask = display.getRootHomeTask();
1102 if (homeTask != null) {
1103 display.removeStack(homeTask);
1104 }
1105 assertNull(display.getRootHomeTask());
1106
1107 assertNotNull(display.getOrCreateRootHomeTask());
1108 }
1109
1110 @Test
1111 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1112 DisplayContent display = createNewDisplay();
1113 doReturn(false).when(display).supportsSystemDecorations();
1114
1115 assertNull(display.getRootHomeTask());
1116 assertNull(display.getOrCreateRootHomeTask());
1117 }
1118
1119 @Test
1120 public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
1121 DisplayContent display = createNewDisplay();
1122 doReturn(true).when(display).isUntrustedVirtualDisplay();
1123
1124 assertNull(display.getRootHomeTask());
1125 assertNull(display.getOrCreateRootHomeTask());
1126 }
1127
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001128 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001129 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001130 }
1131
Bryce Lee27cec322017-03-21 09:41:37 -07001132 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1133 int expectedBaseHeight, int expectedBaseDensity) {
1134 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1135 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1136 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1137 }
1138
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001139 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001140 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001141 }
1142
Riddle Hsu12c05452020-01-09 00:39:52 +08001143 private void performLayout(DisplayContent dc) {
1144 dc.setLayoutNeeded();
1145 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1146 }
1147
Riddle Hsu654a6f92018-07-13 22:59:36 +08001148 /**
1149 * Create DisplayContent that does not update display base/initial values from device to keep
1150 * the values set by test.
1151 */
1152 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001153 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001154 doNothing().when(displayContent).updateDisplayInfo();
1155 return displayContent;
1156 }
1157
Adrian Roos0f9368c2018-04-08 10:59:08 -07001158 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1159 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001160
1161 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001162 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001163 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1164
1165 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001166
1167 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001168 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001169 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1170 }
1171
1172 private static List<WindowState> reverseList(List<WindowState> list) {
1173 final ArrayList<WindowState> result = new ArrayList<>(list);
1174 Collections.reverse(result);
1175 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001176 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001177
Arthur Hungbe5ce212018-09-13 18:41:56 +08001178 private void tapOnDisplay(final DisplayContent dc) {
1179 final DisplayMetrics dm = dc.getDisplayMetrics();
1180 final float x = dm.widthPixels / 2;
1181 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001182 final long downTime = SystemClock.uptimeMillis();
1183 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001184 // sending ACTION_DOWN
1185 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001186 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001187 downTime,
1188 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001189 x,
1190 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001191 0 /*metaState*/);
1192 downEvent.setDisplayId(dc.getDisplayId());
1193 dc.mTapDetector.onPointerEvent(downEvent);
1194
1195 // sending ACTION_UP
1196 final MotionEvent upEvent = MotionEvent.obtain(
1197 downTime,
1198 eventTime,
1199 MotionEvent.ACTION_UP,
1200 x,
1201 y,
1202 0 /*metaState*/);
1203 upEvent.setDisplayId(dc.getDisplayId());
1204 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001205 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001206}