blob: 7be05a39cbde5949c5dffb9cde0c4e280e783e16 [file] [log] [blame]
Robert Carr16a4e3c2016-10-28 11:45:22 -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.
Robert Carr16a4e3c2016-10-28 11:45:22 -070015 */
16
17package com.android.server.wm;
18
Evan Rosky0d654cb2019-02-26 10:59:10 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Yunfan Chen279f5582018-12-12 15:24:50 -080020import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Evan Rosky4fb1e912019-03-06 13:54:43 -080021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Issei Suzuki43190bd2018-08-20 17:28:41 +020022import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Brett Chabota26eda92018-07-23 13:08:30 -070023import static android.view.DisplayCutout.fromBoundingRect;
Brett Chabota26eda92018-07-23 13:08:30 -070024import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
25
Wale Ogunwalea733c792019-10-16 21:31:15 -070026import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
27import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
28import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
29
Brett Chabota26eda92018-07-23 13:08:30 -070030import static org.junit.Assert.assertEquals;
Robert Carr16a4e3c2016-10-28 11:45:22 -070031
Bryce Leef3c6a472017-11-14 14:53:06 -080032import android.content.res.Configuration;
Robert Carr16a4e3c2016-10-28 11:45:22 -070033import android.graphics.Rect;
Robert Carr16a4e3c2016-10-28 11:45:22 -070034import android.platform.test.annotations.Presubmit;
Robert Carrfbbde852016-10-18 11:02:28 -070035import android.view.DisplayInfo;
Robert Carr16a4e3c2016-10-28 11:45:22 -070036import android.view.Gravity;
Robert Carr16a4e3c2016-10-28 11:45:22 -070037import android.view.WindowManager;
38
Yunfan Chenc1caf6b2019-04-12 13:58:51 +090039import androidx.test.filters.FlakyTest;
Brett Chabota26eda92018-07-23 13:08:30 -070040import androidx.test.filters.SmallTest;
Robert Carr16a4e3c2016-10-28 11:45:22 -070041
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010042import com.android.server.wm.utils.WmDisplayCutout;
43
Brett Chabota26eda92018-07-23 13:08:30 -070044import org.junit.Before;
45import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080046import org.junit.runner.RunWith;
Evan Rosky0d654cb2019-02-26 10:59:10 -080047import org.mockito.Mockito;
Brett Chabota26eda92018-07-23 13:08:30 -070048
Robert Carr16a4e3c2016-10-28 11:45:22 -070049/**
50 * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
51 *
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070052 * Build/Install/Run:
Riddle Hsu73f53572019-09-23 23:13:01 +080053 * atest WmTests:WindowFrameTests
Robert Carr16a4e3c2016-10-28 11:45:22 -070054 */
55@SmallTest
56@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080057@RunWith(WindowTestRunner.class)
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070058public class WindowFrameTests extends WindowTestsBase {
Robert Carr16a4e3c2016-10-28 11:45:22 -070059
chaviw553b0212018-07-12 13:37:01 -070060 private final Rect mEmptyRect = new Rect();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -070061 private DisplayContent mTestDisplayContent;
Robert Carr16a4e3c2016-10-28 11:45:22 -070062
Robert Carr16a4e3c2016-10-28 11:45:22 -070063 @Before
64 public void setUp() throws Exception {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -070065 DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
66 testDisplayInfo.displayCutout = null;
67 mTestDisplayContent = createNewDisplay(testDisplayInfo);
Robert Carr16a4e3c2016-10-28 11:45:22 -070068 }
69
Kazuki Takisee8d6d442018-07-23 17:40:20 +090070 // Do not use this function directly in the tests below. Instead, use more explicit function
71 // such as assertFlame().
72 private void assertRect(Rect rect, int left, int top, int right, int bottom) {
Robert Carr16a4e3c2016-10-28 11:45:22 -070073 assertEquals(left, rect.left);
74 assertEquals(top, rect.top);
75 assertEquals(right, rect.right);
76 assertEquals(bottom, rect.bottom);
77 }
78
Kazuki Takisee8d6d442018-07-23 17:40:20 +090079 private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -070080 assertRect(w.getContentInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +090081 }
82
83 private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -070084 assertRect(w.getVisibleInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +090085 }
86
87 private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -070088 assertRect(w.getStableInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +090089 }
90
Wale Ogunwale8a1860a2019-06-05 08:57:19 -070091 private void assertFrame(WindowState w, Rect frame) {
92 assertEquals(w.getFrameLw(), frame);
93 }
94
Kazuki Takisee8d6d442018-07-23 17:40:20 +090095 private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
96 assertRect(w.getFrameLw(), left, top, right, bottom);
97 }
98
Evan Rosky70213702019-11-05 10:26:24 -080099 private void assertRelFrame(WindowState w, int left, int top, int right, int bottom) {
100 assertRect(w.getRelativeFrameLw(), left, top, right, bottom);
101 }
102
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900103 private void assertContentFrame(WindowState w, Rect expectedRect) {
104 assertRect(w.getContentFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
105 expectedRect.bottom);
106 }
107
108 private void assertVisibleFrame(WindowState w, Rect expectedRect) {
109 assertRect(w.getVisibleFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
110 expectedRect.bottom);
111 }
112
113 private void assertStableFrame(WindowState w, Rect expectedRect) {
114 assertRect(w.getStableFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
115 expectedRect.bottom);
116 }
117
Wale Ogunwalea733c792019-10-16 21:31:15 -0700118 private void assertPolicyCrop(WindowState w, int left, int top, int right, int bottom) {
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900119 Rect policyCrop = new Rect();
120 w.calculatePolicyCrop(policyCrop);
121 assertRect(policyCrop, left, top, right, bottom);
122 }
123
Robert Carr16a4e3c2016-10-28 11:45:22 -0700124 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700125 public void testLayoutInFullscreenTaskInsets() {
126 // fullscreen task doesn't use bounds for computeFrame
Wale Ogunwalea733c792019-10-16 21:31:15 -0700127 WindowState w = createWindow();
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700128 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
129
130 final int bottomContentInset = 100;
131 final int topContentInset = 50;
132 final int bottomVisibleInset = 30;
133 final int topVisibleInset = 70;
134 final int leftStableInset = 20;
135 final int rightStableInset = 90;
136
137 // With no insets or system decor all the frames incoming from PhoneWindowManager
138 // are identical.
139 final Rect pf = new Rect(0, 0, 1000, 1000);
140 final Rect df = pf;
141 final Rect of = df;
142 final Rect cf = new Rect(pf);
143 // Produce some insets
144 cf.top += 50;
145 cf.bottom -= 100;
146 final Rect vf = new Rect(pf);
147 vf.top += topVisibleInset;
148 vf.bottom -= bottomVisibleInset;
149 final Rect sf = new Rect(pf);
150 sf.left += leftStableInset;
151 sf.right -= rightStableInset;
152
153 final Rect dcf = pf;
154 // When mFrame extends past cf, the content insets are
155 // the difference between mFrame and ContentFrame. Visible
156 // and stable frames work the same way.
Jorim Jaggif081f062019-10-24 16:24:54 +0200157 w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf);
chaviw1454b392018-08-06 09:54:04 -0700158 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900159 assertFrame(w, 0, 0, 1000, 1000);
Evan Rosky70213702019-11-05 10:26:24 -0800160 assertRelFrame(w, 0, 0, 1000, 1000);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900161 assertContentInset(w, 0, topContentInset, 0, bottomContentInset);
162 assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset);
163 assertStableInset(w, leftStableInset, 0, rightStableInset, 0);
164 assertContentFrame(w, cf);
165 assertVisibleFrame(w, vf);
166 assertStableFrame(w, sf);
chaviw492139a2018-07-16 16:07:35 -0700167 // On the other hand getFrame() doesn't extend past cf we won't get any insets
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700168 w.mAttrs.x = 100;
169 w.mAttrs.y = 100;
170 w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
171 w.mRequestedWidth = 100;
172 w.mRequestedHeight = 100;
chaviw1454b392018-08-06 09:54:04 -0700173 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900174 assertFrame(w, 100, 100, 200, 200);
Evan Rosky70213702019-11-05 10:26:24 -0800175 assertRelFrame(w, 100, 100, 200, 200);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900176 assertContentInset(w, 0, 0, 0, 0);
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700177 // In this case the frames are shrunk to the window frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900178 assertContentFrame(w, w.getFrameLw());
179 assertVisibleFrame(w, w.getFrameLw());
180 assertStableFrame(w, w.getFrameLw());
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700181 }
182
183 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700184 public void testLayoutInFullscreenTaskNoInsets() {
185 // fullscreen task doesn't use bounds for computeFrame
Wale Ogunwalea733c792019-10-16 21:31:15 -0700186 WindowState w = createWindow();
Robert Carr16a4e3c2016-10-28 11:45:22 -0700187 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
188
189 // With no insets or system decor all the frames incoming from PhoneWindowManager
190 // are identical.
191 final Rect pf = new Rect(0, 0, 1000, 1000);
192
193 // Here the window has FILL_PARENT, FILL_PARENT
194 // so we expect it to fill the entire available frame.
Jorim Jaggif081f062019-10-24 16:24:54 +0200195 w.getWindowFrames().setFrames(pf, pf, pf, pf, pf, pf);
chaviw1454b392018-08-06 09:54:04 -0700196 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900197 assertFrame(w, 0, 0, 1000, 1000);
Evan Rosky70213702019-11-05 10:26:24 -0800198 assertRelFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700199
200 // It can select various widths and heights within the bounds.
201 // Strangely the window attribute width is ignored for normal windows
202 // and we use mRequestedWidth/mRequestedHeight
203 w.mAttrs.width = 300;
204 w.mAttrs.height = 300;
chaviw1454b392018-08-06 09:54:04 -0700205 w.computeFrameLw();
Robert Carr16a4e3c2016-10-28 11:45:22 -0700206 // Explicit width and height without requested width/height
207 // gets us nothing.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900208 assertFrame(w, 0, 0, 0, 0);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700209
210 w.mRequestedWidth = 300;
211 w.mRequestedHeight = 300;
chaviw1454b392018-08-06 09:54:04 -0700212 w.computeFrameLw();
Robert Carr16a4e3c2016-10-28 11:45:22 -0700213 // With requestedWidth/Height we can freely choose our size within the
214 // parent bounds.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900215 assertFrame(w, 0, 0, 300, 300);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700216
217 // With FLAG_SCALED though, requestedWidth/height is used to control
218 // the unscaled surface size, and mAttrs.width/height becomes the
219 // layout controller.
220 w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED;
221 w.mRequestedHeight = -1;
222 w.mRequestedWidth = -1;
223 w.mAttrs.width = 100;
224 w.mAttrs.height = 100;
chaviw1454b392018-08-06 09:54:04 -0700225 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900226 assertFrame(w, 0, 0, 100, 100);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700227 w.mAttrs.flags = 0;
228
229 // But sizes too large will be clipped to the containing frame
230 w.mRequestedWidth = 1200;
231 w.mRequestedHeight = 1200;
chaviw1454b392018-08-06 09:54:04 -0700232 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900233 assertFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700234
235 // Before they are clipped though windows will be shifted
236 w.mAttrs.x = 300;
237 w.mAttrs.y = 300;
238 w.mRequestedWidth = 1000;
239 w.mRequestedHeight = 1000;
chaviw1454b392018-08-06 09:54:04 -0700240 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900241 assertFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700242
243 // If there is room to move around in the parent frame the window will be shifted according
244 // to gravity.
245 w.mAttrs.x = 0;
246 w.mAttrs.y = 0;
247 w.mRequestedWidth = 300;
248 w.mRequestedHeight = 300;
249 w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
chaviw1454b392018-08-06 09:54:04 -0700250 w.computeFrameLw();
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +0900251 assertFrame(w, 700, 0, 1000, 300);
Evan Rosky70213702019-11-05 10:26:24 -0800252 assertRelFrame(w, 700, 0, 1000, 300);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700253 w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
chaviw1454b392018-08-06 09:54:04 -0700254 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900255 assertFrame(w, 700, 700, 1000, 1000);
Evan Rosky70213702019-11-05 10:26:24 -0800256 assertRelFrame(w, 700, 700, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700257 // Window specified x and y are interpreted as offsets in the opposite
258 // direction of gravity
259 w.mAttrs.x = 100;
260 w.mAttrs.y = 100;
chaviw1454b392018-08-06 09:54:04 -0700261 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900262 assertFrame(w, 600, 600, 900, 900);
Evan Rosky70213702019-11-05 10:26:24 -0800263 assertRelFrame(w, 600, 600, 900, 900);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700264 }
265
Robert Carr15dd7ef2016-11-03 14:26:58 -0700266 @Test
267 public void testLayoutNonfullscreenTask() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200268 removeGlobalMinSizeRestriction();
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700269 final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700270 final int logicalWidth = displayInfo.logicalWidth;
271 final int logicalHeight = displayInfo.logicalHeight;
272
Wale Ogunwalea733c792019-10-16 21:31:15 -0700273 final Rect taskBounds = new Rect(
274 logicalWidth / 4, logicalHeight / 4, logicalWidth / 4 * 3, logicalHeight / 4 * 3);
275 WindowState w = createWindow();
Evan Rosky4fb1e912019-03-06 13:54:43 -0800276 final Task task = w.getTask();
277 // Use split-screen because it is non-fullscreen, but also not floating
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200278 task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
279 task.setBounds(taskBounds);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700280 // The bounds we are requesting might be different from what the system resolved based on
281 // other factors.
282 final Rect resolvedTaskBounds = task.getBounds();
Robert Carr15dd7ef2016-11-03 14:26:58 -0700283 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
284
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700285 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
chaviw1454b392018-08-06 09:54:04 -0700286 final WindowFrames windowFrames = w.getWindowFrames();
Jorim Jaggif081f062019-10-24 16:24:54 +0200287 windowFrames.setFrames(pf, pf, pf, pf, pf, pf);
chaviw1454b392018-08-06 09:54:04 -0700288 w.computeFrameLw();
Robert Carr15dd7ef2016-11-03 14:26:58 -0700289 // For non fullscreen tasks the containing frame is based off the
290 // task bounds not the parent frame.
Wale Ogunwalea733c792019-10-16 21:31:15 -0700291 assertEquals(resolvedTaskBounds, w.getFrameLw());
Evan Rosky70213702019-11-05 10:26:24 -0800292 assertEquals(0, w.getRelativeFrameLw().left);
293 assertEquals(0, w.getRelativeFrameLw().top);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700294 assertContentFrame(w, resolvedTaskBounds);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900295 assertContentInset(w, 0, 0, 0, 0);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700296
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700297 pf.set(0, 0, logicalWidth, logicalHeight);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700298 // We still produce insets against the containing frame the same way.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700299 final int cfRight = logicalWidth / 2;
300 final int cfBottom = logicalHeight / 2;
301 final Rect cf = new Rect(0, 0, cfRight, cfBottom);
Jorim Jaggif081f062019-10-24 16:24:54 +0200302 windowFrames.setFrames(pf, pf, cf, cf, pf, cf);
chaviw1454b392018-08-06 09:54:04 -0700303 w.computeFrameLw();
Wale Ogunwalea733c792019-10-16 21:31:15 -0700304 assertEquals(resolvedTaskBounds, w.getFrameLw());
Evan Rosky70213702019-11-05 10:26:24 -0800305 assertEquals(0, w.getRelativeFrameLw().left);
306 assertEquals(0, w.getRelativeFrameLw().top);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700307 int contentInsetRight = resolvedTaskBounds.right - cfRight;
308 int contentInsetBottom = resolvedTaskBounds.bottom - cfBottom;
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900309 assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700310 assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top,
311 resolvedTaskBounds.right - contentInsetRight,
312 resolvedTaskBounds.bottom - contentInsetBottom));
Robert Carr15dd7ef2016-11-03 14:26:58 -0700313
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700314 pf.set(0, 0, logicalWidth, logicalHeight);
Evan Roskyed6767f2018-10-26 17:21:06 -0700315 // If we set displayed bounds, the insets will be computed with the main task bounds
316 // but the frame will be positioned according to the displayed bounds.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700317 final int insetLeft = logicalWidth / 5;
318 final int insetTop = logicalHeight / 5;
Wale Ogunwalea733c792019-10-16 21:31:15 -0700319 final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left);
320 final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200321 task.setOverrideDisplayedBounds(resolvedTaskBounds);
322 task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
Jorim Jaggif081f062019-10-24 16:24:54 +0200323 windowFrames.setFrames(pf, pf, cf, cf, pf, cf);
chaviw1454b392018-08-06 09:54:04 -0700324 w.computeFrameLw();
Wale Ogunwalea733c792019-10-16 21:31:15 -0700325 assertEquals(resolvedTaskBounds, w.getFrameLw());
Evan Rosky70213702019-11-05 10:26:24 -0800326 assertEquals(0, w.getRelativeFrameLw().left);
327 assertEquals(0, w.getRelativeFrameLw().top);
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700328 contentInsetRight = insetRight - cfRight;
329 contentInsetBottom = insetBottom - cfBottom;
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900330 assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700331 assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top,
332 resolvedTaskBounds.right - contentInsetRight,
333 resolvedTaskBounds.bottom - contentInsetBottom));
Robert Carr15dd7ef2016-11-03 14:26:58 -0700334 }
335
Robert Carrfbbde852016-10-18 11:02:28 -0700336 @Test
Yunfan Chenc1caf6b2019-04-12 13:58:51 +0900337 @FlakyTest(bugId = 130388666)
Robert Carrfbbde852016-10-18 11:02:28 -0700338 public void testCalculatePolicyCrop() {
Wale Ogunwalea733c792019-10-16 21:31:15 -0700339 final WindowState w = createWindow();
Robert Carrfbbde852016-10-18 11:02:28 -0700340 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
341
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700342 final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
343 final int logicalWidth = displayInfo.logicalWidth;
344 final int logicalHeight = displayInfo.logicalHeight;
345 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
Robert Carrfbbde852016-10-18 11:02:28 -0700346 final Rect df = pf;
Robert Carrfbbde852016-10-18 11:02:28 -0700347 final Rect cf = new Rect(pf);
348 // Produce some insets
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700349 cf.top += displayInfo.logicalWidth / 10;
350 cf.bottom -= displayInfo.logicalWidth / 5;
Robert Carrfbbde852016-10-18 11:02:28 -0700351 final Rect vf = cf;
352 final Rect sf = vf;
353 // We use a decor content frame with insets to produce cropping.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900354 Rect dcf = new Rect(cf);
Robert Carrfbbde852016-10-18 11:02:28 -0700355
chaviw1454b392018-08-06 09:54:04 -0700356 final WindowFrames windowFrames = w.getWindowFrames();
Jorim Jaggif081f062019-10-24 16:24:54 +0200357 windowFrames.setFrames(pf, df, cf, vf, dcf, sf);
chaviw1454b392018-08-06 09:54:04 -0700358 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900359 assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom);
chaviw0eac1682017-11-02 11:27:51 -0700360
chaviw553b0212018-07-12 13:37:01 -0700361 windowFrames.mDecorFrame.setEmpty();
Robert Carrfbbde852016-10-18 11:02:28 -0700362 // Likewise with no decor frame we would get no crop
chaviw1454b392018-08-06 09:54:04 -0700363 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900364 assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight);
Robert Carrfbbde852016-10-18 11:02:28 -0700365
366 // Now we set up a window which doesn't fill the entire decor frame.
367 // Normally it would be cropped to it's frame but in the case of docked resizing
368 // we need to account for the fact the windows surface will be made
369 // fullscreen and thus also make the crop fullscreen.
chaviw553b0212018-07-12 13:37:01 -0700370
Jorim Jaggif081f062019-10-24 16:24:54 +0200371 windowFrames.setFrames(pf, pf, pf, pf, pf, pf);
Robert Carrfbbde852016-10-18 11:02:28 -0700372 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700373 w.mAttrs.width = logicalWidth / 2;
374 w.mAttrs.height = logicalHeight / 2;
375 w.mRequestedWidth = logicalWidth / 2;
376 w.mRequestedHeight = logicalHeight / 2;
chaviw1454b392018-08-06 09:54:04 -0700377 w.computeFrameLw();
Robert Carrfbbde852016-10-18 11:02:28 -0700378
Robert Carrfbbde852016-10-18 11:02:28 -0700379 // Normally the crop is shrunk from the decor frame
380 // to the computed window frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900381 assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2);
Robert Carrfbbde852016-10-18 11:02:28 -0700382
Wale Ogunwalea733c792019-10-16 21:31:15 -0700383 doReturn(true).when(w).isDockedResizing();
Robert Carr186d9de2017-02-09 12:41:03 -0800384 // But if we are docked resizing it won't be, however we will still be
385 // shrunk to the decor frame and the display.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900386 assertPolicyCrop(w, 0, 0,
Robert Carr186d9de2017-02-09 12:41:03 -0800387 Math.min(pf.width(), displayInfo.logicalWidth),
388 Math.min(pf.height(), displayInfo.logicalHeight));
Robert Carrfbbde852016-10-18 11:02:28 -0700389 }
390
Andrii Kulianc24f3732017-08-08 19:35:17 -0700391 @Test
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700392 @FlakyTest(bugId = 137879065)
Andrii Kulianc24f3732017-08-08 19:35:17 -0700393 public void testLayoutLetterboxedWindow() {
394 // First verify task behavior in multi-window mode.
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700395 final DisplayInfo displayInfo = mTestDisplayContent.getDisplayInfo();
Andrii Kulianc24f3732017-08-08 19:35:17 -0700396 final int logicalWidth = displayInfo.logicalWidth;
397 final int logicalHeight = displayInfo.logicalHeight;
398
399 final int taskLeft = logicalWidth / 5;
400 final int taskTop = logicalHeight / 5;
401 final int taskRight = logicalWidth / 4 * 3;
402 final int taskBottom = logicalHeight / 4 * 3;
403 final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700404 WindowState w = createWindow();
Evan Rosky4fb1e912019-03-06 13:54:43 -0800405 final Task task = w.getTask();
406 // Use split-screen because it is non-fullscreen, but also not floating
407 task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
408 task.setBounds(taskBounds);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700409 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
410
411 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
chaviw1454b392018-08-06 09:54:04 -0700412 final WindowFrames windowFrames = w.getWindowFrames();
Jorim Jaggif081f062019-10-24 16:24:54 +0200413 windowFrames.setFrames(pf, pf, pf, pf, pf, pf);
chaviw1454b392018-08-06 09:54:04 -0700414 w.computeFrameLw();
Andrii Kulianc24f3732017-08-08 19:35:17 -0700415 // For non fullscreen tasks the containing frame is based off the
416 // task bounds not the parent frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900417 assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
418 assertContentFrame(w, taskBounds);
419 assertContentInset(w, 0, 0, 0, 0);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700420
421 // Now simulate switch to fullscreen for letterboxed app.
422 final int xInset = logicalWidth / 10;
Riddle Hsub398da32019-01-21 21:48:16 +0800423 final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700424 Configuration config = new Configuration(w.mActivityRecord.getRequestedOverrideConfiguration());
Bryce Leef3c6a472017-11-14 14:53:06 -0800425 config.windowConfiguration.setBounds(cf);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700426 config.windowConfiguration.setAppBounds(cf);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700427 w.mActivityRecord.onRequestedOverrideConfigurationChanged(config);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700428 pf.set(0, 0, logicalWidth, logicalHeight);
Evan Rosky4fb1e912019-03-06 13:54:43 -0800429 task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
430 task.setBounds(null);
Jorim Jaggif081f062019-10-24 16:24:54 +0200431 windowFrames.setFrames(pf, pf, cf, cf, pf, cf);
chaviw1454b392018-08-06 09:54:04 -0700432 w.computeFrameLw();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700433 assertFrame(w, cf);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900434 assertContentFrame(w, cf);
435 assertContentInset(w, 0, 0, 0, 0);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700436 }
437
Adrian Roos5c6b6222017-11-07 17:36:10 +0100438 @Test
Yunfan Chenc1caf6b2019-04-12 13:58:51 +0900439 @FlakyTest(bugId = 130388666)
Adrian Roos5c6b6222017-11-07 17:36:10 +0100440 public void testDisplayCutout() {
441 // Regular fullscreen task and window
Wale Ogunwalea733c792019-10-16 21:31:15 -0700442 WindowState w = createWindow();
Adrian Roos5c6b6222017-11-07 17:36:10 +0100443 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
444
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100445 final Rect pf = new Rect(0, 0, 1000, 2000);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100446 // Create a display cutout of size 50x50, aligned top-center
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100447 final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200448 fromBoundingRect(500, 0, 550, 50, BOUNDS_POSITION_TOP),
449 pf.width(), pf.height());
Adrian Roos5c6b6222017-11-07 17:36:10 +0100450
chaviw1454b392018-08-06 09:54:04 -0700451 final WindowFrames windowFrames = w.getWindowFrames();
Jorim Jaggif081f062019-10-24 16:24:54 +0200452 windowFrames.setFrames(pf, pf, pf, pf, pf, pf);
chaviwcdba9a42018-07-19 11:36:42 -0700453 windowFrames.setDisplayCutout(cutout);
chaviw1454b392018-08-06 09:54:04 -0700454 w.computeFrameLw();
Adrian Roos5c6b6222017-11-07 17:36:10 +0100455
chaviwcdba9a42018-07-19 11:36:42 -0700456 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
457 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
458 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0);
459 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100460 }
461
Jorim Jaggibae2b152018-04-18 17:27:27 +0200462 @Test
Yunfan Chenc1caf6b2019-04-12 13:58:51 +0900463 @FlakyTest(bugId = 130388666)
Evan Roskyed6767f2018-10-26 17:21:06 -0700464 public void testDisplayCutout_tempDisplayedBounds() {
Jorim Jaggibae2b152018-04-18 17:27:27 +0200465 // Regular fullscreen task and window
Wale Ogunwalea733c792019-10-16 21:31:15 -0700466 WindowState w = createWindow();
Evan Rosky4fb1e912019-03-06 13:54:43 -0800467 final Task task = w.getTask();
468 task.setBounds(new Rect(0, 0, 1000, 2000));
Evan Roskyed6767f2018-10-26 17:21:06 -0700469 task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500));
Jorim Jaggibae2b152018-04-18 17:27:27 +0200470 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
471
472 final Rect pf = new Rect(0, -500, 1000, 1500);
473 // Create a display cutout of size 50x50, aligned top-center
474 final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200475 fromBoundingRect(500, 0, 550, 50, BOUNDS_POSITION_TOP),
476 pf.width(), pf.height());
Jorim Jaggibae2b152018-04-18 17:27:27 +0200477
chaviw1454b392018-08-06 09:54:04 -0700478 final WindowFrames windowFrames = w.getWindowFrames();
Jorim Jaggif081f062019-10-24 16:24:54 +0200479 windowFrames.setFrames(pf, pf, pf, pf, pf, pf);
chaviwcdba9a42018-07-19 11:36:42 -0700480 windowFrames.setDisplayCutout(cutout);
chaviw1454b392018-08-06 09:54:04 -0700481 w.computeFrameLw();
Jorim Jaggibae2b152018-04-18 17:27:27 +0200482
chaviwcdba9a42018-07-19 11:36:42 -0700483 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
484 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
485 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0);
486 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0);
Jorim Jaggibae2b152018-04-18 17:27:27 +0200487 }
488
Evan Rosky0d654cb2019-02-26 10:59:10 -0800489 @Test
490 public void testFreeformContentInsets() {
Wale Ogunwalea733c792019-10-16 21:31:15 -0700491 removeGlobalMinSizeRestriction();
Evan Rosky0d654cb2019-02-26 10:59:10 -0800492 // fullscreen task doesn't use bounds for computeFrame
Wale Ogunwalea733c792019-10-16 21:31:15 -0700493 WindowState w = createWindow();
Evan Rosky4fb1e912019-03-06 13:54:43 -0800494 final Task task = w.getTask();
Evan Rosky0d654cb2019-02-26 10:59:10 -0800495 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200496 task.setWindowingMode(WINDOWING_MODE_FREEFORM);
Evan Rosky0d654cb2019-02-26 10:59:10 -0800497
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700498 DisplayContent dc = mTestDisplayContent;
Evan Rosky0d654cb2019-02-26 10:59:10 -0800499 dc.mInputMethodTarget = w;
500 WindowState mockIme = mock(WindowState.class);
501 Mockito.doReturn(true).when(mockIme).isVisibleNow();
502 dc.mInputMethodWindow = mockIme;
503
504 // With no insets or system decor all the frames incoming from PhoneWindowManager
505 // are identical.
506 final Rect pf = new Rect(0, 0, 1000, 800);
507 final Rect df = pf;
508 final Rect of = df;
509 final Rect cf = new Rect(pf);
510 cf.bottom -= 400;
511 final Rect vf = new Rect(cf);
512 final Rect sf = new Rect(pf);
513 final Rect dcf = pf;
514
515 // First check that it only gets moved up enough to show window.
516 final Rect winRect = new Rect(200, 200, 300, 500);
517
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200518 task.setBounds(winRect);
Jorim Jaggif081f062019-10-24 16:24:54 +0200519 w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf);
Evan Rosky0d654cb2019-02-26 10:59:10 -0800520 w.computeFrameLw();
521
522 final Rect expected = new Rect(winRect.left, cf.bottom - winRect.height(),
523 winRect.right, cf.bottom);
524 assertEquals(expected, w.getFrameLw());
525 assertEquals(expected, w.getContentFrameLw());
526 assertEquals(expected, w.getVisibleFrameLw());
527
528 // Now check that it won't get moved beyond the top and then has appropriate insets
529 winRect.bottom = 600;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200530 task.setBounds(winRect);
Evan Rosky0d654cb2019-02-26 10:59:10 -0800531 w.setBounds(winRect);
Jorim Jaggif081f062019-10-24 16:24:54 +0200532 w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf);
Evan Rosky0d654cb2019-02-26 10:59:10 -0800533 w.computeFrameLw();
534
535 assertFrame(w, winRect.left, 0, winRect.right, winRect.height());
536 expected.top = 0;
537 expected.bottom = cf.bottom;
538 assertContentFrame(w, expected);
539 assertVisibleFrame(w, expected);
540
541 // Check that it's moved back without ime insets
Jorim Jaggif081f062019-10-24 16:24:54 +0200542 w.getWindowFrames().setFrames(pf, df, pf, pf, dcf, sf);
Evan Rosky0d654cb2019-02-26 10:59:10 -0800543 w.computeFrameLw();
544 assertEquals(winRect, w.getFrameLw());
545 }
546
Wale Ogunwalea733c792019-10-16 21:31:15 -0700547 private WindowState createWindow() {
548 final WindowState ws = createWindow(null, TYPE_APPLICATION, mTestDisplayContent, "WindowFrameTests");
549 spyOn(ws);
Evan Rosky4fb1e912019-03-06 13:54:43 -0800550 return ws;
Robert Carr16a4e3c2016-10-28 11:45:22 -0700551 }
Robert Carr16a4e3c2016-10-28 11:45:22 -0700552}