blob: 3fd81b47c546ddec8c7a425cc8d01e6ed1688de8 [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;
Riddle Hsufc246d12020-03-20 18:28:11 +080059import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
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;
Arthur Hungbe5ce212018-09-13 18:41:56 +080068import static org.junit.Assert.assertNotNull;
lumarkff0ab692018-11-05 20:32:30 +080069import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010070import static org.junit.Assert.assertThat;
Wale Ogunwale34247952017-02-19 11:57:53 -080071import static org.junit.Assert.assertTrue;
Evan Rosky69cace42019-09-20 16:28:13 -070072import static org.mockito.ArgumentMatchers.anyInt;
Tarandeep Singha6f35612019-01-11 19:50:46 -080073import static org.mockito.ArgumentMatchers.eq;
Wale Ogunwale34247952017-02-19 11:57:53 -080074
Andrii Kulian92c9a942017-10-10 00:41:41 -070075import android.annotation.SuppressLint;
Tarandeep Singha6f35612019-01-11 19:50:46 -080076import android.app.WindowConfiguration;
Andrii Kuliand68501e2017-01-10 22:57:27 -080077import android.content.res.Configuration;
Adrian Roos1cf585052018-01-03 18:43:27 +010078import android.graphics.Rect;
Adrian Roos4ffc8972019-02-07 20:45:11 +010079import android.graphics.Region;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -050080import android.metrics.LogMaker;
Evan Rosky69cace42019-09-20 16:28:13 -070081import android.os.RemoteException;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070082import android.os.SystemClock;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070083import android.platform.test.annotations.Presubmit;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070084import android.util.DisplayMetrics;
Adrian Roos1cf585052018-01-03 18:43:27 +010085import android.view.DisplayCutout;
Riddle Hsua4d6fa22018-08-11 00:50:39 +080086import android.view.Gravity;
Evan Rosky69cace42019-09-20 16:28:13 -070087import android.view.IDisplayWindowRotationCallback;
88import android.view.IDisplayWindowRotationController;
Adrian Roos4ffc8972019-02-07 20:45:11 +010089import android.view.ISystemGestureExclusionListener;
Garfield Tana3f19032019-11-19 18:04:50 -080090import android.view.IWindowManager;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070091import android.view.MotionEvent;
Adrian Roos1cf585052018-01-03 18:43:27 +010092import android.view.Surface;
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +080093import android.view.SurfaceControl.Transaction;
Tarandeep Singha6f35612019-01-11 19:50:46 -080094import android.view.ViewRootImpl;
Riddle Hsu12c05452020-01-09 00:39:52 +080095import android.view.WindowManager;
Tarandeep Singha6f35612019-01-11 19:50:46 -080096import android.view.test.InsetsModeSession;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070097
Brett Chabota26eda92018-07-23 13:08:30 -070098import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070099
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500100import com.android.internal.logging.MetricsLogger;
101import com.android.internal.logging.nano.MetricsProto;
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100102import com.android.server.wm.utils.WmDisplayCutout;
103
Brett Chabota26eda92018-07-23 13:08:30 -0700104import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +0800105import org.junit.runner.RunWith;
Garfield Tan90b04282018-12-11 14:04:42 -0800106import org.mockito.ArgumentCaptor;
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500107import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -0700108
Adrian Roos0f9368c2018-04-08 10:59:08 -0700109import java.util.ArrayList;
Wale Ogunwale34247952017-02-19 11:57:53 -0800110import java.util.Arrays;
Adrian Roos0f9368c2018-04-08 10:59:08 -0700111import java.util.Collections;
Wale Ogunwale34247952017-02-19 11:57:53 -0800112import java.util.LinkedList;
113import java.util.List;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700114
115/**
116 * Tests for the {@link DisplayContent} class.
117 *
118 * Build/Install/Run:
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900119 * atest WmTests:DisplayContentTests
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700120 */
121@SmallTest
122@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +0800123@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800124public class DisplayContentTests extends WindowTestsBase {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700125
126 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700127 public void testForAllWindows() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800128 final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700129 mDisplayContent, "exiting app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700130 final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
Yunfan Chen6dd9a622019-02-18 15:12:33 +0900131 // Wait until everything in animation handler get executed to prevent the exiting window
132 // from being removed during WindowSurfacePlacer Traversal.
133 waitUntilHandlersIdle();
134
Garfield Tane8d84ab2019-10-11 09:49:40 -0700135 exitingApp.mIsExiting = true;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800136 exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700137
Wale Ogunwale34247952017-02-19 11:57:53 -0800138 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700139 mWallpaperWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800140 exitingAppWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700141 mChildAppWindowBelow,
142 mAppWindow,
143 mChildAppWindowAbove,
144 mDockedDividerWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200145 mImeWindow,
146 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700147 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800148 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200149 mNavBarWindow));
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800150 }
151
152 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700153 public void testForAllWindows_WithAppImeTarget() {
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800154 final WindowState imeAppTarget =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700155 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800156
lumarkff0ab692018-11-05 20:32:30 +0800157 mDisplayContent.mInputMethodTarget = imeAppTarget;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800158
Wale Ogunwale34247952017-02-19 11:57:53 -0800159 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700160 mWallpaperWindow,
161 mChildAppWindowBelow,
162 mAppWindow,
163 mChildAppWindowAbove,
Wale Ogunwale34247952017-02-19 11:57:53 -0800164 imeAppTarget,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700165 mImeWindow,
166 mImeDialogWindow,
167 mDockedDividerWindow,
168 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800169 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700170 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800171 }
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800172
Wale Ogunwale34247952017-02-19 11:57:53 -0800173 @Test
lumarkff0ab692018-11-05 20:32:30 +0800174 public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
175 mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
Wale Ogunwale3c1170d2016-12-02 14:44:52 -0800176
Wale Ogunwale34247952017-02-19 11:57:53 -0800177 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700178 mWallpaperWindow,
179 mChildAppWindowBelow,
180 mAppWindow,
181 mChildAppWindowAbove,
182 mImeWindow,
183 mImeDialogWindow,
184 mDockedDividerWindow,
185 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800186 mNotificationShadeWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700187 mNavBarWindow));
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700188 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800189
190 @Test
lumarkff0ab692018-11-05 20:32:30 +0800191 public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
192 mDisplayContent.mInputMethodTarget = mStatusBarWindow;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800193
Wale Ogunwale34247952017-02-19 11:57:53 -0800194 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700195 mWallpaperWindow,
196 mChildAppWindowBelow,
197 mAppWindow,
198 mChildAppWindowAbove,
199 mDockedDividerWindow,
200 mStatusBarWindow,
201 mImeWindow,
202 mImeDialogWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800203 mNotificationShadeWindow,
204 mNavBarWindow));
205 }
206
207 @Test
208 public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
209 mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
210
211 assertForAllWindowsOrder(Arrays.asList(
212 mWallpaperWindow,
213 mChildAppWindowBelow,
214 mAppWindow,
215 mChildAppWindowAbove,
216 mDockedDividerWindow,
217 mStatusBarWindow,
218 mNotificationShadeWindow,
219 mImeWindow,
220 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700221 mNavBarWindow));
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800222 }
223
224 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700225 public void testForAllWindows_WithInBetweenWindowToken() {
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800226 // This window is set-up to be z-ordered between some windows that go in the same token like
227 // the nav bar and status bar.
228 final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700229 mDisplayContent, "voiceInteractionWindow");
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800230
Wale Ogunwale34247952017-02-19 11:57:53 -0800231 assertForAllWindowsOrder(Arrays.asList(
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700232 mWallpaperWindow,
233 mChildAppWindowBelow,
234 mAppWindow,
235 mChildAppWindowAbove,
236 mDockedDividerWindow,
Wale Ogunwale34247952017-02-19 11:57:53 -0800237 voiceInteractionWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200238 mImeWindow,
239 mImeDialogWindow,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700240 mStatusBarWindow,
wilsonshihe8321942019-10-18 18:39:46 +0800241 mNotificationShadeWindow,
Adrian Roos22a20a82019-10-23 19:05:33 +0200242 mNavBarWindow));
Wale Ogunwale34247952017-02-19 11:57:53 -0800243 }
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800244
Wale Ogunwale34247952017-02-19 11:57:53 -0800245 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700246 public void testComputeImeTarget() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800247 // Verify that an app window can be an ime target.
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700248 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
Wale Ogunwale34247952017-02-19 11:57:53 -0800249 appWin.setHasSurface(true);
250 assertTrue(appWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700251 WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800252 assertEquals(appWin, imeTarget);
chaviwebcbc342018-02-07 13:19:00 -0800253 appWin.mHidden = false;
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800254
Wale Ogunwale34247952017-02-19 11:57:53 -0800255 // Verify that an child window can be an ime target.
256 final WindowState childWin = createWindow(appWin,
257 TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
258 childWin.setHasSurface(true);
259 assertTrue(childWin.canBeImeTarget());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700260 imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
Wale Ogunwale34247952017-02-19 11:57:53 -0800261 assertEquals(childWin, imeTarget);
Wale Ogunwale5d7e7f12016-12-12 14:47:05 -0800262 }
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800263
Andrii Kuliand68501e2017-01-10 22:57:27 -0800264 /**
265 * This tests stack movement between displays and proper stack's, task's and app token's display
266 * container references updates.
267 */
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800268 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700269 public void testMoveStackBetweenDisplays() {
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800270 // Create a second display.
271 final DisplayContent dc = createNewDisplay();
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800272
273 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700274 final ActivityStack stack = createTaskStackOnDisplay(dc);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800275 assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800276 assertEquals(dc, stack.getDisplayContent());
277
278 final Task task = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700279 final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
280 task.addChild(activity, 0);
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800281 assertEquals(dc, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700282 assertEquals(dc, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800283
284 // Move stack to first display.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700285 stack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true /* onTop */);
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700286 assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700287 assertEquals(mDisplayContent, stack.getDisplayContent());
288 assertEquals(mDisplayContent, task.getDisplayContent());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700289 assertEquals(mDisplayContent, activity.getDisplayContent());
Andrii Kulian6cc1a1d2016-12-27 23:52:59 -0800290 }
Andrii Kuliand68501e2017-01-10 22:57:27 -0800291
292 /**
293 * This tests override configuration updates for display content.
294 */
295 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700296 public void testDisplayOverrideConfigUpdate() {
Evan Roskydfe3da72018-10-26 17:21:06 -0700297 final Configuration currentOverrideConfig =
298 mDisplayContent.getRequestedOverrideConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800299
300 // Create new, slightly changed override configuration and apply it to the display.
301 final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
302 newOverrideConfig.densityDpi += 120;
303 newOverrideConfig.fontScale += 0.3;
304
Evan Roskye747c3e2018-10-30 20:06:41 -0700305 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800306
307 // Check that override config is applied.
Evan Roskydfe3da72018-10-26 17:21:06 -0700308 assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800309 }
310
311 /**
312 * This tests global configuration updates when default display config is updated.
313 */
314 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700315 public void testDefaultDisplayOverrideConfigUpdate() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700316 DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
317 final Configuration currentConfig = defaultDisplay.getConfiguration();
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800318
319 // Create new, slightly changed override configuration and apply it to the display.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700320 final Configuration newOverrideConfig = new Configuration(currentConfig);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800321 newOverrideConfig.densityDpi += 120;
322 newOverrideConfig.fontScale += 0.3;
323
Evan Roskye747c3e2018-10-30 20:06:41 -0700324 mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800325
326 // Check that global configuration is updated, as we've updated default display's config.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700327 Configuration globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliand68501e2017-01-10 22:57:27 -0800328 assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
329 assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kulian367ff7f2017-01-25 19:45:34 -0800330
331 // Return back to original values.
Evan Roskye747c3e2018-10-30 20:06:41 -0700332 mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700333 globalConfig = mWm.mRoot.getConfiguration();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700334 assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
335 assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
Andrii Kuliand68501e2017-01-10 22:57:27 -0800336 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800337
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700338 /**
339 * Tests tapping on a stack in different display results in window gaining focus.
340 */
341 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700342 public void testInputEventBringsCorrectDisplayInFocus() {
343 DisplayContent dc0 = mWm.getDefaultDisplayContentLocked();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700344 // Create a second display
345 final DisplayContent dc1 = createNewDisplay();
346
347 // Add stack with activity.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700348 final ActivityStack stack0 = createTaskStackOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700349 final Task task0 = createTaskInStack(stack0, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700350 final ActivityRecord activity =
351 WindowTestUtils.createTestActivityRecord(dc0);
352 task0.addChild(activity, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800353 dc0.configureDisplayPolicy();
354 assertNotNull(dc0.mTapDetector);
355
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700356 final ActivityStack stack1 = createTaskStackOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700357 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700358 final ActivityRecord activity1 =
359 WindowTestUtils.createTestActivityRecord(dc0);
360 task1.addChild(activity1, 0);
Arthur Hungbe5ce212018-09-13 18:41:56 +0800361 dc1.configureDisplayPolicy();
362 assertNotNull(dc1.mTapDetector);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700363
Arthur Hungbe5ce212018-09-13 18:41:56 +0800364 // tap on primary display.
365 tapOnDisplay(dc0);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700366 // Check focus is on primary display.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700367 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800368 dc0.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700369
Arthur Hungbe5ce212018-09-13 18:41:56 +0800370 // Tap on secondary display.
371 tapOnDisplay(dc1);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700372 // Check focus is on secondary.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700373 assertEquals(mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800374 dc1.findFocusedWindow());
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700375 }
376
David Stevens46939562017-03-24 13:04:00 -0700377 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700378 public void testFocusedWindowMultipleDisplays() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800379 doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
380 }
381
382 @Test
383 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
384 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
385 }
386
387 @Test
388 public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
389 doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
390 }
391
392 private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
393 int targetSdk) {
394 mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
395
Andrii Kulian0214ed92017-05-16 13:44:05 -0700396 // Create a focusable window and check that focus is calculated correctly
David Stevens46939562017-03-24 13:04:00 -0700397 final WindowState window1 =
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700398 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700399 window1.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800400 updateFocusedWindow();
401 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700402 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700403
404 // Check that a new display doesn't affect focus
405 final DisplayContent dc = createNewDisplay();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800406 updateFocusedWindow();
407 assertTrue(window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700408 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700409
410 // Add a window to the second display, and it should be focused
411 final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700412 window2.mActivityRecord.mTargetSdk = targetSdk;
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800413 updateFocusedWindow();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800414 assertTrue(window2.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800415 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700416 assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
David Stevens46939562017-03-24 13:04:00 -0700417
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800418 // Move the first window to top including parents, and make sure focus is updated
David Stevens46939562017-03-24 13:04:00 -0700419 window1.getParent().positionChildAt(POSITION_TOP, window1, true);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800420 updateFocusedWindow();
421 assertTrue(window1.isFocused());
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800422 assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700423 assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
Louis Changa9350fe2019-04-25 17:14:20 +0800424
425 // Make sure top focused display not changed if there is a focused app.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100426 window1.mActivityRecord.mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700427 window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
Louis Changa9350fe2019-04-25 17:14:20 +0800428 updateFocusedWindow();
429 assertTrue(!window1.isFocused());
430 assertEquals(window1.getDisplayId(),
431 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
Adrian Roos4163d622018-05-22 16:56:35 +0200432 }
433
Riddle Hsub2297ad2019-07-26 23:37:25 -0600434 @Test
435 public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
436 mWm.mSystemBooted = true;
437 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
438 final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
439 TYPE_WALLPAPER, TYPE_APPLICATION);
440
441 // Verify waiting for windows to be drawn.
442 assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
443
444 // Verify not waiting for drawn windows.
445 makeWindowsDrawn(windows);
446 assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
447 }
448
449 @Test
450 public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
451 mWm.mSystemBooted = true;
452 final DisplayContent secondaryDisplay = createNewDisplay();
453 final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
454 TYPE_WALLPAPER, TYPE_APPLICATION);
455
456 // Verify not waiting for display without system decorations.
457 doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
458 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
459
460 // Verify waiting for non-drawn windows on display with system decorations.
461 reset(secondaryDisplay);
462 doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
463 assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
464
465 // Verify not waiting for drawn windows on display with system decorations.
466 makeWindowsDrawn(windows);
467 assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
468 }
469
470 private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
471 final WindowState[] windows = new WindowState[types.length];
472 for (int i = 0; i < types.length; i++) {
473 final int type = types[i];
474 windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
475 windows[i].mHasSurface = false;
476 }
477 return windows;
478 }
479
480 private static void makeWindowsDrawn(WindowState[] windows) {
481 for (WindowState window : windows) {
482 window.mHasSurface = true;
483 window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
484 }
485 }
486
Bryce Lee27cec322017-03-21 09:41:37 -0700487 /**
488 * This tests setting the maximum ui width on a display.
489 */
490 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700491 public void testMaxUiWidth() {
Riddle Hsu654a6f92018-07-13 22:59:36 +0800492 // Prevent base display metrics for test from being updated to the value of real display.
493 final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
Bryce Lee27cec322017-03-21 09:41:37 -0700494 final int baseWidth = 1440;
495 final int baseHeight = 2560;
496 final int baseDensity = 300;
497
Riddle Hsu654a6f92018-07-13 22:59:36 +0800498 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700499
500 final int maxWidth = 300;
501 final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
502 final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
503
Riddle Hsu654a6f92018-07-13 22:59:36 +0800504 displayContent.setMaxUiWidth(maxWidth);
505 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700506
507 // Assert setting values again does not change;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800508 displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
509 verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700510
511 final int smallerWidth = 200;
512 final int smallerHeight = 400;
513 final int smallerDensity = 100;
514
515 // Specify smaller dimension, verify that it is honored
Riddle Hsu654a6f92018-07-13 22:59:36 +0800516 displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
517 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700518
519 // Verify that setting the max width to a greater value than the base width has no effect
Riddle Hsu654a6f92018-07-13 22:59:36 +0800520 displayContent.setMaxUiWidth(maxWidth);
521 verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
Bryce Lee27cec322017-03-21 09:41:37 -0700522 }
523
Andrii Kulian92c9a942017-10-10 00:41:41 -0700524 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700525 public void testDisplayCutout_rot0() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800526 final DisplayContent dc = createNewDisplay();
527 dc.mInitialDisplayWidth = 200;
528 dc.mInitialDisplayHeight = 400;
529 final Rect r = new Rect(80, 0, 120, 10);
530 final DisplayCutout cutout = new WmDisplayCutout(
531 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_TOP), null)
532 .computeSafeInsets(200, 400).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100533
Riddle Hsu73f53572019-09-23 23:13:01 +0800534 dc.mInitialDisplayCutout = cutout;
535 dc.getDisplayRotation().setRotation(Surface.ROTATION_0);
536 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100537
Riddle Hsu73f53572019-09-23 23:13:01 +0800538 assertEquals(cutout, dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100539 }
540
541 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700542 public void testDisplayCutout_rot90() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800543 // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
544 // if the device has no cutout).
545 final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
Garfield Tan7cb30142019-12-20 16:43:06 -0800546 // This test assumes it's a top cutout on a portrait display, so if it happens to be a
547 // landscape display let's rotate it.
548 if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
549 int tmp = dc.mInitialDisplayHeight;
550 dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
551 dc.mInitialDisplayWidth = tmp;
552 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800553 // Rotation may use real display info to compute bound, so here also uses the
554 // same width and height.
555 final int displayWidth = dc.mInitialDisplayWidth;
556 final int displayHeight = dc.mInitialDisplayHeight;
557 final int cutoutWidth = 40;
558 final int cutoutHeight = 10;
559 final int left = (displayWidth - cutoutWidth) / 2;
560 final int top = 0;
561 final int right = (displayWidth + cutoutWidth) / 2;
562 final int bottom = cutoutHeight;
Riddle Hsu654a6f92018-07-13 22:59:36 +0800563
Riddle Hsu73f53572019-09-23 23:13:01 +0800564 final Rect r1 = new Rect(left, top, right, bottom);
565 final DisplayCutout cutout = new WmDisplayCutout(
566 fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom, BOUNDS_POSITION_TOP), null)
567 .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
Adrian Roos1cf585052018-01-03 18:43:27 +0100568
Riddle Hsu73f53572019-09-23 23:13:01 +0800569 dc.mInitialDisplayCutout = cutout;
570 dc.getDisplayRotation().setRotation(Surface.ROTATION_90);
571 dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
Adrian Roos1cf585052018-01-03 18:43:27 +0100572
Riddle Hsu73f53572019-09-23 23:13:01 +0800573 // ----o---------- -------------
574 // | | | | |
575 // | ------o | o---
576 // | | | |
577 // | | -> | |
578 // | | ---o
579 // | | |
580 // | | -------------
581 final Rect r = new Rect(top, left, bottom, right);
582 assertEquals(new WmDisplayCutout(
583 fromBoundingRect(r.left, r.top, r.right, r.bottom, BOUNDS_POSITION_LEFT), null)
584 .computeSafeInsets(displayHeight, displayWidth).getDisplayCutout(),
585 dc.getDisplayInfo().displayCutout);
Adrian Roos1cf585052018-01-03 18:43:27 +0100586 }
587
588 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700589 public void testLayoutSeq_assignedDuringLayout() {
Riddle Hsu73f53572019-09-23 23:13:01 +0800590 final DisplayContent dc = createNewDisplay();
591 final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Adrian Roos5251b1d2018-03-23 18:57:43 +0100592
Riddle Hsu12c05452020-01-09 00:39:52 +0800593 performLayout(dc);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100594
Riddle Hsu73f53572019-09-23 23:13:01 +0800595 assertThat(win.mLayoutSeq, is(dc.mLayoutSeq));
Adrian Roos5251b1d2018-03-23 18:57:43 +0100596 }
597
598 @Test
Andrii Kulian92c9a942017-10-10 00:41:41 -0700599 @SuppressLint("InlinedApi")
600 public void testOrientationDefinedByKeyguard() {
601 final DisplayContent dc = createNewDisplay();
Garfield Tan90b04282018-12-11 14:04:42 -0800602
603 // When display content is created its configuration is not yet initialized, which could
604 // cause unnecessary configuration propagation, so initialize it here.
605 final Configuration config = new Configuration();
606 dc.computeScreenConfiguration(config);
607 dc.onRequestedOverrideConfigurationChanged(config);
608
Andrii Kulian92c9a942017-10-10 00:41:41 -0700609 // Create a window that requests landscape orientation. It will define device orientation
610 // by default.
611 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700612 window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700613
wilsonshihe8321942019-10-18 18:39:46 +0800614 final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
Andrii Kulian92c9a942017-10-10 00:41:41 -0700615 keyguard.mHasSurface = true;
616 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
617
618 assertEquals("Screen orientation must be defined by the app window by default",
619 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
620
621 keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
622 assertEquals("Visible keyguard must influence device orientation",
623 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
624
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700625 mWm.setKeyguardGoingAway(true);
Andrii Kulian92c9a942017-10-10 00:41:41 -0700626 assertEquals("Keyguard that is going away must not influence device orientation",
627 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
628 }
629
Andrii Kulianf0379de2018-03-14 16:24:07 -0700630 @Test
Tiger Huang86e6d072019-05-02 20:23:47 +0800631 public void testOrientationForAspectRatio() {
632 final DisplayContent dc = createNewDisplay();
633
634 // When display content is created its configuration is not yet initialized, which could
635 // cause unnecessary configuration propagation, so initialize it here.
636 final Configuration config = new Configuration();
637 dc.computeScreenConfiguration(config);
638 dc.onRequestedOverrideConfigurationChanged(config);
639
640 // Create a window that requests a fixed orientation. It will define device orientation
641 // by default.
642 final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
643 "window");
644 window.mHasSurface = true;
645 window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
646
647 // --------------------------------
648 // Test non-close-to-square display
649 // --------------------------------
650 dc.mBaseDisplayWidth = 1000;
651 dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
652 dc.configureDisplayPolicy();
653
654 assertEquals("Screen orientation must be defined by the window by default.",
655 window.mAttrs.screenOrientation, dc.getOrientation());
656
657 // ----------------------------
658 // Test close-to-square display
659 // ----------------------------
660 dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
661 dc.configureDisplayPolicy();
662
663 assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
664 SCREEN_ORIENTATION_USER, dc.getOrientation());
665 }
666
667 @Test
Andrii Kulianf0379de2018-03-14 16:24:07 -0700668 public void testDisableDisplayInfoOverrideFromWindowManager() {
669 final DisplayContent dc = createNewDisplay();
670
671 assertTrue(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700672 mWm.dontOverrideDisplayInfo(dc.getDisplayId());
Andrii Kulianf0379de2018-03-14 16:24:07 -0700673
674 assertFalse(dc.mShouldOverrideDisplayConfiguration);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700675 verify(mWm.mDisplayManagerInternal, times(1))
Andrii Kulianf0379de2018-03-14 16:24:07 -0700676 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
677 }
678
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800679 @Test
Riddle Hsu85bd04b2018-11-17 00:34:36 +0800680 public void testClearLastFocusWhenReparentingFocusedWindow() {
681 final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
682 final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
683 defaultDisplay, "window");
684 defaultDisplay.mLastFocus = window;
685 mDisplayContent.mCurrentFocus = window;
686 mDisplayContent.reParentWindowToken(window.mToken);
687
688 assertNull(defaultDisplay.mLastFocus);
689 }
690
691 @Test
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800692 public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
693 final DisplayContent portraitDisplay = createNewDisplay();
694 portraitDisplay.mInitialDisplayHeight = 2000;
695 portraitDisplay.mInitialDisplayWidth = 1000;
696
Riddle Hsuccf09402019-08-13 00:33:06 +0800697 portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800698 assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700699 portraitDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800700 assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
701
702 final DisplayContent landscapeDisplay = createNewDisplay();
703 landscapeDisplay.mInitialDisplayHeight = 1000;
704 landscapeDisplay.mInitialDisplayWidth = 2000;
705
Riddle Hsuccf09402019-08-13 00:33:06 +0800706 landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800707 assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
Evan Rosky69cace42019-09-20 16:28:13 -0700708 landscapeDisplay.getDisplayRotation().setRotation(ROTATION_90);
Riddle Hsua4d6fa22018-08-11 00:50:39 +0800709 assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
710 }
711
lumarkff0ab692018-11-05 20:32:30 +0800712 @Test
713 public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
714 final DisplayContent newDisplay = createNewDisplay();
715
716 final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
717 final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
718 appWin.setHasSurface(true);
719 appWin1.setHasSurface(true);
720
721 // Set current input method window on default display, make sure the input method target
722 // is appWin & null on the other display.
723 mDisplayContent.setInputMethodWindowLocked(mImeWindow);
724 newDisplay.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200725 assertEquals("appWin should be IME target window",
726 appWin, mDisplayContent.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800727 assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
728
729 // Switch input method window on new display & make sure the input method target also
730 // switched as expected.
731 newDisplay.setInputMethodWindowLocked(mImeWindow);
732 mDisplayContent.setInputMethodWindowLocked(null);
Wale Ogunwale3198da42019-10-10 14:45:03 +0200733 assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
lumarkff0ab692018-11-05 20:32:30 +0800734 assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
735 }
736
Garfield Tan90b04282018-12-11 14:04:42 -0800737 @Test
Garfield Tan98eead32019-11-18 13:24:53 -0800738 public void testAllowsTopmostFullscreenOrientation() {
739 final DisplayContent dc = createNewDisplay();
740 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800741 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan98eead32019-11-18 13:24:53 -0800742
743 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800744 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800745 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800746 .build();
747 doReturn(true).when(stack).isVisible();
748
749 final ActivityStack freeformStack =
Louis Chang149d5c82019-12-30 09:47:39 +0800750 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800751 .setDisplay(dc)
Garfield Tan98eead32019-11-18 13:24:53 -0800752 .setWindowingMode(WINDOWING_MODE_FREEFORM)
753 .build();
754 doReturn(true).when(freeformStack).isVisible();
755 freeformStack.getTopChild().setBounds(100, 100, 300, 400);
756
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700757 assertTrue(dc.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM));
Garfield Tan98eead32019-11-18 13:24:53 -0800758
759 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
760 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
761 assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
762
763 stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
764 freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
765 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
766 }
767
768 @Test
Garfield Tan90b04282018-12-11 14:04:42 -0800769 public void testOnDescendantOrientationRequestChanged() {
Garfield Tan49dae102019-02-04 09:51:59 -0800770 final DisplayContent dc = createNewDisplay();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700771 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800772 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800773 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
774 ? SCREEN_ORIENTATION_PORTRAIT
775 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800776
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700777 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800778 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800779 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900780 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800781
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700782 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800783
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700784 final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
785 ? Configuration.ORIENTATION_PORTRAIT
786 : Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky01775072019-09-11 17:28:07 -0700787 assertEquals(expectedOrientation, dc.getConfiguration().orientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800788 }
789
790 @Test
791 public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
Garfield Tan49dae102019-02-04 09:51:59 -0800792 final DisplayContent dc = createNewDisplay();
Garfield Tan7fbca052019-02-19 10:45:35 -0800793 dc.getDisplayRotation().setFixedToUserRotation(
Garfield Tana3f19032019-11-19 18:04:50 -0800794 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
Garfield Tan49dae102019-02-04 09:51:59 -0800795 final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
796 ? SCREEN_ORIENTATION_PORTRAIT
797 : SCREEN_ORIENTATION_LANDSCAPE;
Garfield Tan90b04282018-12-11 14:04:42 -0800798
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700799 final ActivityStack stack =
Louis Chang149d5c82019-12-30 09:47:39 +0800800 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
Louis Chang2453d062019-11-19 22:30:48 +0800801 .setDisplay(dc).build();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900802 final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
Garfield Tan90b04282018-12-11 14:04:42 -0800803
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700804 activity.setRequestedOrientation(newOrientation);
Garfield Tan90b04282018-12-11 14:04:42 -0800805
Louis Chang677921f2019-12-06 16:44:24 +0800806 verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
807 anyBoolean(), same(null));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700808 assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
Garfield Tan90b04282018-12-11 14:04:42 -0800809 }
810
Tarandeep Singha6f35612019-01-11 19:50:46 -0800811 @Test
812 public void testComputeImeParent_app() throws Exception {
813 try (final InsetsModeSession session =
814 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
815 final DisplayContent dc = createNewDisplay();
816 dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700817 assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
Tarandeep Singha6f35612019-01-11 19:50:46 -0800818 dc.computeImeParent());
819 }
820 }
821
822 @Test
823 public void testComputeImeParent_app_notFullscreen() throws Exception {
824 try (final InsetsModeSession session =
825 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
826 final DisplayContent dc = createNewDisplay();
827 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
828 dc.mInputMethodTarget.setWindowingMode(
829 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
Adrian Roos329cbd02020-04-14 15:42:41 +0200830 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800831 }
832 }
833
834 @Test
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800835 public void testComputeImeParent_app_notMatchParentBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700836 spyOn(mAppWindow.mActivityRecord);
837 doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800838 mDisplayContent.mInputMethodTarget = mAppWindow;
839 // The surface parent of IME should be the display instead of app window.
Adrian Roos329cbd02020-04-14 15:42:41 +0200840 assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
841 mDisplayContent.computeImeParent());
Riddle Hsu6d6f67c2019-03-14 16:54:26 +0800842 }
843
844 @Test
Tarandeep Singha6f35612019-01-11 19:50:46 -0800845 public void testComputeImeParent_noApp() throws Exception {
846 try (final InsetsModeSession session =
847 new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
848 final DisplayContent dc = createNewDisplay();
849 dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
Adrian Roos329cbd02020-04-14 15:42:41 +0200850 assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
Tarandeep Singha6f35612019-01-11 19:50:46 -0800851 }
852 }
853
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500854 @Test
Adrian Roos4ffc8972019-02-07 20:45:11 +0100855 public void testUpdateSystemGestureExclusion() throws Exception {
856 final DisplayContent dc = createNewDisplay();
857 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
858 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
859 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
860
Riddle Hsu12c05452020-01-09 00:39:52 +0800861 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100862
863 win.setHasSurface(true);
864 dc.updateSystemGestureExclusion();
865
Riddle Hsu73f53572019-09-23 23:13:01 +0800866 final boolean[] invoked = { false };
Adrian Roos4ffc8972019-02-07 20:45:11 +0100867 final ISystemGestureExclusionListener.Stub verifier =
868 new ISystemGestureExclusionListener.Stub() {
869 @Override
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200870 public void onSystemGestureExclusionChanged(int displayId, Region actual,
871 Region unrestricted) {
Adrian Roos4ffc8972019-02-07 20:45:11 +0100872 Region expected = Region.obtain();
873 expected.set(10, 20, 30, 40);
874 assertEquals(expected, actual);
Riddle Hsu73f53572019-09-23 23:13:01 +0800875 invoked[0] = true;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100876 }
877 };
878 try {
879 dc.registerSystemGestureExclusionListener(verifier);
880 } finally {
881 dc.unregisterSystemGestureExclusionListener(verifier);
882 }
Riddle Hsu73f53572019-09-23 23:13:01 +0800883 assertTrue("SystemGestureExclusionListener was not invoked", invoked[0]);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100884 }
885
886 @Test
887 public void testCalculateSystemGestureExclusion() throws Exception {
888 final DisplayContent dc = createNewDisplay();
889 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
890 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
891 win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
892
893 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
894 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
895 win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
896
Riddle Hsu12c05452020-01-09 00:39:52 +0800897 performLayout(dc);
Adrian Roos4ffc8972019-02-07 20:45:11 +0100898
899 win.setHasSurface(true);
900 win2.setHasSurface(true);
901
902 final Region expected = Region.obtain();
903 expected.set(20, 30, 40, 50);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200904 assertEquals(expected, calculateSystemGestureExclusion(dc));
905 }
906
907 private Region calculateSystemGestureExclusion(DisplayContent dc) {
908 Region out = Region.obtain();
909 Region unrestricted = Region.obtain();
910 dc.calculateSystemGestureExclusion(out, unrestricted);
911 return out;
Adrian Roos4ffc8972019-02-07 20:45:11 +0100912 }
913
914 @Test
Adrian Roosb1063792019-06-28 12:10:51 +0200915 public void testCalculateSystemGestureExclusion_modal() throws Exception {
916 final DisplayContent dc = createNewDisplay();
917 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
918 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
919 win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
920
921 final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
922 win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
923 win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
924 win2.getAttrs().width = 10;
925 win2.getAttrs().height = 10;
926 win2.setSystemGestureExclusion(Collections.emptyList());
927
Riddle Hsu12c05452020-01-09 00:39:52 +0800928 performLayout(dc);
Adrian Roosb1063792019-06-28 12:10:51 +0200929
930 win.setHasSurface(true);
931 win2.setHasSurface(true);
932
933 final Region expected = Region.obtain();
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200934 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roosb1063792019-06-28 12:10:51 +0200935 }
936
937 @Test
Adrian Roos019a52b2019-07-02 16:47:44 +0200938 public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
Adrian Roos1c2e9a12019-08-20 18:23:47 +0200939 mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
Adrian Roos019a52b2019-07-02 16:47:44 +0200940
Riddle Hsu73f53572019-09-23 23:13:01 +0800941 final DisplayContent dc = createNewDisplay();
942 final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
943 win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
944 win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
945 win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
946 win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
947 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
948 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700949 win.mActivityRecord.mTargetSdk = P;
Adrian Roos019a52b2019-07-02 16:47:44 +0200950
Riddle Hsu12c05452020-01-09 00:39:52 +0800951 performLayout(dc);
Adrian Roos019a52b2019-07-02 16:47:44 +0200952
Riddle Hsu73f53572019-09-23 23:13:01 +0800953 win.setHasSurface(true);
Adrian Roos019a52b2019-07-02 16:47:44 +0200954
Riddle Hsu73f53572019-09-23 23:13:01 +0800955 final Region expected = Region.obtain();
956 expected.set(dc.getBounds());
957 assertEquals(expected, calculateSystemGestureExclusion(dc));
Adrian Roos019a52b2019-07-02 16:47:44 +0200958
Riddle Hsu73f53572019-09-23 23:13:01 +0800959 win.setHasSurface(false);
Adrian Roos019a52b2019-07-02 16:47:44 +0200960 }
961
962 @Test
Riddle Hsu12c05452020-01-09 00:39:52 +0800963 public void testRequestResizeForEmptyFrames() {
964 final WindowState win = mChildAppWindowAbove;
965 makeWindowVisible(win, win.getParentWindow());
966 win.setRequestedSize(mDisplayContent.mBaseDisplayWidth, 0 /* height */);
967 win.mAttrs.width = win.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT;
968 win.mAttrs.gravity = Gravity.CENTER;
969 performLayout(mDisplayContent);
970
971 // The frame is empty because the requested height is zero.
972 assertTrue(win.getFrameLw().isEmpty());
973 // The window should be scheduled to resize then the client may report a new non-empty size.
974 win.updateResizingWindowIfNeeded();
975 assertThat(mWm.mResizingWindows).contains(win);
976 }
977
978 @Test
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500979 public void testOrientationChangeLogging() {
980 MetricsLogger mockLogger = mock(MetricsLogger.class);
981 Configuration oldConfig = new Configuration();
982 oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
983
984 Configuration newConfig = new Configuration();
985 newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu73f53572019-09-23 23:13:01 +0800986 final DisplayContent displayContent = createNewDisplay();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500987 Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
988 Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
Louis Chang2453d062019-11-19 22:30:48 +0800989 doNothing().when(displayContent).preOnConfigurationChanged();
Susi Kharraz-Post9893b8c2019-02-12 14:21:29 -0500990
991 displayContent.onConfigurationChanged(newConfig);
992
993 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
994 verify(mockLogger).write(logMakerCaptor.capture());
995 assertThat(logMakerCaptor.getValue().getCategory(),
996 is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
997 assertThat(logMakerCaptor.getValue().getSubtype(),
998 is(Configuration.ORIENTATION_PORTRAIT));
999 }
1000
Evan Rosky69cace42019-09-20 16:28:13 -07001001 @Test
Riddle Hsu6f548e92020-01-13 13:34:09 +08001002 public void testApplyTopFixedRotationTransform() {
1003 mWm.mIsFixedRotationTransformEnabled = true;
1004 final Configuration config90 = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001005 mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001006
1007 final Configuration config = new Configuration();
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001008 mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
Riddle Hsu6f548e92020-01-13 13:34:09 +08001009 mDisplayContent.computeScreenConfiguration(config);
1010 mDisplayContent.onRequestedOverrideConfigurationChanged(config);
1011
Riddle Hsufc246d12020-03-20 18:28:11 +08001012 final ActivityRecord closingApp = new ActivityTestsBase.StackBuilder(mWm.mRoot)
1013 .setDisplay(mDisplayContent).setOnTop(false).build().getTopMostActivity();
1014 closingApp.nowVisible = true;
1015 closingApp.startAnimation(closingApp.getPendingTransaction(), mock(AnimationAdapter.class),
1016 false /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
1017 assertTrue(closingApp.isAnimating());
1018
Riddle Hsu6f548e92020-01-13 13:34:09 +08001019 final ActivityRecord app = mAppWindow.mActivityRecord;
1020 mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
1021 false /* alwaysKeepCurrent */);
1022 mDisplayContent.mOpeningApps.add(app);
1023 app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
1024
1025 assertTrue(app.isFixedRotationTransforming());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001026 assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
1027 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
1028 false /* forceUpdate */));
Riddle Hsuf41034c2020-03-19 13:10:46 +08001029
1030 final Rect outFrame = new Rect();
1031 final Rect outInsets = new Rect();
1032 final Rect outStableInsets = new Rect();
1033 final Rect outSurfaceInsets = new Rect();
1034 mAppWindow.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
1035 // The animation frames should not be rotated because display hasn't rotated.
1036 assertEquals(mDisplayContent.getBounds(), outFrame);
1037
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001038 // The display should keep current orientation and the rotated configuration should apply
1039 // to the activity.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001040 assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
1041 assertEquals(config90.orientation, app.getConfiguration().orientation);
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001042 assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
Riddle Hsu6f548e92020-01-13 13:34:09 +08001043
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001044 // Make wallaper laid out with the fixed rotation transform.
1045 final WindowToken wallpaperToken = mWallpaperWindow.mToken;
1046 wallpaperToken.linkFixedRotationTransform(app);
1047 mWallpaperWindow.mLayoutNeeded = true;
1048 performLayout(mDisplayContent);
1049
Riddle Hsu6da58ac2020-04-02 01:04:40 +08001050 // Force the negative offset to verify it can be updated.
1051 mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
1052 assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
1053 false /* sync */));
1054 assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
1055 assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
1056
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08001057 // The wallpaper need to animate with transformed position, so its surface position should
1058 // not be reset.
1059 final Transaction t = wallpaperToken.getPendingTransaction();
1060 spyOn(t);
1061 mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
1062 verify(t, never()).setPosition(any(), eq(0), eq(0));
1063
Riddle Hsu6f548e92020-01-13 13:34:09 +08001064 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
1065
Riddle Hsufc246d12020-03-20 18:28:11 +08001066 // The animation in old rotation should be cancelled.
1067 assertFalse(closingApp.isAnimating());
Riddle Hsu9239d7c62020-02-20 01:35:56 +08001068 // The display should be rotated after the launch is finished.
Riddle Hsu6f548e92020-01-13 13:34:09 +08001069 assertFalse(app.hasFixedRotationTransform());
1070 assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
1071 }
1072
1073 @Test
Evan Rosky69cace42019-09-20 16:28:13 -07001074 public void testRemoteRotation() {
1075 DisplayContent dc = createNewDisplay();
1076
1077 final DisplayRotation dr = dc.getDisplayRotation();
1078 Mockito.doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
1079 Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt());
1080 final boolean[] continued = new boolean[1];
Louis Chang2453d062019-11-19 22:30:48 +08001081 // TODO(display-merge): Remove cast
Evan Rosky69cace42019-09-20 16:28:13 -07001082 Mockito.doAnswer(
1083 invocation -> {
1084 continued[0] = true;
1085 return true;
Louis Chang677921f2019-12-06 16:44:24 +08001086 }).when(dc).updateDisplayOverrideConfigurationLocked();
Evan Rosky69cace42019-09-20 16:28:13 -07001087 final boolean[] called = new boolean[1];
1088 mWm.mDisplayRotationController =
1089 new IDisplayWindowRotationController.Stub() {
1090 @Override
1091 public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
1092 IDisplayWindowRotationCallback callback) {
1093 called[0] = true;
1094
1095 try {
1096 callback.continueRotateDisplay(toRotation, null);
1097 } catch (RemoteException e) {
1098 assertTrue(false);
1099 }
1100 }
1101 };
1102
1103 // kill any existing rotation animation (vestigial from test setup).
1104 dc.setRotationAnimation(null);
1105
1106 mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
1107 assertTrue(called[0]);
1108 waitUntilHandlersIdle();
1109 assertTrue(continued[0]);
1110 }
1111
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001112 @Test
1113 public void testGetOrCreateRootHomeTask_defaultDisplay() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001114 TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001115
1116 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian86d676c2020-03-27 19:34:54 -07001117 ActivityStack homeTask = defaultTaskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001118 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001119 defaultTaskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001120 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001121 assertNull(defaultTaskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001122
Andrii Kulian86d676c2020-03-27 19:34:54 -07001123 assertNotNull(defaultTaskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001124 }
1125
1126 @Test
1127 public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
1128 DisplayContent display = createNewDisplay();
1129 doReturn(true).when(display).supportsSystemDecorations();
1130 doReturn(false).when(display).isUntrustedVirtualDisplay();
1131
1132 // Remove the current home stack if it exists so a new one can be created below.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001133 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Andrii Kulian86d676c2020-03-27 19:34:54 -07001134 ActivityStack homeTask = taskDisplayArea.getRootHomeTask();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001135 if (homeTask != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001136 taskDisplayArea.removeChild(homeTask);
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001137 }
Andrii Kulian86d676c2020-03-27 19:34:54 -07001138 assertNull(taskDisplayArea.getRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001139
Andrii Kulian86d676c2020-03-27 19:34:54 -07001140 assertNotNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001141 }
1142
1143 @Test
1144 public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
1145 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001146 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001147 doReturn(false).when(display).supportsSystemDecorations();
1148
Andrii Kulian86d676c2020-03-27 19:34:54 -07001149 assertNull(taskDisplayArea.getRootHomeTask());
1150 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001151 }
1152
1153 @Test
1154 public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
1155 DisplayContent display = createNewDisplay();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001156 TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001157 doReturn(true).when(display).isUntrustedVirtualDisplay();
1158
Andrii Kulian86d676c2020-03-27 19:34:54 -07001159 assertNull(taskDisplayArea.getRootHomeTask());
1160 assertNull(taskDisplayArea.getOrCreateRootHomeTask());
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001161 }
1162
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001163 private boolean isOptionsPanelAtRight(int displayId) {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001164 return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
Riddle Hsua4d6fa22018-08-11 00:50:39 +08001165 }
1166
Bryce Lee27cec322017-03-21 09:41:37 -07001167 private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
1168 int expectedBaseHeight, int expectedBaseDensity) {
1169 assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
1170 assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight);
1171 assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
1172 }
1173
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001174 private void updateFocusedWindow() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001175 mWm.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001176 }
1177
Riddle Hsu12c05452020-01-09 00:39:52 +08001178 private void performLayout(DisplayContent dc) {
1179 dc.setLayoutNeeded();
1180 dc.performLayout(true /* initial */, false /* updateImeWindows */);
1181 }
1182
Riddle Hsu654a6f92018-07-13 22:59:36 +08001183 /**
1184 * Create DisplayContent that does not update display base/initial values from device to keep
1185 * the values set by test.
1186 */
1187 private DisplayContent createDisplayNoUpdateDisplayInfo() {
Riddle Hsu73f53572019-09-23 23:13:01 +08001188 final DisplayContent displayContent = createNewDisplay();
Riddle Hsu654a6f92018-07-13 22:59:36 +08001189 doNothing().when(displayContent).updateDisplayInfo();
1190 return displayContent;
1191 }
1192
Adrian Roos0f9368c2018-04-08 10:59:08 -07001193 private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
1194 final LinkedList<WindowState> actualWindows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -08001195
1196 // Test forward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001197 mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001198 assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
1199
1200 actualWindows.clear();
Wale Ogunwale34247952017-02-19 11:57:53 -08001201
1202 // Test backward traversal.
Wale Ogunwale11cc5162017-04-25 20:29:13 -07001203 mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
Adrian Roos0f9368c2018-04-08 10:59:08 -07001204 assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
1205 }
1206
1207 private static List<WindowState> reverseList(List<WindowState> list) {
1208 final ArrayList<WindowState> result = new ArrayList<>(list);
1209 Collections.reverse(result);
1210 return result;
Wale Ogunwale34247952017-02-19 11:57:53 -08001211 }
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001212
Arthur Hungbe5ce212018-09-13 18:41:56 +08001213 private void tapOnDisplay(final DisplayContent dc) {
1214 final DisplayMetrics dm = dc.getDisplayMetrics();
1215 final float x = dm.widthPixels / 2;
1216 final float y = dm.heightPixels / 2;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001217 final long downTime = SystemClock.uptimeMillis();
1218 final long eventTime = SystemClock.uptimeMillis() + 100;
Arthur Hungbe5ce212018-09-13 18:41:56 +08001219 // sending ACTION_DOWN
1220 final MotionEvent downEvent = MotionEvent.obtain(
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001221 downTime,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001222 downTime,
1223 MotionEvent.ACTION_DOWN,
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001224 x,
1225 y,
Arthur Hungbe5ce212018-09-13 18:41:56 +08001226 0 /*metaState*/);
1227 downEvent.setDisplayId(dc.getDisplayId());
1228 dc.mTapDetector.onPointerEvent(downEvent);
1229
1230 // sending ACTION_UP
1231 final MotionEvent upEvent = MotionEvent.obtain(
1232 downTime,
1233 eventTime,
1234 MotionEvent.ACTION_UP,
1235 x,
1236 y,
1237 0 /*metaState*/);
1238 upEvent.setDisplayId(dc.getDisplayId());
1239 dc.mTapDetector.onPointerEvent(upEvent);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -07001240 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001241}