blob: 2c68cc7a19bfd5f6a698c578b431295ee83f8200 [file] [log] [blame]
Wale Ogunwaleb699ce02016-07-18 12:05:30 -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 Ogunwaleb699ce02016-07-18 12:05:30 -070015 */
16
17package com.android.server.wm;
18
chaviwb28de1f2018-03-02 10:42:36 -080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
lumarkf948afe2019-05-23 21:22:36 +080021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Adrian Roos0e7b70a2018-06-07 15:29:34 +020022import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
Tiger Huang332793b2019-10-29 23:21:27 +080023import static android.view.InsetsState.ITYPE_STATUS_BAR;
Adrian Roos0e7b70a2018-06-07 15:29:34 +020024import static android.view.Surface.ROTATION_0;
Yunfan Chen5e696f12019-02-07 22:02:08 +090025import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070026import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
Wale Ogunwale805d9ec2016-12-07 12:22:08 -080027import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
28import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070029import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Wale Ogunwale34247952017-02-19 11:57:53 -080030import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
31import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
32import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
33import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
Suprabh Shukla69c71422018-04-02 18:39:01 -070034import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
Riddle Hsu5df3b752019-12-16 13:27:37 -060035import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale34247952017-02-19 11:57:53 -080036import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
Riddle Hsu5df3b752019-12-16 13:27:37 -060037import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Wale Ogunwale805d9ec2016-12-07 12:22:08 -080038import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +010039import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
chaviwebcbc342018-02-07 13:19:00 -080040
Yunfan Chend6c85a42019-02-18 15:52:17 +090041import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
lumarkf948afe2019-05-23 21:22:36 +080042import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090043import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
44import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
45import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
46import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
Yunfan Chendb39c162019-02-08 16:14:14 +090047import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090048import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
49
Adrian Roos5251b1d2018-03-23 18:57:43 +010050import static org.hamcrest.Matchers.is;
51import static org.hamcrest.Matchers.not;
Wale Ogunwalea7e3b642016-08-29 10:15:34 -070052import static org.junit.Assert.assertEquals;
53import static org.junit.Assert.assertFalse;
54import static org.junit.Assert.assertNull;
Adrian Roos5251b1d2018-03-23 18:57:43 +010055import static org.junit.Assert.assertThat;
Wale Ogunwalea7e3b642016-08-29 10:15:34 -070056import static org.junit.Assert.assertTrue;
Vishnu Nairddd80742018-08-21 14:12:46 -070057import static org.mockito.ArgumentMatchers.any;
Michael Wrighte3001042019-02-05 00:13:14 +000058import static org.mockito.ArgumentMatchers.anyInt;
chaviw40234662018-02-07 09:37:16 -080059import static org.mockito.ArgumentMatchers.anyLong;
60import static org.mockito.ArgumentMatchers.anyString;
Vishnu Nairddd80742018-08-21 14:12:46 -070061import static org.mockito.ArgumentMatchers.eq;
Vinit Nayak8009e922019-09-05 11:49:53 -070062import static org.mockito.Mockito.when;
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070063
Issei Suzuki43190bd2018-08-20 17:28:41 +020064import android.graphics.Insets;
Vishnu Nairddd80742018-08-21 14:12:46 -070065import android.graphics.Matrix;
Tarandeep Singhbcba88c2019-12-06 10:36:55 -080066import android.graphics.PixelFormat;
Adrian Roos49c27ff2018-08-31 13:07:33 -070067import android.graphics.Rect;
Brett Chabota26eda92018-07-23 13:08:30 -070068import android.platform.test.annotations.Presubmit;
Adrian Roos49c27ff2018-08-31 13:07:33 -070069import android.util.Size;
70import android.view.DisplayCutout;
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +010071import android.view.InsetsSource;
Brett Chabota26eda92018-07-23 13:08:30 -070072import android.view.SurfaceControl;
Yunfan Chen5e696f12019-02-07 22:02:08 +090073import android.view.ViewRootImpl;
Brett Chabota26eda92018-07-23 13:08:30 -070074import android.view.WindowManager;
75
Yunfan Chendb39c162019-02-08 16:14:14 +090076import androidx.test.filters.FlakyTest;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070077import androidx.test.filters.SmallTest;
78
Adrian Roos49c27ff2018-08-31 13:07:33 -070079import com.android.server.wm.utils.WmDisplayCutout;
80
Yunfan Chen5e696f12019-02-07 22:02:08 +090081import org.junit.AfterClass;
Yunfan Chendb39c162019-02-08 16:14:14 +090082import org.junit.Before;
Yunfan Chen5e696f12019-02-07 22:02:08 +090083import org.junit.BeforeClass;
Brett Chabota26eda92018-07-23 13:08:30 -070084import org.junit.Test;
Riddle Hsu2da2d032019-08-28 21:08:58 +080085import org.junit.runner.RunWith;
Brett Chabota26eda92018-07-23 13:08:30 -070086
Riddle Hsu5df3b752019-12-16 13:27:37 -060087import java.util.Arrays;
Brett Chabota26eda92018-07-23 13:08:30 -070088import java.util.LinkedList;
Riddle Hsu5df3b752019-12-16 13:27:37 -060089import java.util.List;
Brett Chabota26eda92018-07-23 13:08:30 -070090
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070091/**
92 * Tests for the {@link WindowState} class.
93 *
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070094 * Build/Install/Run:
Andrii Kulianf5d14112019-10-31 17:37:54 -070095 * atest WmTests:WindowStateTests
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070096 */
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070097@SmallTest
98@Presubmit
Riddle Hsu2da2d032019-08-28 21:08:58 +080099@RunWith(WindowTestRunner.class)
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800100public class WindowStateTests extends WindowTestsBase {
Yunfan Chen5e696f12019-02-07 22:02:08 +0900101 private static int sPreviousNewInsetsMode;
102
103 @BeforeClass
104 public static void setUpOnce() {
Yunfan Chendb39c162019-02-08 16:14:14 +0900105 // TODO: Make use of SettingsSession when it becomes feasible for this.
Yunfan Chen5e696f12019-02-07 22:02:08 +0900106 sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode;
107 // To let the insets provider control the insets visibility, the insets mode has to be
108 // NEW_INSETS_MODE_FULL.
109 ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
110 }
111
112 @AfterClass
113 public static void tearDownOnce() {
114 ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode;
115 }
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700116
Yunfan Chendb39c162019-02-08 16:14:14 +0900117 @Before
118 public void setUp() {
119 // TODO: Let the insets source with new mode keep the visibility control, and remove this
120 // setup code. Now mTopFullscreenOpaqueWindowState will take back the control of insets
121 // visibility.
Riddle Hsu2da2d032019-08-28 21:08:58 +0800122 spyOn(mDisplayContent);
123 doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
Yunfan Chendb39c162019-02-08 16:14:14 +0900124 }
125
Wale Ogunwalea7e3b642016-08-29 10:15:34 -0700126 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700127 public void testIsParentWindowHidden() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800128 final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
129 final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
130 final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
Wale Ogunwale9d147902016-07-16 11:58:55 -0700131
chaviwebcbc342018-02-07 13:19:00 -0800132 // parentWindow is initially set to hidden.
133 assertTrue(parentWindow.mHidden);
134 assertFalse(parentWindow.isParentWindowHidden());
135 assertTrue(child1.isParentWindowHidden());
136 assertTrue(child2.isParentWindowHidden());
137
138 parentWindow.mHidden = false;
Wale Ogunwale9d147902016-07-16 11:58:55 -0700139 assertFalse(parentWindow.isParentWindowHidden());
140 assertFalse(child1.isParentWindowHidden());
141 assertFalse(child2.isParentWindowHidden());
Wale Ogunwale9d147902016-07-16 11:58:55 -0700142 }
143
Wale Ogunwalea7e3b642016-08-29 10:15:34 -0700144 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700145 public void testIsChildWindow() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800146 final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
147 final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
148 final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
149 final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
Wale Ogunwaleadde52e2016-07-16 13:11:55 -0700150
151 assertFalse(parentWindow.isChildWindow());
152 assertTrue(child1.isChildWindow());
153 assertTrue(child2.isChildWindow());
154 assertFalse(randomWindow.isChildWindow());
155 }
156
Wale Ogunwalea7e3b642016-08-29 10:15:34 -0700157 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700158 public void testHasChild() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800159 final WindowState win1 = createWindow(null, TYPE_APPLICATION, "win1");
160 final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, "win11");
161 final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, "win12");
162 final WindowState win2 = createWindow(null, TYPE_APPLICATION, "win2");
163 final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, "win21");
164 final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
Wale Ogunwaleadde52e2016-07-16 13:11:55 -0700165
166 assertTrue(win1.hasChild(win11));
167 assertTrue(win1.hasChild(win12));
168 assertTrue(win2.hasChild(win21));
169
170 assertFalse(win1.hasChild(win21));
171 assertFalse(win1.hasChild(randomWindow));
172
173 assertFalse(win2.hasChild(win11));
174 assertFalse(win2.hasChild(win12));
175 assertFalse(win2.hasChild(randomWindow));
176 }
177
Wale Ogunwalea7e3b642016-08-29 10:15:34 -0700178 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700179 public void testGetParentWindow() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800180 final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
181 final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
182 final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700183
184 assertNull(parentWindow.getParentWindow());
185 assertEquals(parentWindow, child1.getParentWindow());
186 assertEquals(parentWindow, child2.getParentWindow());
187 }
188
Wale Ogunwalea7e3b642016-08-29 10:15:34 -0700189 @Test
Suprabh Shukla69c71422018-04-02 18:39:01 -0700190 public void testOverlayWindowHiddenWhenSuspended() {
191 final WindowState overlayWindow = spy(createWindow(null, TYPE_APPLICATION_OVERLAY,
192 "overlayWindow"));
193 overlayWindow.setHiddenWhileSuspended(true);
194 verify(overlayWindow).hideLw(true, true);
195 overlayWindow.setHiddenWhileSuspended(false);
196 verify(overlayWindow).showLw(true, true);
197 }
198
199 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700200 public void testGetTopParentWindow() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800201 final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
202 final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
203 final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700204
205 assertEquals(root, root.getTopParentWindow());
206 assertEquals(root, child1.getTopParentWindow());
207 assertEquals(child1, child2.getParentWindow());
208 assertEquals(root, child2.getTopParentWindow());
Wale Ogunwaleea92d972016-12-08 07:33:13 -0800209
210 // Test case were child is detached from parent.
211 root.removeChild(child1);
212 assertEquals(child1, child1.getTopParentWindow());
213 assertEquals(child1, child2.getParentWindow());
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700214 }
215
Jorim Jaggiaf221d12016-11-15 14:59:57 -0800216 @Test
217 public void testIsOnScreen_hiddenByPolicy() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800218 final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
Jorim Jaggiaf221d12016-11-15 14:59:57 -0800219 window.setHasSurface(true);
220 assertTrue(window.isOnScreen());
221 window.hideLw(false /* doAnimation */);
222 assertFalse(window.isOnScreen());
223 }
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800224
225 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700226 public void testCanBeImeTarget() {
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800227 final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
228 final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
229
Tarandeep Singhbcba88c2019-12-06 10:36:55 -0800230 // Setting FLAG_NOT_FOCUSABLE prevents the window from being an IME target.
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800231 appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
232 imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
233
234 // Make windows visible
235 appWindow.setHasSurface(true);
236 imeWindow.setHasSurface(true);
237
Tarandeep Singhbcba88c2019-12-06 10:36:55 -0800238 // Windows with FLAG_NOT_FOCUSABLE can't be IME targets
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800239 assertFalse(appWindow.canBeImeTarget());
240 assertFalse(imeWindow.canBeImeTarget());
241
242 // Add IME target flags
243 appWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
244 imeWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
245
Tarandeep Singhbcba88c2019-12-06 10:36:55 -0800246 // Visible app window with flags FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM can't be IME
247 // target while an IME window can never be an IME target regardless of its visibility
248 // or flags.
249 assertFalse(appWindow.canBeImeTarget());
Andrew Chant17c896e2019-12-05 22:39:02 +0000250 assertFalse(imeWindow.canBeImeTarget());
Tarandeep Singh0ffa15a2019-11-04 13:40:15 -0800251
Tarandeep Singhbcba88c2019-12-06 10:36:55 -0800252 // b/145812508: special legacy use-case for transparent/translucent windows.
253 appWindow.mAttrs.format = PixelFormat.TRANSPARENT;
254 assertTrue(appWindow.canBeImeTarget());
255
256 appWindow.mAttrs.format = PixelFormat.OPAQUE;
257 appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM;
258 assertFalse(appWindow.canBeImeTarget());
259 appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
260 assertTrue(appWindow.canBeImeTarget());
261
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800262 // Make windows invisible
263 appWindow.hideLw(false /* doAnimation */);
264 imeWindow.hideLw(false /* doAnimation */);
265
266 // Invisible window can't be IME targets even if they have the right flags.
267 assertFalse(appWindow.canBeImeTarget());
268 assertFalse(imeWindow.canBeImeTarget());
lumarkf948afe2019-05-23 21:22:36 +0800269
270 // Simulate the window is in split screen primary stack and the current state is
271 // minimized and home stack is resizable, so that we should ignore input for the stack.
272 final DockedStackDividerController controller =
273 mDisplayContent.getDockedDividerController();
Louis Changdc077272019-11-12 16:52:56 +0800274 final ActivityStack stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
lumarkf948afe2019-05-23 21:22:36 +0800275 ACTIVITY_TYPE_STANDARD, mDisplayContent);
276 spyOn(appWindow);
277 spyOn(controller);
278 spyOn(stack);
279 doReturn(true).when(controller).isMinimizedDock();
280 doReturn(true).when(controller).isHomeStackResizable();
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800281 doReturn(stack).when(appWindow).getRootTask();
lumarkf948afe2019-05-23 21:22:36 +0800282
283 // Make sure canBeImeTarget is false due to shouldIgnoreInput is true;
284 assertFalse(appWindow.canBeImeTarget());
285 assertTrue(stack.shouldIgnoreInput());
Wale Ogunwale805d9ec2016-12-07 12:22:08 -0800286 }
Wale Ogunwale34247952017-02-19 11:57:53 -0800287
288 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700289 public void testGetWindow() {
Wale Ogunwale34247952017-02-19 11:57:53 -0800290 final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
291 final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
292 final WindowState mediaOverlayChild = createWindow(root,
293 TYPE_APPLICATION_MEDIA_OVERLAY, "mediaOverlayChild");
294 final WindowState attachedDialogChild = createWindow(root,
295 TYPE_APPLICATION_ATTACHED_DIALOG, "attachedDialogChild");
296 final WindowState subPanelChild = createWindow(root,
297 TYPE_APPLICATION_SUB_PANEL, "subPanelChild");
298 final WindowState aboveSubPanelChild = createWindow(root,
299 TYPE_APPLICATION_ABOVE_SUB_PANEL, "aboveSubPanelChild");
300
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700301 final LinkedList<WindowState> windows = new LinkedList<>();
Wale Ogunwale34247952017-02-19 11:57:53 -0800302
303 root.getWindow(w -> {
304 windows.addLast(w);
305 return false;
306 });
307
308 // getWindow should have returned candidate windows in z-order.
309 assertEquals(aboveSubPanelChild, windows.pollFirst());
310 assertEquals(subPanelChild, windows.pollFirst());
311 assertEquals(attachedDialogChild, windows.pollFirst());
312 assertEquals(root, windows.pollFirst());
313 assertEquals(mediaOverlayChild, windows.pollFirst());
314 assertEquals(mediaChild, windows.pollFirst());
315 assertTrue(windows.isEmpty());
316 }
Bryce Leeae73ba42017-05-05 09:58:25 -0700317
318 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700319 public void testPrepareWindowToDisplayDuringRelayout() {
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800320 // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
Garfield Tane8d84ab2019-10-11 09:49:40 -0700321 // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same activity.
322 final ActivityRecord activity = createActivityRecord(mDisplayContent,
chaviwb28de1f2018-03-02 10:42:36 -0800323 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700324 final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
325 final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
chaviwb28de1f2018-03-02 10:42:36 -0800326
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800327 testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
328 true /* expectedCurrentLaunchCanTurnScreenOn */);
Andrii Kulian46799182019-10-17 16:26:17 -0700329 testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
330 true /* expectedCurrentLaunchCanTurnScreenOn */);
331
332 // Call prepareWindowToDisplayDuringRelayout for two windows from the same activity, one of
333 // which has FLAG_TURN_SCREEN_ON. The first processed one should trigger the wakeup.
334 second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
335 testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
336 false /* expectedCurrentLaunchCanTurnScreenOn */);
337 testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800338 false /* expectedCurrentLaunchCanTurnScreenOn */);
chaviwb28de1f2018-03-02 10:42:36 -0800339
340 // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON
Garfield Tane8d84ab2019-10-11 09:49:40 -0700341 // from the same activity. Only one should trigger the wakeup.
342 activity.setCurrentLaunchCanTurnScreenOn(true);
chaviwb28de1f2018-03-02 10:42:36 -0800343 first.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
344 second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
345
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800346 testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
347 false /* expectedCurrentLaunchCanTurnScreenOn */);
348 testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
349 false /* expectedCurrentLaunchCanTurnScreenOn */);
chaviwb28de1f2018-03-02 10:42:36 -0800350
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800351 // Without window flags, the state of ActivityRecord.canTurnScreenOn should still be able to
352 // turn on the screen.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700353 activity.setCurrentLaunchCanTurnScreenOn(true);
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800354 first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700355 doReturn(true).when(activity).canTurnScreenOn();
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800356
357 testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
358 false /* expectedCurrentLaunchCanTurnScreenOn */);
chaviwb28de1f2018-03-02 10:42:36 -0800359
360 // Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
Garfield Tane8d84ab2019-10-11 09:49:40 -0700361 // activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
chaviw97d28202018-02-27 16:23:53 -0800362 final WindowToken windowToken = WindowTestUtils.createTestWindowToken(FIRST_SUB_WINDOW,
chaviwb28de1f2018-03-02 10:42:36 -0800363 mDisplayContent);
364 final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
365 "firstWindow");
366 final WindowState secondWindow = createWindow(null, TYPE_APPLICATION, windowToken,
367 "secondWindow");
368 firstWindow.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
369 secondWindow.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
370
Garfield Tane3d37b52019-07-23 12:43:05 -0700371 final WindowState.PowerManagerWrapper powerManagerWrapper =
372 mSystemServicesTestRule.getPowerManagerWrapper();
373 reset(powerManagerWrapper);
chaviwb28de1f2018-03-02 10:42:36 -0800374 firstWindow.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
Garfield Tane3d37b52019-07-23 12:43:05 -0700375 verify(powerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
chaviwb28de1f2018-03-02 10:42:36 -0800376
Garfield Tane3d37b52019-07-23 12:43:05 -0700377 reset(powerManagerWrapper);
chaviwb28de1f2018-03-02 10:42:36 -0800378 secondWindow.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
Garfield Tane3d37b52019-07-23 12:43:05 -0700379 verify(powerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
Bryce Leeae73ba42017-05-05 09:58:25 -0700380 }
381
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800382 private void testPrepareWindowToDisplayDuringRelayout(WindowState appWindow,
383 boolean expectedWakeupCalled, boolean expectedCurrentLaunchCanTurnScreenOn) {
Garfield Tane3d37b52019-07-23 12:43:05 -0700384 final WindowState.PowerManagerWrapper powerManagerWrapper =
385 mSystemServicesTestRule.getPowerManagerWrapper();
386 reset(powerManagerWrapper);
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800387 appWindow.prepareWindowToDisplayDuringRelayout(false /* wasVisible */);
388
389 if (expectedWakeupCalled) {
Garfield Tane3d37b52019-07-23 12:43:05 -0700390 verify(powerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800391 } else {
Garfield Tane3d37b52019-07-23 12:43:05 -0700392 verify(powerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString());
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800393 }
394 // If wakeup is expected to be called, the currentLaunchCanTurnScreenOn should be false
395 // because the state will be consumed.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700396 assertThat(appWindow.mActivityRecord.currentLaunchCanTurnScreenOn(),
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800397 is(expectedCurrentLaunchCanTurnScreenOn));
398 }
399
Jorim Jaggi72207752018-01-08 13:16:59 +0100400 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700401 public void testCanAffectSystemUiFlags() {
Jorim Jaggi72207752018-01-08 13:16:59 +0100402 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
Issei Suzukif2f6c912019-11-08 11:24:18 +0100403 app.mActivityRecord.setVisible(true);
Jorim Jaggi72207752018-01-08 13:16:59 +0100404 assertTrue(app.canAffectSystemUiFlags());
Issei Suzukif2f6c912019-11-08 11:24:18 +0100405 app.mActivityRecord.setVisible(false);
Jorim Jaggi72207752018-01-08 13:16:59 +0100406 assertFalse(app.canAffectSystemUiFlags());
Issei Suzukif2f6c912019-11-08 11:24:18 +0100407 app.mActivityRecord.setVisible(true);
Jorim Jaggi72207752018-01-08 13:16:59 +0100408 app.mAttrs.alpha = 0.0f;
409 assertFalse(app.canAffectSystemUiFlags());
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100410 }
411
412 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700413 public void testCanAffectSystemUiFlags_disallow() {
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100414 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
Issei Suzukif2f6c912019-11-08 11:24:18 +0100415 app.mActivityRecord.setVisible(true);
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100416 assertTrue(app.canAffectSystemUiFlags());
417 app.getTask().setCanAffectSystemUiFlags(false);
418 assertFalse(app.canAffectSystemUiFlags());
Jorim Jaggi72207752018-01-08 13:16:59 +0100419 }
420
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100421 @Test
Jorim Jaggi956ca412019-01-07 14:49:14 +0100422 public void testVisibleWithInsetsProvider() {
Tiger Huang332793b2019-10-29 23:21:27 +0800423 final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100424 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
Tiger Huang332793b2019-10-29 23:21:27 +0800425 statusBar.mHasSurface = true;
426 assertTrue(statusBar.isVisible());
427 mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
Jorim Jaggi9b4f4202020-01-28 17:05:06 +0100428 .setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */);
Jorim Jaggi956ca412019-01-07 14:49:14 +0100429 mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
430 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +0100431 final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
432 source.setVisible(false);
Tiger Huang332793b2019-10-29 23:21:27 +0800433 mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +0100434 .onInsetsModified(app, source);
Yunfan Chendb39c162019-02-08 16:14:14 +0900435 waitUntilHandlersIdle();
Tiger Huang332793b2019-10-29 23:21:27 +0800436 assertFalse(statusBar.isVisible());
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100437 }
438
439 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700440 public void testIsSelfOrAncestorWindowAnimating() {
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100441 final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
442 final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
443 final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
444 assertFalse(child2.isSelfOrAncestorWindowAnimatingExit());
445 child2.mAnimatingExit = true;
446 assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
447 child2.mAnimatingExit = false;
448 root.mAnimatingExit = true;
449 assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
450 }
451
Adrian Roos5251b1d2018-03-23 18:57:43 +0100452 @Test
Yunfan Chend6c85a42019-02-18 15:52:17 +0900453 @FlakyTest(bugId = 74078662)
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700454 public void testLayoutSeqResetOnReparent() {
Adrian Roos5251b1d2018-03-23 18:57:43 +0100455 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
456 app.mLayoutSeq = 1;
457 mDisplayContent.mLayoutSeq = 1;
458
Garfield Tane223e682019-04-15 09:59:25 -0700459 DisplayContent newDisplay = createNewDisplay();
460
461 app.onDisplayChanged(newDisplay);
Adrian Roos5251b1d2018-03-23 18:57:43 +0100462
463 assertThat(app.mLayoutSeq, not(is(mDisplayContent.mLayoutSeq)));
464 }
465
Brad Stenningaf596412018-04-02 12:03:19 -0700466 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700467 public void testDisplayIdUpdatedOnReparent() {
Brad Stenningaf596412018-04-02 12:03:19 -0700468 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
469 // fake a different display
470 app.mInputWindowHandle.displayId = mDisplayContent.getDisplayId() + 1;
471 app.onDisplayChanged(mDisplayContent);
472
473 assertThat(app.mInputWindowHandle.displayId, is(mDisplayContent.getDisplayId()));
474 assertThat(app.getDisplayId(), is(mDisplayContent.getDisplayId()));
475 }
476
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200477 @Test
478 public void testSeamlesslyRotateWindow() {
479 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
chaviw619da692019-06-10 15:39:40 -0700480 final SurfaceControl.Transaction t = spy(StubTransaction.class);
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200481
482 app.mHasSurface = true;
Vishnu Naird8c664b2018-09-24 12:52:35 -0700483 app.mSurfaceControl = mock(SurfaceControl.class);
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200484 try {
chaviw492139a2018-07-16 16:07:35 -0700485 app.getFrameLw().set(10, 20, 60, 80);
Vishnu Naird8c664b2018-09-24 12:52:35 -0700486 app.updateSurfacePosition(t);
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200487
Vishnu Nairddd80742018-08-21 14:12:46 -0700488 app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true);
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200489
490 assertTrue(app.mSeamlesslyRotated);
Vishnu Naird8c664b2018-09-24 12:52:35 -0700491
492 // Verify we un-rotate the window state surface.
Vishnu Nairddd80742018-08-21 14:12:46 -0700493 Matrix matrix = new Matrix();
494 // Un-rotate 90 deg
495 matrix.setRotate(270);
496 // Translate it back to origin
497 matrix.postTranslate(0, mDisplayInfo.logicalWidth);
Vishnu Naird8c664b2018-09-24 12:52:35 -0700498 verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class));
499
500 // Verify we update the position as well.
501 float[] currentSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y};
502 matrix.mapPoints(currentSurfacePos);
503 verify(t).setPosition(eq(app.mSurfaceControl), eq(currentSurfacePos[0]),
504 eq(currentSurfacePos[1]));
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200505 } finally {
Vishnu Naird8c664b2018-09-24 12:52:35 -0700506 app.mSurfaceControl = null;
Adrian Roos0e7b70a2018-06-07 15:29:34 +0200507 app.mHasSurface = false;
508 }
509 }
510
Adrian Roos49c27ff2018-08-31 13:07:33 -0700511 @Test
Yunfan Chend6c85a42019-02-18 15:52:17 +0900512 @FlakyTest(bugId = 74078662)
Adrian Roos49c27ff2018-08-31 13:07:33 -0700513 public void testDisplayCutoutIsCalculatedRelativeToFrame() {
514 final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
chaviw1454b392018-08-06 09:54:04 -0700515 WindowFrames wf = app.getWindowFrames();
Adrian Roos49c27ff2018-08-31 13:07:33 -0700516 wf.mParentFrame.set(7, 10, 185, 380);
517 wf.mDisplayFrame.set(wf.mParentFrame);
Issei Suzuki43190bd2018-08-20 17:28:41 +0200518 final DisplayCutout cutout = new DisplayCutout(
519 Insets.of(0, 15, 0, 22) /* safeInset */,
520 null /* boundLeft */,
521 new Rect(95, 0, 105, 15),
522 null /* boundRight */,
523 new Rect(95, 378, 105, 400));
Adrian Roos49c27ff2018-08-31 13:07:33 -0700524 wf.setDisplayCutout(new WmDisplayCutout(cutout, new Size(200, 400)));
525
chaviw1454b392018-08-06 09:54:04 -0700526 app.computeFrameLw();
Adrian Roos49c27ff2018-08-31 13:07:33 -0700527 assertThat(app.getWmDisplayCutout().getDisplayCutout(), is(cutout.inset(7, 10, 5, 20)));
528 }
529
chaviw15ad49f2019-04-24 15:05:39 -0700530 @Test
531 public void testVisibilityChangeSwitchUser() {
532 final WindowState window = createWindow(null, TYPE_APPLICATION, "app");
533 window.mHasSurface = true;
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800534 spyOn(window);
535 doReturn(false).when(window).showForAllUsers();
chaviw15ad49f2019-04-24 15:05:39 -0700536
537 mWm.mCurrentUserId = 1;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700538 window.switchUser(mWm.mCurrentUserId);
chaviw15ad49f2019-04-24 15:05:39 -0700539 assertFalse(window.isVisible());
540 assertFalse(window.isVisibleByPolicy());
541
542 mWm.mCurrentUserId = 0;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700543 window.switchUser(mWm.mCurrentUserId);
chaviw15ad49f2019-04-24 15:05:39 -0700544 assertTrue(window.isVisible());
545 assertTrue(window.isVisibleByPolicy());
546 }
Tiger Huangd8ec9382019-04-18 14:35:09 -0700547
548 @Test
Riddle Hsu5df3b752019-12-16 13:27:37 -0600549 public void testRequestDrawIfNeeded() {
550 final WindowState startingApp = createWindow(null /* parent */,
551 TYPE_BASE_APPLICATION, "startingApp");
552 final WindowState startingWindow = createWindow(null /* parent */,
553 TYPE_APPLICATION_STARTING, startingApp.mToken, "starting");
554 startingApp.mActivityRecord.startingWindow = startingWindow;
wilsonshihe8321942019-10-18 18:39:46 +0800555 final WindowState keyguardHostWindow = mNotificationShadeWindow;
Riddle Hsu5df3b752019-12-16 13:27:37 -0600556 final WindowState allDrawnApp = mAppWindow;
557 allDrawnApp.mActivityRecord.allDrawn = true;
558
559 // The waiting list is used to ensure the content is ready when turning on screen.
560 final List<WindowState> outWaitingForDrawn = mDisplayContent.mWaitingForDrawn;
561 final List<WindowState> visibleWindows = Arrays.asList(mChildAppWindowAbove,
562 keyguardHostWindow, allDrawnApp, startingApp, startingWindow);
563 visibleWindows.forEach(w -> {
564 w.mHasSurface = true;
565 w.requestDrawIfNeeded(outWaitingForDrawn);
566 });
567
568 // Keyguard host window should be always contained. The drawn app or app with starting
569 // window are unnecessary to draw.
570 assertEquals(Arrays.asList(keyguardHostWindow, startingWindow), outWaitingForDrawn);
571 }
572
573 @Test
Tiger Huangd8ec9382019-04-18 14:35:09 -0700574 public void testGetTransformationMatrix() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700575 final int PARENT_WINDOW_OFFSET = 1;
576 final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
577 final int WINDOW_OFFSET = 3;
578 final float OFFSET_SUM =
579 PARENT_WINDOW_OFFSET + DISPLAY_IN_PARENT_WINDOW_OFFSET + WINDOW_OFFSET;
580
Riddle Hsu2da2d032019-08-28 21:08:58 +0800581 final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
Tiger Huangd8ec9382019-04-18 14:35:09 -0700582
Riddle Hsu2da2d032019-08-28 21:08:58 +0800583 final DisplayContent dc = createNewDisplay();
584 win0.getFrameLw().offsetTo(PARENT_WINDOW_OFFSET, 0);
585 dc.reparentDisplayContent(win0, win0.getSurfaceControl());
586 dc.updateLocation(win0, DISPLAY_IN_PARENT_WINDOW_OFFSET, 0);
Tiger Huangd8ec9382019-04-18 14:35:09 -0700587
Riddle Hsu2da2d032019-08-28 21:08:58 +0800588 final float[] values = new float[9];
589 final Matrix matrix = new Matrix();
chaviw619da692019-06-10 15:39:40 -0700590 final SurfaceControl.Transaction t = spy(StubTransaction.class);
Riddle Hsu2da2d032019-08-28 21:08:58 +0800591 final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
592 win1.mHasSurface = true;
593 win1.mSurfaceControl = mock(SurfaceControl.class);
594 win1.getFrameLw().offsetTo(WINDOW_OFFSET, 0);
595 win1.updateSurfacePosition(t);
596 win1.getTransformationMatrix(values, matrix);
Tiger Huangd8ec9382019-04-18 14:35:09 -0700597
Riddle Hsu2da2d032019-08-28 21:08:58 +0800598 matrix.getValues(values);
599 assertEquals(OFFSET_SUM, values[Matrix.MTRANS_X], 0f);
600 assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
Tiger Huangd8ec9382019-04-18 14:35:09 -0700601 }
Vinit Nayak8009e922019-09-05 11:49:53 -0700602
603 @Test
604 public void testCantReceiveTouchDuringRecentsAnimation() {
605 final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
606
607 // Mock active recents animation
608 RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
Winson Chungdc4edb82019-12-16 16:31:04 -0800609 when(recentsController.shouldApplyInputConsumer(win0.mActivityRecord)).thenReturn(true);
Vinit Nayak8009e922019-09-05 11:49:53 -0700610 mWm.setRecentsAnimationController(recentsController);
611 assertTrue(win0.cantReceiveTouchInput());
612 }
613
614 @Test
615 public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
616 final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
Issei Suzuki1669ea42019-11-06 14:20:59 +0100617 win0.mActivityRecord.mVisibleRequested = false;
Vinit Nayak8009e922019-09-05 11:49:53 -0700618 assertTrue(win0.cantReceiveTouchInput());
619 }
620
621 @Test
622 public void testCantReceiveTouchWhenShouldIgnoreInput() {
623 final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700624 win0.mActivityRecord.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */);
Vinit Nayak8009e922019-09-05 11:49:53 -0700625 assertTrue(win0.cantReceiveTouchInput());
626 }
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700627}