blob: ac95a817bec91b885d629d5664b09ee9384a5f08 [file] [log] [blame]
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070015 */
16
17package com.android.server.wm;
18
Garfield Tan98eead32019-11-18 13:24:53 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Andrii Kulian92c9a942017-10-10 00:41:41 -070020import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
22import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Tiger Huang86e6d072019-05-02 20:23:47 +080023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080024import static android.os.Build.VERSION_CODES.P;
25import static android.os.Build.VERSION_CODES.Q;
Wale Ogunwale34247952017-02-19 11:57:53 -080026import static android.view.Display.DEFAULT_DISPLAY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020027import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
28import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Adrian Roos24264212018-02-19 16:26:15 +010029import static android.view.DisplayCutout.fromBoundingRect;
Riddle Hsu9239d7c62020-02-20 01:35:56 +080030import static android.view.Surface.ROTATION_0;
Evan Rosky69cace42019-09-20 16:28:13 -070031import static android.view.Surface.ROTATION_90;
Adrian Roos019a52b2019-07-02 16:47:44 +020032import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
33import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
34import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Adrian Roos4ffc8972019-02-07 20:45:11 +010035import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
36import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Adrian Roos019a52b2019-07-02 16:47:44 +020037import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
38import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080039import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
40import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Tiger Huang86e6d072019-05-02 20:23:47 +080041import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Wale Ogunwale34247952017-02-19 11:57:53 -080042import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
wilsonshihe8321942019-10-18 18:39:46 +080043import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
Mark Renoufa9279292020-04-17 12:22:50 -040044import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
Andrii Kulian92c9a942017-10-10 00:41:41 -070045import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwale34247952017-02-19 11:57:53 -080046import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
Riddle Hsub2297ad2019-07-26 23:37:25 -060047import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070048
Garfield Tan90b04282018-12-11 14:04:42 -080049import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
50import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090051import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080052import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Garfield Tan90b04282018-12-11 14:04:42 -080053import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
54import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Riddle Hsub2297ad2019-07-26 23:37:25 -060055import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Garfield Tan90b04282018-12-11 14:04:42 -080056import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
Riddle Hsu6d6f67c2019-03-14 16:54:26 +080057import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090058import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
59import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
David Stevens46939562017-03-24 13:04:00 -070060import static com.android.server.wm.WindowContainer.POSITION_TOP;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080061import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
chaviwebcbc342018-02-07 13:19:00 -080062
Riddle Hsu12c05452020-01-09 00:39:52 +080063import static com.google.common.truth.Truth.assertThat;
64
Adrian Roos5251b1d2018-03-23 18:57:43 +010065import static org.hamcrest.Matchers.is;
Wale Ogunwale34247952017-02-19 11:57:53 -080066import static org.junit.Assert.assertEquals;
Andrii Kulianf0379de2018-03-14 16:24:07 -070067import static org.junit.Assert.assertFalse;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020068import static org.junit.Assert.assertNotEquals;
Arthur Hungbe5ce212018-09-13 18:41:56 +080069import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080070import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010071import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080072import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070073import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080074import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080075
Andrii Kulian92c9a942017-10-10 00:41:41 -070076import android.annotation.SuppressLint;
Mark Renoufa9279292020-04-17 12:22:50 -040077import android.app.ActivityTaskManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080078import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080079import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010080import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010081import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050082import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070083import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070084import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070085import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070086import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010087import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080088import android.view.Gravity;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020089import android.view.IDisplayWindowInsetsController;
Evan Rosky69cace42019-09-20 16:28:13 -070090import android.view.IDisplayWindowRotationCallback;
91import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010092import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080093import android.view.IWindowManager;
Jorim Jaggicc57cb72020-04-09 14:54:13 +020094import android.view.InsetsSourceControl;
95import android.view.InsetsState;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070096import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010097import android.view.Surface;
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +080098import android.view.SurfaceControl.Transaction;
Riddle Hsu12c05452020-01-09 00:39:52 +080099import android.view.WindowManager;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700100
Brett Chabota26eda92018-07-23 13:08:30 -0700101import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -0700102
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500103import com.android.internal.logging.MetricsLogger;
104import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100105import com.android.server.wm.utils.WmDisplayCutout;
106
Brett Chabota26eda92018-07-23 13:08:30 -0700107import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800108import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800109import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500110import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700111
Adrian Roos0f9368c2018-04-08 10:59:08 -0700112import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800113import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700114import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800115import java.util.LinkedList;
116import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700117
118/**
119 * Tests for the {@link DisplayContent} class.
120 *
121 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900122 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700123 */
124@SmallTest
125@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800126@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800127public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700128
129 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700130 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800131 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700132 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700133 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900134 // Wait until everything in animation handler get executed to prevent the exiting window
135 // from being removed during WindowSurfacePlacer Traversal.
136 waitUntilHandlersIdle();
137
Garfield Tane8d84ab2019-10-11 09:49:40 -0700138 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800139 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700140
Wale Ogunwale34247952017-02-19 11:57:53 -0800141 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700142 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800143 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700144 mChildAppWindowBelow,
145 mAppWindow,
146 mChildAppWindowAbove,
147 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200148 mImeWindow,
149 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700150 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800151 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200152 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800153 }
154
155 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700156 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800157 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700158 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800159
lumarkff0ab692018-11-05 20:32:30 +0800160 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800161
Wale Ogunwale34247952017-02-19 11:57:53 -0800162 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700163 mWallpaperWindow,
164 mChildAppWindowBelow,
165 mAppWindow,
166 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800167 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700168 mImeWindow,
169 mImeDialogWindow,
170 mDockedDividerWindow,
171 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800172 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700173 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800174 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800175
Wale Ogunwale34247952017-02-19 11:57:53 -0800176 @Test
lumarkff0ab692018-11-05 20:32:30 +0800177 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
178 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800179
Wale Ogunwale34247952017-02-19 11:57:53 -0800180 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700181 mWallpaperWindow,
182 mChildAppWindowBelow,
183 mAppWindow,
184 mChildAppWindowAbove,
185 mImeWindow,
186 mImeDialogWindow,
187 mDockedDividerWindow,
188 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800189 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700190 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700191 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800192
193 @Test
lumarkff0ab692018-11-05 20:32:30 +0800194 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
195 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800196
Wale Ogunwale34247952017-02-19 11:57:53 -0800197 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700198 mWallpaperWindow,
199 mChildAppWindowBelow,
200 mAppWindow,
201 mChildAppWindowAbove,
202 mDockedDividerWindow,
203 mStatusBarWindow,
204 mImeWindow,
205 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800206 mNotificationShadeWindow,
207 mNavBarWindow));
208 }
209
210 @Test
211 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
212 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
213
214 assertForAllWindowsOrder(Arrays.asList(
215 mWallpaperWindow,
216 mChildAppWindowBelow,
217 mAppWindow,
218 mChildAppWindowAbove,
219 mDockedDividerWindow,
220 mStatusBarWindow,
221 mNotificationShadeWindow,
222 mImeWindow,
223 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700224 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800225 }
226
227 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700228 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800229 // This window is set-up to be z-ordered between some windows that go in the same token like
230 // the nav bar and status bar.
231 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700232 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800233
Wale Ogunwale34247952017-02-19 11:57:53 -0800234 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700235 mWallpaperWindow,
236 mChildAppWindowBelow,
237 mAppWindow,
238 mChildAppWindowAbove,
239 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800240 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200241 mImeWindow,
242 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700243 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800244 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200245 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800246 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800247
Wale Ogunwale34247952017-02-19 11:57:53 -0800248 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700249 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800250 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700251 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800252 appWin.setHasSurface(true);
253 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700254 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800255 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800256 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800257
Wale Ogunwale34247952017-02-19 11:57:53 -0800258 // Verify that an child window can be an ime target.
259 final WindowState childWin = createWindow(appWin,
260 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
261 childWin.setHasSurface(true);
262 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700263 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800264 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800265 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800266
Andrii Kuliand68501e2017-01-10 22:57:27 -0800267 /**
268 * This tests stack movement between displays and proper stack's, task's and app token's display
269 * container references updates.
270 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800271 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700272 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800273 // Create a second display.
274 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800275
276 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700277 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800278 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800279 assertEquals(dc, stack.getDisplayContent());
280
281 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700282 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
283 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800284 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700285 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800286
287 // Move stack to first display.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700288 stack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true /* onTop */);
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700289 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700290 assertEquals(mDisplayContent, stack.getDisplayContent());
291 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700292 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800293 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800294
295 /**
296 * This tests override configuration updates for display content.
297 */
298 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700299 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700300 final Configuration currentOverrideConfig =
301 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800302
303 // Create new, slightly changed override configuration and apply it to the display.
304 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
305 newOverrideConfig.densityDpi += 120;
306 newOverrideConfig.fontScale += 0.3;
307
Evan Roskye747c3e2018-10-30 20:06:41 -0700308 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800309
310 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700311 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800312 }
313
314 /**
315 * This tests global configuration updates when default display config is updated.
316 */
317 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700318 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700319 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
320 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800321
322 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700323 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800324 newOverrideConfig.densityDpi += 120;
325 newOverrideConfig.fontScale += 0.3;
326
Evan Roskye747c3e2018-10-30 20:06:41 -0700327 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800328
329 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700330 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800331 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
332 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800333
334 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700335 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700336 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700337 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
338 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800339 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800340
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700341 /**
342 * Tests tapping on a stack in different display results in window gaining focus.
343 */
344 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700345 public void testInputEventBringsCorrectDisplayInFocus() {
346 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700347 // Create a second display
348 final DisplayContent dc1 = createNewDisplay();
349
350 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700351 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700352 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700353 final ActivityRecord activity =
354 WindowTestUtils.createTestActivityRecord(dc0);
355 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800356 dc0.configureDisplayPolicy();
357 assertNotNull(dc0.mTapDetector);
358
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700359 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700360 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700361 final ActivityRecord activity1 =
362 WindowTestUtils.createTestActivityRecord(dc0);
363 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800364 dc1.configureDisplayPolicy();
365 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700366
Arthur Hungbe5ce212018-09-13 18:41:56 +0800367 // tap on primary display.
368 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700369 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700370 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800371 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700372
Arthur Hungbe5ce212018-09-13 18:41:56 +0800373 // Tap on secondary display.
374 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700375 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700376 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800377 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700378 }
379
David Stevens46939562017-03-24 13:04:00 -0700380 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700381 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800382 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
383 }
384
385 @Test
386 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
387 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
388 }
389
390 @Test
391 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
392 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
393 }
394
395 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
396 int targetSdk) {
397 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
398
Andrii Kulian0214ed92017-05-16 13:44:05 -0700399 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700400 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700401 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700402 window1.mActivityRecord.mTargetSdk = targetSdk;
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 // Check that a new display doesn't affect focus
408 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800409 updateFocusedWindow();
410 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700411 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700412
413 // Add a window to the second display, and it should be focused
414 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700415 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800416 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800417 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800418 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700419 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700420
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800421 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700422 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800423 updateFocusedWindow();
424 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800425 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700426 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800427
428 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100429 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700430 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800431 updateFocusedWindow();
432 assertTrue(!window1.isFocused());
433 assertEquals(window1.getDisplayId(),
434 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200435 }
436
Riddle Hsub2297ad2019-07-26 23:37:25 -0600437 @Test
438 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
439 mWm.mSystemBooted = true;
440 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
441 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
442 TYPE_WALLPAPER, TYPE_APPLICATION);
443
444 // Verify waiting for windows to be drawn.
445 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
446
447 // Verify not waiting for drawn windows.
Lais Andrade57283fb2020-04-21 18:58:15 +0000448 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
Riddle Hsub2297ad2019-07-26 23:37:25 -0600449 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
450 }
451
452 @Test
453 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
454 mWm.mSystemBooted = true;
455 final DisplayContent secondaryDisplay = createNewDisplay();
456 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
457 TYPE_WALLPAPER, TYPE_APPLICATION);
458
459 // Verify not waiting for display without system decorations.
460 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
461 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
462
463 // Verify waiting for non-drawn windows on display with system decorations.
464 reset(secondaryDisplay);
465 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
466 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
467
468 // Verify not waiting for drawn windows on display with system decorations.
Lais Andrade57283fb2020-04-21 18:58:15 +0000469 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
Riddle Hsub2297ad2019-07-26 23:37:25 -0600470 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
471 }
472
Lais Andrade57283fb2020-04-21 18:58:15 +0000473 @Test
474 public void testShouldWaitForSystemDecorWindowsOnBoot_OnWindowReadyToShowAndDrawn() {
475 mWm.mSystemBooted = true;
476 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
477 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
478 TYPE_WALLPAPER, TYPE_APPLICATION);
479
480 // Verify waiting for windows to be drawn.
481 makeWindowsDrawnState(windows, WindowStateAnimator.READY_TO_SHOW);
482 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
483
484 // Verify not waiting for drawn windows.
485 makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
486 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
487 }
488
Riddle Hsub2297ad2019-07-26 23:37:25 -0600489 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
490 final WindowState[] windows = new WindowState[types.length];
491 for (int i = 0; i < types.length; i++) {
492 final int type = types[i];
493 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
494 windows[i].mHasSurface = false;
495 }
496 return windows;
497 }
498
Lais Andrade57283fb2020-04-21 18:58:15 +0000499 private static void makeWindowsDrawnState(WindowState[] windows, int state) {
Riddle Hsub2297ad2019-07-26 23:37:25 -0600500 for (WindowState window : windows) {
501 window.mHasSurface = true;
Lais Andrade57283fb2020-04-21 18:58:15 +0000502 window.mWinAnimator.mDrawState = state;
Riddle Hsub2297ad2019-07-26 23:37:25 -0600503 }
504 }
505
Bryce Lee27cec322017-03-21 09:41:37 -0700506 /**
507 * This tests setting the maximum ui width on a display.
508 */
509 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700510 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800511 // Prevent base display metrics for test from being updated to the value of real display.
512 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700513 final int baseWidth = 1440;
514 final int baseHeight = 2560;
515 final int baseDensity = 300;
516
Riddle Hsu654a6f92018-07-13 22:59:36 +0800517 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700518
519 final int maxWidth = 300;
520 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
521 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
522
Riddle Hsu654a6f92018-07-13 22:59:36 +0800523 displayContent.setMaxUiWidth(maxWidth);
524 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700525
526 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800527 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
528 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700529
530 final int smallerWidth = 200;
531 final int smallerHeight = 400;
532 final int smallerDensity = 100;
533
534 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800535 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
536 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700537
538 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800539 displayContent.setMaxUiWidth(maxWidth);
540 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700541 }
542
Andrii Kulian92c9a942017-10-10 00:41:41 -0700543 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700544 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800545 final DisplayContent dc = createNewDisplay();
546 dc.mInitialDisplayWidth = 200;
547 dc.mInitialDisplayHeight = 400;
548 final Rect r = new Rect(80, 0, 120, 10);
549 final DisplayCutout cutout = new WmDisplayCutout(
550 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
551 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100552
Riddle Hsu73f53572019-09-23 23:13:01 +0800553 dc.mInitialDisplayCutout = cutout;
554 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
555 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100556
Riddle Hsu73f53572019-09-23 23:13:01 +0800557 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100558 }
559
560 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700561 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800562 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
563 // if the device has no cutout).
564 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800565 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
566 // landscape display let's rotate it.
567 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
568 int tmp = dc.mInitialDisplayHeight;
569 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
570 dc.mInitialDisplayWidth = tmp;
571 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800572 // Rotation may use real display info to compute bound, so here also uses the
573 // same width and height.
574 final int displayWidth = dc.mInitialDisplayWidth;
575 final int displayHeight = dc.mInitialDisplayHeight;
576 final int cutoutWidth = 40;
577 final int cutoutHeight = 10;
578 final int left = (displayWidth - cutoutWidth) / 2;
579 final int top = 0;
580 final int right = (displayWidth + cutoutWidth) / 2;
581 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800582
Riddle Hsu73f53572019-09-23 23:13:01 +0800583 final Rect r1 = new Rect(left, top, right, bottom);
584 final DisplayCutout cutout = new WmDisplayCutout(
585 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
586 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100587
Riddle Hsu73f53572019-09-23 23:13:01 +0800588 dc.mInitialDisplayCutout = cutout;
589 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
590 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100591
Riddle Hsu73f53572019-09-23 23:13:01 +0800592 // ----o---------- -------------
593 // | | | | |
594 // | ------o | o---
595 // | | | |
596 // | | -> | |
597 // | | ---o
598 // | | |
599 // | | -------------
600 final Rect r = new Rect(top, left, bottom, right);
601 assertEquals(new WmDisplayCutout(
602 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
603 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
604 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100605 }
606
607 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700608 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800609 final DisplayContent dc = createNewDisplay();
610 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100611
Riddle Hsu12c05452020-01-09 00:39:52 +0800612 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100613
Riddle Hsu73f53572019-09-23 23:13:01 +0800614 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100615 }
616
617 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700618 @SuppressLint("InlinedApi")
619 public void testOrientationDefinedByKeyguard() {
620 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800621
622 // When display content is created its configuration is not yet initialized, which could
623 // cause unnecessary configuration propagation, so initialize it here.
624 final Configuration config = new Configuration();
625 dc.computeScreenConfiguration(config);
626 dc.onRequestedOverrideConfigurationChanged(config);
627
Andrii Kulian92c9a942017-10-10 00:41:41 -0700628 // Create a window that requests landscape orientation. It will define device orientation
629 // by default.
630 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700631 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700632
wilsonshihe8321942019-10-18 18:39:46 +0800633 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700634 keyguard.mHasSurface = true;
635 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
636
637 assertEquals("Screen orientation must be defined by the app window by default",
638 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
639
640 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
641 assertEquals("Visible keyguard must influence device orientation",
642 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
643
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700644 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700645 assertEquals("Keyguard that is going away must not influence device orientation",
646 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
647 }
648
Andrii Kulianf0379de2018-03-14 16:24:07 -0700649 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800650 public void testOrientationForAspectRatio() {
651 final DisplayContent dc = createNewDisplay();
652
653 // When display content is created its configuration is not yet initialized, which could
654 // cause unnecessary configuration propagation, so initialize it here.
655 final Configuration config = new Configuration();
656 dc.computeScreenConfiguration(config);
657 dc.onRequestedOverrideConfigurationChanged(config);
658
659 // Create a window that requests a fixed orientation. It will define device orientation
660 // by default.
661 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
662 "window");
663 window.mHasSurface = true;
664 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
665
666 // --------------------------------
667 // Test non-close-to-square display
668 // --------------------------------
669 dc.mBaseDisplayWidth = 1000;
670 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
671 dc.configureDisplayPolicy();
672
673 assertEquals("Screen orientation must be defined by the window by default.",
674 window.mAttrs.screenOrientation, dc.getOrientation());
675
676 // ----------------------------
677 // Test close-to-square display
678 // ----------------------------
679 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
680 dc.configureDisplayPolicy();
681
682 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
683 SCREEN_ORIENTATION_USER, dc.getOrientation());
684 }
685
686 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700687 public void testDisableDisplayInfoOverrideFromWindowManager() {
688 final DisplayContent dc = createNewDisplay();
689
690 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700691 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700692
693 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700694 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700695 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
696 }
697
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800698 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800699 public void testClearLastFocusWhenReparentingFocusedWindow() {
700 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
701 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
702 defaultDisplay, "window");
703 defaultDisplay.mLastFocus = window;
704 mDisplayContent.mCurrentFocus = window;
705 mDisplayContent.reParentWindowToken(window.mToken);
706
707 assertNull(defaultDisplay.mLastFocus);
708 }
709
710 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800711 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
712 final DisplayContent portraitDisplay = createNewDisplay();
713 portraitDisplay.mInitialDisplayHeight = 2000;
714 portraitDisplay.mInitialDisplayWidth = 1000;
715
Riddle Hsuccf09402019-08-13 00:33:06 +0800716 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800717 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700718 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800719 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
720
721 final DisplayContent landscapeDisplay = createNewDisplay();
722 landscapeDisplay.mInitialDisplayHeight = 1000;
723 landscapeDisplay.mInitialDisplayWidth = 2000;
724
Riddle Hsuccf09402019-08-13 00:33:06 +0800725 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800726 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700727 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800728 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
729 }
730
lumarkff0ab692018-11-05 20:32:30 +0800731 @Test
732 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
733 final DisplayContent newDisplay = createNewDisplay();
734
735 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
736 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
737 appWin.setHasSurface(true);
738 appWin1.setHasSurface(true);
739
740 // Set current input method window on default display, make sure the input method target
741 // is appWin & null on the other display.
742 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
743 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200744 assertEquals("appWin should be IME target window",
745 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800746 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
747
748 // Switch input method window on new display & make sure the input method target also
749 // switched as expected.
750 newDisplay.setInputMethodWindowLocked(mImeWindow);
751 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200752 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800753 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
754 }
755
Garfield Tan90b04282018-12-11 14:04:42 -0800756 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800757 public void testAllowsTopmostFullscreenOrientation() {
758 final DisplayContent dc = createNewDisplay();
759 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800760 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800761
762 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800763 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800764 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800765 .build();
766 doReturn(true).when(stack).isVisible();
767
768 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800769 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800770 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800771 .setWindowingMode(WINDOWING_MODE_FREEFORM)
772 .build();
773 doReturn(true).when(freeformStack).isVisible();
774 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
775
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700776 assertTrue(dc.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM));
Garfield Tan98eead32019-11-18 13:24:53 -0800777
778 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
779 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
780 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
781
782 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
783 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
784 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
785 }
786
787 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800788 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800789 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700790 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800791 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Riddle Hsud4957432020-04-24 22:06:29 +0800792 final int newOrientation = getRotatedOrientation(dc);
Garfield Tan90b04282018-12-11 14:04:42 -0800793
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700794 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800795 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800796 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900797 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800798
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700799 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800800
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700801 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
802 ? Configuration.ORIENTATION_PORTRAIT
803 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700804 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800805 }
806
807 @Test
808 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800809 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800810 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800811 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Riddle Hsud4957432020-04-24 22:06:29 +0800812 final int newOrientation = getRotatedOrientation(dc);
Garfield Tan90b04282018-12-11 14:04:42 -0800813
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700814 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800815 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800816 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900817 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800818
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700819 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800820
Louis Chang677921f2019-12-06 16:44:24 +0800821 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
822 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700823 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800824 }
825
Tarandeep Singha6f35612019-01-11 19:50:46 -0800826 @Test
827 public void testComputeImeParent_app() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200828 final DisplayContent dc = createNewDisplay();
829 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
830 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
831 dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800832 }
833
834 @Test
835 public void testComputeImeParent_app_notFullscreen() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200836 final DisplayContent dc = createNewDisplay();
837 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
838 dc.mInputMethodTarget.setWindowingMode(
839 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
840 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800841 }
842
843 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800844 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700845 spyOn(mAppWindow.mActivityRecord);
846 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800847 mDisplayContent.mInputMethodTarget = mAppWindow;
848 // The surface parent of IME should be the display instead of app window.
Adrian Roos329cbd02020-04-14 15:42:41 +0200849 assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
850 mDisplayContent.computeImeParent());
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800851 }
852
853 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800854 public void testComputeImeParent_noApp() throws Exception {
Jorim Jaggicc57cb72020-04-09 14:54:13 +0200855 final DisplayContent dc = createNewDisplay();
856 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
857 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
858 }
859
860 @Test
861 public void testComputeImeControlTarget() throws Exception {
862 final DisplayContent dc = createNewDisplay();
863 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
864 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
865 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
866 assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
867 }
868
869 @Test
870 public void testComputeImeControlTarget_splitscreen() throws Exception {
871 final DisplayContent dc = createNewDisplay();
872 dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
873 dc.mInputMethodInputTarget.setWindowingMode(
874 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
875 dc.mInputMethodTarget = dc.mInputMethodInputTarget;
876 dc.setRemoteInsetsController(createDisplayWindowInsetsController());
877 assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
878 }
879
880 @Test
881 public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
882 spyOn(mAppWindow.mActivityRecord);
883 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
884 mDisplayContent.mInputMethodInputTarget = mAppWindow;
885 mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
886 mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
887 assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
888 }
889
890 private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
891 return new IDisplayWindowInsetsController.Stub() {
892
893 @Override
894 public void insetsChanged(InsetsState insetsState) throws RemoteException {
895 }
896
897 @Override
898 public void insetsControlChanged(InsetsState insetsState,
899 InsetsSourceControl[] insetsSourceControls) throws RemoteException {
900 }
901
902 @Override
903 public void showInsets(int i, boolean b) throws RemoteException {
904 }
905
906 @Override
907 public void hideInsets(int i, boolean b) throws RemoteException {
908 }
909 };
Tarandeep Singha6f35612019-01-11 19:50:46 -0800910 }
911
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500912 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100913 public void testUpdateSystemGestureExclusion() throws Exception {
914 final DisplayContent dc = createNewDisplay();
915 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
916 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
917 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
918
Riddle Hsu12c05452020-01-09 00:39:52 +0800919 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100920
921 win.setHasSurface(true);
922 dc.updateSystemGestureExclusion();
923
Riddle Hsu73f53572019-09-23 23:13:01 +0800924 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100925 final ISystemGestureExclusionListener.Stub verifier =
926 new ISystemGestureExclusionListener.Stub() {
927 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200928 public void onSystemGestureExclusionChanged(int displayId, Region actual,
929 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100930 Region expected = Region.obtain();
931 expected.set(10, 20, 30, 40);
932 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800933 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100934 }
935 };
936 try {
937 dc.registerSystemGestureExclusionListener(verifier);
938 } finally {
939 dc.unregisterSystemGestureExclusionListener(verifier);
940 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800941 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100942 }
943
944 @Test
945 public void testCalculateSystemGestureExclusion() throws Exception {
946 final DisplayContent dc = createNewDisplay();
947 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
948 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
949 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
950
951 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
952 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
953 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
954
Riddle Hsu12c05452020-01-09 00:39:52 +0800955 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100956
957 win.setHasSurface(true);
958 win2.setHasSurface(true);
959
960 final Region expected = Region.obtain();
961 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200962 assertEquals(expected, calculateSystemGestureExclusion(dc));
963 }
964
965 private Region calculateSystemGestureExclusion(DisplayContent dc) {
966 Region out = Region.obtain();
967 Region unrestricted = Region.obtain();
968 dc.calculateSystemGestureExclusion(out, unrestricted);
969 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100970 }
971
972 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200973 public void testCalculateSystemGestureExclusion_modal() throws Exception {
974 final DisplayContent dc = createNewDisplay();
975 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
976 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
977 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
978
979 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
980 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
981 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
982 win2.getAttrs().width = 10;
983 win2.getAttrs().height = 10;
984 win2.setSystemGestureExclusion(Collections.emptyList());
985
Riddle Hsu12c05452020-01-09 00:39:52 +0800986 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200987
988 win.setHasSurface(true);
989 win2.setHasSurface(true);
990
991 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200992 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200993 }
994
995 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200996 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200997 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200998
Riddle Hsu73f53572019-09-23 23:13:01 +0800999 final DisplayContent dc = createNewDisplay();
1000 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
1001 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
1002 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
1003 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
1004 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
1005 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
1006 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001007 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +02001008
Riddle Hsu12c05452020-01-09 00:39:52 +08001009 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +02001010
Riddle Hsu73f53572019-09-23 23:13:01 +08001011 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +02001012
Riddle Hsu73f53572019-09-23 23:13:01 +08001013 final Region expected = Region.obtain();
1014 expected.set(dc.getBounds());
1015 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +02001016
Riddle Hsu73f53572019-09-23 23:13:01 +08001017 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +02001018 }
1019
1020 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +08001021 public void testRequestResizeForEmptyFrames() {
1022 final WindowState win = mChildAppWindowAbove;
1023 makeWindowVisible(win, win.getParentWindow());
1024 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
1025 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
1026 win.mAttrs.gravity = Gravity.CENTER;
1027 performLayout(mDisplayContent);
1028
1029 // The frame is empty because the requested height is zero.
1030 assertTrue(win.getFrameLw().isEmpty());
1031 // The window should be scheduled to resize then the client may report a new non-empty size.
1032 win.updateResizingWindowIfNeeded();
1033 assertThat(mWm.mResizingWindows).contains(win);
1034 }
1035
1036 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001037 public void testOrientationChangeLogging() {
1038 MetricsLogger mockLogger = mock(MetricsLogger.class);
1039 Configuration oldConfig = new Configuration();
1040 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
1041
1042 Configuration newConfig = new Configuration();
1043 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +08001044 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001045 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
1046 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +08001047 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -05001048
1049 displayContent.onConfigurationChanged(newConfig);
1050
1051 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1052 verify(mockLogger).write(logMakerCaptor.capture());
1053 assertThat(logMakerCaptor.getValue().getCategory(),
1054 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
1055 assertThat(logMakerCaptor.getValue().getSubtype(),
1056 is(Configuration.ORIENTATION_PORTRAIT));
1057 }
1058
Evan Rosky69cace42019-09-20 16:28:13 -07001059 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +08001060 public void testApplyTopFixedRotationTransform() {
1061 mWm.mIsFixedRotationTransformEnabled = true;
1062 final Configuration config90 = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001063 mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001064
1065 final Configuration config = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001066 mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001067 mDisplayContent.computeScreenConfiguration(config);
1068 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1069
1070 final ActivityRecord app = mAppWindow.mActivityRecord;
1071 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1072 false /* alwaysKeepCurrent */);
1073 mDisplayContent.mOpeningApps.add(app);
Riddle Hsud4957432020-04-24 22:06:29 +08001074 final int newOrientation = getRotatedOrientation(mDisplayContent);
1075 app.setRequestedOrientation(newOrientation);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001076
1077 assertTrue(app.isFixedRotationTransforming());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001078 assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
1079 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
1080 false /* forceUpdate */));
Riddle Hsuf41034c2020-03-19 13:10:46 +08001081
1082 final Rect outFrame = new Rect();
1083 final Rect outInsets = new Rect();
1084 final Rect outStableInsets = new Rect();
1085 final Rect outSurfaceInsets = new Rect();
1086 mAppWindow.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
1087 // The animation frames should not be rotated because display hasn't rotated.
1088 assertEquals(mDisplayContent.getBounds(), outFrame);
1089
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001090 // The display should keep current orientation and the rotated configuration should apply
1091 // to the activity.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001092 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1093 assertEquals(config90.orientation, app.getConfiguration().orientation);
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001094 assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001095
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001096 // Make wallaper laid out with the fixed rotation transform.
1097 final WindowToken wallpaperToken = mWallpaperWindow.mToken;
1098 wallpaperToken.linkFixedRotationTransform(app);
1099 mWallpaperWindow.mLayoutNeeded = true;
1100 performLayout(mDisplayContent);
1101
Riddle Hsu6da58ac2020-04-02 01:04:40 +08001102 // Force the negative offset to verify it can be updated.
1103 mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
1104 assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
1105 false /* sync */));
1106 assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
1107 assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
1108
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001109 // The wallpaper need to animate with transformed position, so its surface position should
1110 // not be reset.
1111 final Transaction t = wallpaperToken.getPendingTransaction();
1112 spyOn(t);
1113 mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
1114 verify(t, never()).setPosition(any(), eq(0), eq(0));
1115
Riddle Hsud4957432020-04-24 22:06:29 +08001116 // Launch another activity before the transition is finished.
1117 final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
1118 .setDisplay(mDisplayContent).build().getTopMostActivity();
1119 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1120 false /* alwaysKeepCurrent */);
1121 mDisplayContent.mOpeningApps.add(app2);
1122 app2.setRequestedOrientation(newOrientation);
1123
1124 // The activity should share the same transform state as the existing one.
1125 assertTrue(app.hasFixedRotationTransform(app2));
1126
1127 // The display should be rotated after the launch is finished.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001128 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1129
Riddle Hsud4957432020-04-24 22:06:29 +08001130 // The fixed rotation should be cleared and the new rotation is applied to display.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001131 assertFalse(app.hasFixedRotationTransform());
Riddle Hsud4957432020-04-24 22:06:29 +08001132 assertFalse(app2.hasFixedRotationTransform());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001133 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
1134 }
1135
1136 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001137 public void testRemoteRotation() {
1138 DisplayContent dc = createNewDisplay();
1139
1140 final DisplayRotation dr = dc.getDisplayRotation();
1141 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
1142 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1143 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001144 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -07001145 Mockito.doAnswer(
1146 invocation -> {
1147 continued[0] = true;
1148 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001149 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001150 final boolean[] called = new boolean[1];
1151 mWm.mDisplayRotationController =
1152 new IDisplayWindowRotationController.Stub() {
1153 @Override
1154 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1155 IDisplayWindowRotationCallback callback) {
1156 called[0] = true;
1157
1158 try {
1159 callback.continueRotateDisplay(toRotation, null);
1160 } catch (RemoteException e) {
1161 assertTrue(false);
1162 }
1163 }
1164 };
1165
1166 // kill any existing rotation animation (vestigial from test setup).
1167 dc.setRotationAnimation(null);
1168
1169 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1170 assertTrue(called[0]);
1171 waitUntilHandlersIdle();
1172 assertTrue(continued[0]);
1173 }
1174
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001175 @Test
1176 public void testGetOrCreateRootHomeTask_defaultDisplay() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001177 TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001178
1179 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian86d676c2020-03-27 19:34:54 -07001180 ActivityStack homeTask = defaultTaskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001181 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001182 defaultTaskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001183 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001184 assertNull(defaultTaskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001185
Andrii Kulian86d676c2020-03-27 19:34:54 -07001186 assertNotNull(defaultTaskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001187 }
1188
1189 @Test
1190 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1191 DisplayContent display = createNewDisplay();
1192 doReturn(true).when(display).supportsSystemDecorations();
1193 doReturn(false).when(display).isUntrustedVirtualDisplay();
1194
1195 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001196 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Andrii Kulian86d676c2020-03-27 19:34:54 -07001197 ActivityStack homeTask = taskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001198 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001199 taskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001200 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001201 assertNull(taskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001202
Andrii Kulian86d676c2020-03-27 19:34:54 -07001203 assertNotNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001204 }
1205
1206 @Test
1207 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1208 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001209 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001210 doReturn(false).when(display).supportsSystemDecorations();
1211
Andrii Kulian86d676c2020-03-27 19:34:54 -07001212 assertNull(taskDisplayArea.getRootHomeTask());
1213 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001214 }
1215
1216 @Test
1217 public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
1218 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001219 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001220 doReturn(true).when(display).isUntrustedVirtualDisplay();
1221
Andrii Kulian86d676c2020-03-27 19:34:54 -07001222 assertNull(taskDisplayArea.getRootHomeTask());
1223 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001224 }
1225
Mark Renoufa9279292020-04-17 12:22:50 -04001226 @Test
1227 public void testFindScrollCaptureTargetWindow_behindWindow() {
1228 DisplayContent display = createNewDisplay();
1229 ActivityStack stack = createTaskStackOnDisplay(display);
1230 Task task = createTaskInStack(stack, 0 /* userId */);
1231 WindowState activityWindow = createAppWindow(task, TYPE_APPLICATION, "App Window");
1232 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1233
1234 WindowState result = display.findScrollCaptureTargetWindow(behindWindow,
1235 ActivityTaskManager.INVALID_TASK_ID);
1236 assertEquals(activityWindow, result);
1237 }
1238
1239 @Test
1240 public void testFindScrollCaptureTargetWindow_taskId() {
1241 DisplayContent display = createNewDisplay();
1242 ActivityStack stack = createTaskStackOnDisplay(display);
1243 Task task = createTaskInStack(stack, 0 /* userId */);
1244 WindowState window = createAppWindow(task, TYPE_APPLICATION, "App Window");
1245 WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
1246
1247 WindowState result = display.findScrollCaptureTargetWindow(null, task.mTaskId);
1248 assertEquals(window, result);
1249 }
1250
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001251 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001252 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001253 }
1254
Bryce Lee27cec322017-03-21 09:41:37 -07001255 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1256 int expectedBaseHeight, int expectedBaseDensity) {
1257 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1258 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1259 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1260 }
1261
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001262 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001263 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001264 }
1265
Riddle Hsu12c05452020-01-09 00:39:52 +08001266 private void performLayout(DisplayContent dc) {
1267 dc.setLayoutNeeded();
1268 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1269 }
1270
Riddle Hsu654a6f92018-07-13 22:59:36 +08001271 /**
1272 * Create DisplayContent that does not update display base/initial values from device to keep
1273 * the values set by test.
1274 */
1275 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001276 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001277 doNothing().when(displayContent).updateDisplayInfo();
1278 return displayContent;
1279 }
1280
Adrian Roos0f9368c2018-04-08 10:59:08 -07001281 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1282 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001283
1284 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001285 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001286 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1287
1288 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001289
1290 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001291 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001292 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1293 }
1294
Riddle Hsud4957432020-04-24 22:06:29 +08001295 private static int getRotatedOrientation(DisplayContent dc) {
1296 return dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
1297 ? SCREEN_ORIENTATION_PORTRAIT
1298 : SCREEN_ORIENTATION_LANDSCAPE;
1299 }
1300
Adrian Roos0f9368c2018-04-08 10:59:08 -07001301 private static List<WindowState> reverseList(List<WindowState> list) {
1302 final ArrayList<WindowState> result = new ArrayList<>(list);
1303 Collections.reverse(result);
1304 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001305 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001306
Arthur Hungbe5ce212018-09-13 18:41:56 +08001307 private void tapOnDisplay(final DisplayContent dc) {
1308 final DisplayMetrics dm = dc.getDisplayMetrics();
1309 final float x = dm.widthPixels / 2;
1310 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001311 final long downTime = SystemClock.uptimeMillis();
1312 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001313 // sending ACTION_DOWN
1314 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001315 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001316 downTime,
1317 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001318 x,
1319 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001320 0 /*metaState*/);
1321 downEvent.setDisplayId(dc.getDisplayId());
1322 dc.mTapDetector.onPointerEvent(downEvent);
1323
1324 // sending ACTION_UP
1325 final MotionEvent upEvent = MotionEvent.obtain(
1326 downTime,
1327 eventTime,
1328 MotionEvent.ACTION_UP,
1329 x,
1330 y,
1331 0 /*metaState*/);
1332 upEvent.setDisplayId(dc.getDisplayId());
1333 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001334 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001335}