blob: 61c1d39e420fc56ed685dd21a61dcdf09046f42b [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
Yunfan Chen279f5582018-12-12 15:24:50 -080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Issei Suzuki43190bd2018-08-20 17:28:41 +020021import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
Brett Chabota26eda92018-07-23 13:08:30 -070022import static android.view.DisplayCutout.fromBoundingRect;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070023import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
Brett Chabota26eda92018-07-23 13:08:30 -070024import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
25
26import static org.junit.Assert.assertEquals;
Yunfan Chen279f5582018-12-12 15:24:50 -080027import static org.mockito.Mockito.mock;
Robert Carr16a4e3c2016-10-28 11:45:22 -070028
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010029import android.app.ActivityManager.TaskDescription;
Bryce Leef3c6a472017-11-14 14:53:06 -080030import android.content.res.Configuration;
Robert Carr16a4e3c2016-10-28 11:45:22 -070031import android.graphics.Rect;
Robert Carr16a4e3c2016-10-28 11:45:22 -070032import android.platform.test.annotations.Presubmit;
Robert Carrfbbde852016-10-18 11:02:28 -070033import android.view.DisplayInfo;
Robert Carr16a4e3c2016-10-28 11:45:22 -070034import android.view.Gravity;
35import android.view.IWindow;
36import android.view.WindowManager;
37
Brett Chabota26eda92018-07-23 13:08:30 -070038import androidx.test.filters.SmallTest;
Robert Carr16a4e3c2016-10-28 11:45:22 -070039
Adrian Roos6a4fa0e2018-03-05 19:50:16 +010040import com.android.server.wm.utils.WmDisplayCutout;
41
Brett Chabota26eda92018-07-23 13:08:30 -070042import org.junit.Before;
43import org.junit.Test;
Brett Chabota26eda92018-07-23 13:08:30 -070044
Robert Carr16a4e3c2016-10-28 11:45:22 -070045/**
46 * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
47 *
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070048 * Build/Install/Run:
49 * atest FrameworksServicesTests:WindowFrameTests
Robert Carr16a4e3c2016-10-28 11:45:22 -070050 */
51@SmallTest
52@Presubmit
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070053public class WindowFrameTests extends WindowTestsBase {
Robert Carr16a4e3c2016-10-28 11:45:22 -070054
Robert Carr16a4e3c2016-10-28 11:45:22 -070055 private WindowToken mWindowToken;
56 private final IWindow mIWindow = new TestIWindow();
chaviw553b0212018-07-12 13:37:01 -070057 private final Rect mEmptyRect = new Rect();
Robert Carr16a4e3c2016-10-28 11:45:22 -070058
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070059 static class WindowStateWithTask extends WindowState {
Robert Carr16a4e3c2016-10-28 11:45:22 -070060 final Task mTask;
Robert Carrfbbde852016-10-18 11:02:28 -070061 boolean mDockedResizingForTest = false;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070062 WindowStateWithTask(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
63 WindowManager.LayoutParams attrs, Task t) {
Yunfan Chen279f5582018-12-12 15:24:50 -080064 super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0,
Wale Ogunwale5cd907d2017-01-26 14:14:08 -080065 false /* ownerCanAddInternalSystemWindow */);
Robert Carr16a4e3c2016-10-28 11:45:22 -070066 mTask = t;
67 }
68
69 @Override
70 Task getTask() {
71 return mTask;
72 }
Robert Carrfbbde852016-10-18 11:02:28 -070073
74 @Override
75 boolean isDockedResizing() {
76 return mDockedResizingForTest;
77 }
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070078 }
Robert Carr16a4e3c2016-10-28 11:45:22 -070079
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070080 private static class TaskWithBounds extends Task {
Robert Carr16a4e3c2016-10-28 11:45:22 -070081 final Rect mBounds;
Evan Roskyed6767f2018-10-26 17:21:06 -070082 final Rect mOverrideDisplayedBounds = new Rect();
Robert Carr15dd7ef2016-11-03 14:26:58 -070083 boolean mFullscreenForTest = true;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070084
85 TaskWithBounds(TaskStack stack, WindowManagerService wm, Rect bounds) {
86 super(0, stack, 0, wm, 0, false, new TaskDescription(), null);
Robert Carr16a4e3c2016-10-28 11:45:22 -070087 mBounds = bounds;
Bryce Leef3c6a472017-11-14 14:53:06 -080088 setBounds(bounds);
Robert Carr16a4e3c2016-10-28 11:45:22 -070089 }
Bryce Leef3c6a472017-11-14 14:53:06 -080090
Robert Carr16a4e3c2016-10-28 11:45:22 -070091 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -080092 public Rect getBounds() {
93 return mBounds;
94 }
95
96 @Override
97 public void getBounds(Rect out) {
98 out.set(mBounds);
99 }
100
101 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700102 public void getRequestedOverrideBounds(Rect outBounds) {
Robert Carr16a4e3c2016-10-28 11:45:22 -0700103 outBounds.set(mBounds);
104 }
105 @Override
Evan Roskyed6767f2018-10-26 17:21:06 -0700106 Rect getOverrideDisplayedBounds() {
107 return mOverrideDisplayedBounds;
Robert Carr16a4e3c2016-10-28 11:45:22 -0700108 }
109 @Override
110 boolean isFullscreen() {
Robert Carr15dd7ef2016-11-03 14:26:58 -0700111 return mFullscreenForTest;
Robert Carr16a4e3c2016-10-28 11:45:22 -0700112 }
113 }
114
115 TaskStack mStubStack;
116
117 @Before
118 public void setUp() throws Exception {
Yunfan Chen279f5582018-12-12 15:24:50 -0800119 mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
120 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Tadashi G. Takaokad7aa79a2019-02-08 17:42:37 +0900121 mStubStack = mock(TaskStack.class);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700122 }
123
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900124 // Do not use this function directly in the tests below. Instead, use more explicit function
125 // such as assertFlame().
126 private void assertRect(Rect rect, int left, int top, int right, int bottom) {
Robert Carr16a4e3c2016-10-28 11:45:22 -0700127 assertEquals(left, rect.left);
128 assertEquals(top, rect.top);
129 assertEquals(right, rect.right);
130 assertEquals(bottom, rect.bottom);
131 }
132
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900133 private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -0700134 assertRect(w.getContentInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900135 }
136
137 private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -0700138 assertRect(w.getVisibleInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900139 }
140
141 private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
chaviw9c81e632018-07-31 11:17:52 -0700142 assertRect(w.getStableInsets(), left, top, right, bottom);
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900143 }
144
145 private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
146 assertRect(w.getFrameLw(), left, top, right, bottom);
147 }
148
149 private void assertContentFrame(WindowState w, Rect expectedRect) {
150 assertRect(w.getContentFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
151 expectedRect.bottom);
152 }
153
154 private void assertVisibleFrame(WindowState w, Rect expectedRect) {
155 assertRect(w.getVisibleFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
156 expectedRect.bottom);
157 }
158
159 private void assertStableFrame(WindowState w, Rect expectedRect) {
160 assertRect(w.getStableFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
161 expectedRect.bottom);
162 }
163
164 private void assertPolicyCrop(WindowStateWithTask w, int left, int top, int right, int bottom) {
165 Rect policyCrop = new Rect();
166 w.calculatePolicyCrop(policyCrop);
167 assertRect(policyCrop, left, top, right, bottom);
168 }
169
Robert Carr16a4e3c2016-10-28 11:45:22 -0700170 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700171 public void testLayoutInFullscreenTaskInsets() {
172 // fullscreen task doesn't use bounds for computeFrame
173 final Task task = new TaskWithBounds(mStubStack, mWm, null);
174 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700175 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
176
177 final int bottomContentInset = 100;
178 final int topContentInset = 50;
179 final int bottomVisibleInset = 30;
180 final int topVisibleInset = 70;
181 final int leftStableInset = 20;
182 final int rightStableInset = 90;
183
184 // With no insets or system decor all the frames incoming from PhoneWindowManager
185 // are identical.
186 final Rect pf = new Rect(0, 0, 1000, 1000);
187 final Rect df = pf;
188 final Rect of = df;
189 final Rect cf = new Rect(pf);
190 // Produce some insets
191 cf.top += 50;
192 cf.bottom -= 100;
193 final Rect vf = new Rect(pf);
194 vf.top += topVisibleInset;
195 vf.bottom -= bottomVisibleInset;
196 final Rect sf = new Rect(pf);
197 sf.left += leftStableInset;
198 sf.right -= rightStableInset;
199
200 final Rect dcf = pf;
201 // When mFrame extends past cf, the content insets are
202 // the difference between mFrame and ContentFrame. Visible
203 // and stable frames work the same way.
chaviw1454b392018-08-06 09:54:04 -0700204 w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
205 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900206 assertFrame(w, 0, 0, 1000, 1000);
207 assertContentInset(w, 0, topContentInset, 0, bottomContentInset);
208 assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset);
209 assertStableInset(w, leftStableInset, 0, rightStableInset, 0);
210 assertContentFrame(w, cf);
211 assertVisibleFrame(w, vf);
212 assertStableFrame(w, sf);
chaviw492139a2018-07-16 16:07:35 -0700213 // On the other hand getFrame() doesn't extend past cf we won't get any insets
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700214 w.mAttrs.x = 100;
215 w.mAttrs.y = 100;
216 w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
217 w.mRequestedWidth = 100;
218 w.mRequestedHeight = 100;
chaviw1454b392018-08-06 09:54:04 -0700219 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900220 assertFrame(w, 100, 100, 200, 200);
221 assertContentInset(w, 0, 0, 0, 0);
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700222 // In this case the frames are shrunk to the window frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900223 assertContentFrame(w, w.getFrameLw());
224 assertVisibleFrame(w, w.getFrameLw());
225 assertStableFrame(w, w.getFrameLw());
Robert Carre4ee8f8a2016-10-31 12:40:15 -0700226 }
227
228 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700229 public void testLayoutInFullscreenTaskNoInsets() {
230 // fullscreen task doesn't use bounds for computeFrame
231 final Task task = new TaskWithBounds(mStubStack, mWm, null);
232 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700233 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
234
235 // With no insets or system decor all the frames incoming from PhoneWindowManager
236 // are identical.
237 final Rect pf = new Rect(0, 0, 1000, 1000);
238
239 // Here the window has FILL_PARENT, FILL_PARENT
240 // so we expect it to fill the entire available frame.
chaviw1454b392018-08-06 09:54:04 -0700241 w.getWindowFrames().setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
242 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900243 assertFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700244
245 // It can select various widths and heights within the bounds.
246 // Strangely the window attribute width is ignored for normal windows
247 // and we use mRequestedWidth/mRequestedHeight
248 w.mAttrs.width = 300;
249 w.mAttrs.height = 300;
chaviw1454b392018-08-06 09:54:04 -0700250 w.computeFrameLw();
Robert Carr16a4e3c2016-10-28 11:45:22 -0700251 // Explicit width and height without requested width/height
252 // gets us nothing.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900253 assertFrame(w, 0, 0, 0, 0);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700254
255 w.mRequestedWidth = 300;
256 w.mRequestedHeight = 300;
chaviw1454b392018-08-06 09:54:04 -0700257 w.computeFrameLw();
Robert Carr16a4e3c2016-10-28 11:45:22 -0700258 // With requestedWidth/Height we can freely choose our size within the
259 // parent bounds.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900260 assertFrame(w, 0, 0, 300, 300);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700261
262 // With FLAG_SCALED though, requestedWidth/height is used to control
263 // the unscaled surface size, and mAttrs.width/height becomes the
264 // layout controller.
265 w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED;
266 w.mRequestedHeight = -1;
267 w.mRequestedWidth = -1;
268 w.mAttrs.width = 100;
269 w.mAttrs.height = 100;
chaviw1454b392018-08-06 09:54:04 -0700270 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900271 assertFrame(w, 0, 0, 100, 100);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700272 w.mAttrs.flags = 0;
273
274 // But sizes too large will be clipped to the containing frame
275 w.mRequestedWidth = 1200;
276 w.mRequestedHeight = 1200;
chaviw1454b392018-08-06 09:54:04 -0700277 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900278 assertFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700279
280 // Before they are clipped though windows will be shifted
281 w.mAttrs.x = 300;
282 w.mAttrs.y = 300;
283 w.mRequestedWidth = 1000;
284 w.mRequestedHeight = 1000;
chaviw1454b392018-08-06 09:54:04 -0700285 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900286 assertFrame(w, 0, 0, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700287
288 // If there is room to move around in the parent frame the window will be shifted according
289 // to gravity.
290 w.mAttrs.x = 0;
291 w.mAttrs.y = 0;
292 w.mRequestedWidth = 300;
293 w.mRequestedHeight = 300;
294 w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
chaviw1454b392018-08-06 09:54:04 -0700295 w.computeFrameLw();
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +0900296 assertFrame(w, 700, 0, 1000, 300);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700297 w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
chaviw1454b392018-08-06 09:54:04 -0700298 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900299 assertFrame(w, 700, 700, 1000, 1000);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700300 // Window specified x and y are interpreted as offsets in the opposite
301 // direction of gravity
302 w.mAttrs.x = 100;
303 w.mAttrs.y = 100;
chaviw1454b392018-08-06 09:54:04 -0700304 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900305 assertFrame(w, 600, 600, 900, 900);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700306 }
307
Robert Carr15dd7ef2016-11-03 14:26:58 -0700308 @Test
309 public void testLayoutNonfullscreenTask() {
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700310 final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700311 final int logicalWidth = displayInfo.logicalWidth;
312 final int logicalHeight = displayInfo.logicalHeight;
313
314 final int taskLeft = logicalWidth / 4;
315 final int taskTop = logicalHeight / 4;
316 final int taskRight = logicalWidth / 4 * 3;
317 final int taskBottom = logicalHeight / 4 * 3;
318 final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700319 final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700320 task.mFullscreenForTest = false;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700321 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700322 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
323
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700324 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
chaviw1454b392018-08-06 09:54:04 -0700325 final WindowFrames windowFrames = w.getWindowFrames();
326 windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
327 w.computeFrameLw();
Robert Carr15dd7ef2016-11-03 14:26:58 -0700328 // For non fullscreen tasks the containing frame is based off the
329 // task bounds not the parent frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900330 assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
331 assertContentFrame(w, taskBounds);
332 assertContentInset(w, 0, 0, 0, 0);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700333
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700334 pf.set(0, 0, logicalWidth, logicalHeight);
Robert Carr15dd7ef2016-11-03 14:26:58 -0700335 // We still produce insets against the containing frame the same way.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700336 final int cfRight = logicalWidth / 2;
337 final int cfBottom = logicalHeight / 2;
338 final Rect cf = new Rect(0, 0, cfRight, cfBottom);
chaviw553b0212018-07-12 13:37:01 -0700339 windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
chaviw1454b392018-08-06 09:54:04 -0700340 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900341 assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700342 int contentInsetRight = taskRight - cfRight;
343 int contentInsetBottom = taskBottom - cfBottom;
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900344 assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
345 assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
346 taskBottom - contentInsetBottom));
Robert Carr15dd7ef2016-11-03 14:26:58 -0700347
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700348 pf.set(0, 0, logicalWidth, logicalHeight);
Evan Roskyed6767f2018-10-26 17:21:06 -0700349 // If we set displayed bounds, the insets will be computed with the main task bounds
350 // but the frame will be positioned according to the displayed bounds.
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700351 final int insetLeft = logicalWidth / 5;
352 final int insetTop = logicalHeight / 5;
353 final int insetRight = insetLeft + (taskRight - taskLeft);
354 final int insetBottom = insetTop + (taskBottom - taskTop);
Evan Roskyed6767f2018-10-26 17:21:06 -0700355 task.mOverrideDisplayedBounds.set(taskBounds);
356 task.mBounds.set(insetLeft, insetTop, insetRight, insetBottom);
chaviw553b0212018-07-12 13:37:01 -0700357 windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
chaviw1454b392018-08-06 09:54:04 -0700358 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900359 assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700360 contentInsetRight = insetRight - cfRight;
361 contentInsetBottom = insetBottom - cfBottom;
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900362 assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
363 assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
364 taskBottom - contentInsetBottom));
Robert Carr15dd7ef2016-11-03 14:26:58 -0700365 }
366
Robert Carrfbbde852016-10-18 11:02:28 -0700367 @Test
368 public void testCalculatePolicyCrop() {
369 final WindowStateWithTask w = createWindow(
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700370 new TaskWithBounds(mStubStack, mWm, null), MATCH_PARENT, MATCH_PARENT);
Robert Carrfbbde852016-10-18 11:02:28 -0700371 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
372
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700373 final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
374 final int logicalWidth = displayInfo.logicalWidth;
375 final int logicalHeight = displayInfo.logicalHeight;
376 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
Robert Carrfbbde852016-10-18 11:02:28 -0700377 final Rect df = pf;
378 final Rect of = df;
379 final Rect cf = new Rect(pf);
380 // Produce some insets
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700381 cf.top += displayInfo.logicalWidth / 10;
382 cf.bottom -= displayInfo.logicalWidth / 5;
Robert Carrfbbde852016-10-18 11:02:28 -0700383 final Rect vf = cf;
384 final Rect sf = vf;
385 // We use a decor content frame with insets to produce cropping.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900386 Rect dcf = new Rect(cf);
Robert Carrfbbde852016-10-18 11:02:28 -0700387
chaviw1454b392018-08-06 09:54:04 -0700388 final WindowFrames windowFrames = w.getWindowFrames();
389 windowFrames.setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
390 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900391 assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom);
chaviw0eac1682017-11-02 11:27:51 -0700392
chaviw553b0212018-07-12 13:37:01 -0700393 windowFrames.mDecorFrame.setEmpty();
Robert Carrfbbde852016-10-18 11:02:28 -0700394 // Likewise with no decor frame we would get no crop
chaviw1454b392018-08-06 09:54:04 -0700395 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900396 assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight);
Robert Carrfbbde852016-10-18 11:02:28 -0700397
398 // Now we set up a window which doesn't fill the entire decor frame.
399 // Normally it would be cropped to it's frame but in the case of docked resizing
400 // we need to account for the fact the windows surface will be made
401 // fullscreen and thus also make the crop fullscreen.
chaviw553b0212018-07-12 13:37:01 -0700402
403 windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
Robert Carrfbbde852016-10-18 11:02:28 -0700404 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
Andrii Kuliana95bfff2017-03-30 19:00:41 -0700405 w.mAttrs.width = logicalWidth / 2;
406 w.mAttrs.height = logicalHeight / 2;
407 w.mRequestedWidth = logicalWidth / 2;
408 w.mRequestedHeight = logicalHeight / 2;
chaviw1454b392018-08-06 09:54:04 -0700409 w.computeFrameLw();
Robert Carrfbbde852016-10-18 11:02:28 -0700410
Robert Carrfbbde852016-10-18 11:02:28 -0700411 // Normally the crop is shrunk from the decor frame
412 // to the computed window frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900413 assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2);
Robert Carrfbbde852016-10-18 11:02:28 -0700414
415 w.mDockedResizingForTest = true;
Robert Carr186d9de2017-02-09 12:41:03 -0800416 // But if we are docked resizing it won't be, however we will still be
417 // shrunk to the decor frame and the display.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900418 assertPolicyCrop(w, 0, 0,
Robert Carr186d9de2017-02-09 12:41:03 -0800419 Math.min(pf.width(), displayInfo.logicalWidth),
420 Math.min(pf.height(), displayInfo.logicalHeight));
Robert Carrfbbde852016-10-18 11:02:28 -0700421 }
422
Andrii Kulianc24f3732017-08-08 19:35:17 -0700423 @Test
424 public void testLayoutLetterboxedWindow() {
425 // First verify task behavior in multi-window mode.
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700426 final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
Andrii Kulianc24f3732017-08-08 19:35:17 -0700427 final int logicalWidth = displayInfo.logicalWidth;
428 final int logicalHeight = displayInfo.logicalHeight;
429
430 final int taskLeft = logicalWidth / 5;
431 final int taskTop = logicalHeight / 5;
432 final int taskRight = logicalWidth / 4 * 3;
433 final int taskBottom = logicalHeight / 4 * 3;
434 final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700435 final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700436 task.mFullscreenForTest = false;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700437 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700438 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
439
440 final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
chaviw1454b392018-08-06 09:54:04 -0700441 final WindowFrames windowFrames = w.getWindowFrames();
442 windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
443 w.computeFrameLw();
Andrii Kulianc24f3732017-08-08 19:35:17 -0700444 // For non fullscreen tasks the containing frame is based off the
445 // task bounds not the parent frame.
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900446 assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
447 assertContentFrame(w, taskBounds);
448 assertContentInset(w, 0, 0, 0, 0);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700449
450 // Now simulate switch to fullscreen for letterboxed app.
451 final int xInset = logicalWidth / 10;
Riddle Hsub398da32019-01-21 21:48:16 +0800452 final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
Evan Roskydfe3da72018-10-26 17:21:06 -0700453 Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
Bryce Leef3c6a472017-11-14 14:53:06 -0800454 config.windowConfiguration.setBounds(cf);
Evan Roskydfe3da72018-10-26 17:21:06 -0700455 w.mAppToken.onRequestedOverrideConfigurationChanged(config);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700456 pf.set(0, 0, logicalWidth, logicalHeight);
457 task.mFullscreenForTest = true;
chaviw553b0212018-07-12 13:37:01 -0700458 windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
chaviw1454b392018-08-06 09:54:04 -0700459 w.computeFrameLw();
Kazuki Takisee8d6d442018-07-23 17:40:20 +0900460 assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
461 assertContentFrame(w, cf);
462 assertContentInset(w, 0, 0, 0, 0);
Andrii Kulianc24f3732017-08-08 19:35:17 -0700463 }
464
Adrian Roos5c6b6222017-11-07 17:36:10 +0100465 @Test
466 public void testDisplayCutout() {
467 // Regular fullscreen task and window
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700468 final Task task = new TaskWithBounds(mStubStack, mWm, null);
469 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100470 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
471
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100472 final Rect pf = new Rect(0, 0, 1000, 2000);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100473 // Create a display cutout of size 50x50, aligned top-center
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100474 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());
Adrian Roos5c6b6222017-11-07 17:36:10 +0100477
chaviw1454b392018-08-06 09:54:04 -0700478 final WindowFrames windowFrames = w.getWindowFrames();
479 windowFrames.setFrames(pf, pf, 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();
Adrian Roos5c6b6222017-11-07 17:36:10 +0100482
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);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100487 }
488
Jorim Jaggibae2b152018-04-18 17:27:27 +0200489 @Test
Evan Roskyed6767f2018-10-26 17:21:06 -0700490 public void testDisplayCutout_tempDisplayedBounds() {
Jorim Jaggibae2b152018-04-18 17:27:27 +0200491 // Regular fullscreen task and window
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700492 final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm,
Evan Roskyed6767f2018-10-26 17:21:06 -0700493 new Rect(0, 0, 1000, 2000));
Jorim Jaggibae2b152018-04-18 17:27:27 +0200494 task.mFullscreenForTest = false;
Evan Roskyed6767f2018-10-26 17:21:06 -0700495 task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500));
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700496 WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
Jorim Jaggibae2b152018-04-18 17:27:27 +0200497 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
498
499 final Rect pf = new Rect(0, -500, 1000, 1500);
500 // Create a display cutout of size 50x50, aligned top-center
501 final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
Issei Suzuki43190bd2018-08-20 17:28:41 +0200502 fromBoundingRect(500, 0, 550, 50, BOUNDS_POSITION_TOP),
503 pf.width(), pf.height());
Jorim Jaggibae2b152018-04-18 17:27:27 +0200504
chaviw1454b392018-08-06 09:54:04 -0700505 final WindowFrames windowFrames = w.getWindowFrames();
506 windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
chaviwcdba9a42018-07-19 11:36:42 -0700507 windowFrames.setDisplayCutout(cutout);
chaviw1454b392018-08-06 09:54:04 -0700508 w.computeFrameLw();
Jorim Jaggibae2b152018-04-18 17:27:27 +0200509
chaviwcdba9a42018-07-19 11:36:42 -0700510 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
511 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
512 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0);
513 assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0);
Jorim Jaggibae2b152018-04-18 17:27:27 +0200514 }
515
Robert Carrfbbde852016-10-18 11:02:28 -0700516 private WindowStateWithTask createWindow(Task task, int width, int height) {
Robert Carr16a4e3c2016-10-28 11:45:22 -0700517 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
518 attrs.width = width;
519 attrs.height = height;
520
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700521 return new WindowStateWithTask(mWm, mIWindow, mWindowToken, attrs, task);
Robert Carr16a4e3c2016-10-28 11:45:22 -0700522 }
Robert Carr16a4e3c2016-10-28 11:45:22 -0700523}