1 /*
2  * Copyright (C) 2018 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
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
20 import static android.view.DisplayCutout.NO_CUTOUT;
21 import static android.view.InsetsSource.ID_IME;
22 import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
23 import static android.view.Surface.ROTATION_0;
24 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
25 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
26 import static android.view.ViewRootImpl.CLIENT_TRANSIENT;
27 import static android.view.WindowInsets.Type.navigationBars;
28 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
29 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
30 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
31 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
32 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
33 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
34 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
35 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
36 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
37 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
38 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
39 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41 
42 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
43 
44 import static org.junit.Assert.assertEquals;
45 import static org.junit.Assert.assertFalse;
46 import static org.junit.Assert.assertNotEquals;
47 import static org.junit.Assert.assertNotNull;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertTrue;
50 import static org.mockito.ArgumentMatchers.anyInt;
51 import static org.mockito.Mockito.doReturn;
52 import static org.mockito.Mockito.spy;
53 import static org.mockito.Mockito.when;
54 
55 import android.graphics.Insets;
56 import android.graphics.PixelFormat;
57 import android.graphics.Rect;
58 import android.platform.test.annotations.Presubmit;
59 import android.view.DisplayInfo;
60 import android.view.DisplayShape;
61 import android.view.InsetsFrameProvider;
62 import android.view.InsetsSource;
63 import android.view.InsetsState;
64 import android.view.PrivacyIndicatorBounds;
65 import android.view.Surface;
66 import android.view.WindowInsets;
67 import android.view.WindowInsets.Side;
68 import android.view.WindowManager;
69 
70 import androidx.test.filters.SmallTest;
71 
72 import org.junit.Assume;
73 import org.junit.Test;
74 import org.junit.runner.RunWith;
75 
76 @SmallTest
77 @Presubmit
78 @RunWith(WindowTestRunner.class)
79 public class DisplayPolicyTests extends WindowTestsBase {
80 
createOpaqueFullscreen(boolean hasLightNavBar)81     private WindowState createOpaqueFullscreen(boolean hasLightNavBar) {
82         final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "opaqueFullscreen");
83         final WindowManager.LayoutParams attrs = win.mAttrs;
84         attrs.width = MATCH_PARENT;
85         attrs.height = MATCH_PARENT;
86         attrs.flags =
87                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
88         attrs.format = PixelFormat.OPAQUE;
89         attrs.insetsFlags.appearance = hasLightNavBar ? APPEARANCE_LIGHT_NAVIGATION_BARS : 0;
90         return win;
91     }
92 
createDreamWindow()93     private WindowState createDreamWindow() {
94         final WindowState win = createDreamWindow(null, TYPE_BASE_APPLICATION, "dream");
95         final WindowManager.LayoutParams attrs = win.mAttrs;
96         attrs.width = MATCH_PARENT;
97         attrs.height = MATCH_PARENT;
98         attrs.flags =
99                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
100         attrs.format = PixelFormat.OPAQUE;
101         return win;
102     }
103 
createDimmingDialogWindow(boolean canBeImTarget)104     private WindowState createDimmingDialogWindow(boolean canBeImTarget) {
105         final WindowState win = spy(createWindow(null, TYPE_APPLICATION, "dimmingDialog"));
106         final WindowManager.LayoutParams attrs = win.mAttrs;
107         attrs.width = WRAP_CONTENT;
108         attrs.height = WRAP_CONTENT;
109         attrs.flags = FLAG_DIM_BEHIND | (canBeImTarget ? 0 : FLAG_ALT_FOCUSABLE_IM);
110         attrs.format = PixelFormat.TRANSLUCENT;
111         when(win.isDimming()).thenReturn(true);
112         return win;
113     }
114 
createInputMethodWindow(boolean visible, boolean drawNavBar, boolean hasLightNavBar)115     private WindowState createInputMethodWindow(boolean visible, boolean drawNavBar,
116             boolean hasLightNavBar) {
117         final WindowState win = createWindow(null, TYPE_INPUT_METHOD, "inputMethod");
118         final WindowManager.LayoutParams attrs = win.mAttrs;
119         attrs.width = MATCH_PARENT;
120         attrs.height = MATCH_PARENT;
121         attrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN
122                 | (drawNavBar ? FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS : 0);
123         attrs.format = PixelFormat.TRANSPARENT;
124         attrs.insetsFlags.appearance = hasLightNavBar ? APPEARANCE_LIGHT_NAVIGATION_BARS : 0;
125         win.mHasSurface = visible;
126         return win;
127     }
128 
129     @Test
testChooseNavigationColorWindowLw()130     public void testChooseNavigationColorWindowLw() {
131         final WindowState candidate = createOpaqueFullscreen(false);
132         final WindowState dimmingImTarget = createDimmingDialogWindow(true);
133         final WindowState dimmingNonImTarget = createDimmingDialogWindow(false);
134 
135         final WindowState visibleIme = createInputMethodWindow(true, true, false);
136         final WindowState invisibleIme = createInputMethodWindow(false, true, false);
137         final WindowState imeNonDrawNavBar = createInputMethodWindow(true, false, false);
138 
139         // If everything is null, return null.
140         assertNull(null, DisplayPolicy.chooseNavigationColorWindowLw(
141                 null, null, NAV_BAR_BOTTOM));
142 
143         // If no IME windows, return candidate window.
144         assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw(
145                 candidate, null, NAV_BAR_BOTTOM));
146         assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
147                 dimmingImTarget, null, NAV_BAR_BOTTOM));
148         assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
149                 dimmingNonImTarget, null, NAV_BAR_BOTTOM));
150 
151         // If IME is not visible, return candidate window.
152         assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw(
153                 null, invisibleIme, NAV_BAR_BOTTOM));
154         assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw(
155                 candidate, invisibleIme, NAV_BAR_BOTTOM));
156         assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
157                 dimmingImTarget, invisibleIme, NAV_BAR_BOTTOM));
158         assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
159                 dimmingNonImTarget, invisibleIme, NAV_BAR_BOTTOM));
160 
161         // If IME is visible, return candidate when the candidate window is not dimming.
162         assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw(
163                 null, visibleIme, NAV_BAR_BOTTOM));
164         assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw(
165                 candidate, visibleIme, NAV_BAR_BOTTOM));
166 
167         // If IME is visible and the candidate window is dimming, checks whether the dimming window
168         // can be IME tartget or not.
169         assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw(
170                 dimmingImTarget, visibleIme, NAV_BAR_BOTTOM));
171         assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
172                 dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM));
173 
174         // Only IME windows that have FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS should be navigation color
175         // window.
176         assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw(
177                 null, imeNonDrawNavBar, NAV_BAR_BOTTOM));
178         assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw(
179                 candidate, imeNonDrawNavBar, NAV_BAR_BOTTOM));
180         assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
181                 dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
182         assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw(
183                 dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
184     }
185 
186     @Test
testChooseNavigationBackgroundWindow()187     public void testChooseNavigationBackgroundWindow() {
188         final WindowState drawBarWin = createOpaqueFullscreen(false);
189         final WindowState nonDrawBarWin = createDimmingDialogWindow(true);
190 
191         final WindowState visibleIme = createInputMethodWindow(true, true, false);
192         final WindowState invisibleIme = createInputMethodWindow(false, true, false);
193         final WindowState nonDrawBarIme = createInputMethodWindow(true, false, false);
194 
195         assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
196                 drawBarWin, null, NAV_BAR_BOTTOM));
197         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
198                 null, null, NAV_BAR_BOTTOM));
199         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
200                 nonDrawBarWin, null, NAV_BAR_BOTTOM));
201 
202         assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
203                 drawBarWin, visibleIme, NAV_BAR_BOTTOM));
204         assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
205                 null, visibleIme, NAV_BAR_BOTTOM));
206         assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
207                 nonDrawBarWin, visibleIme, NAV_BAR_BOTTOM));
208 
209         assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
210                 drawBarWin, invisibleIme, NAV_BAR_BOTTOM));
211         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
212                 null, invisibleIme, NAV_BAR_BOTTOM));
213         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
214                 nonDrawBarWin, invisibleIme, NAV_BAR_BOTTOM));
215 
216         assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
217                 drawBarWin, nonDrawBarIme, NAV_BAR_BOTTOM));
218         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
219                 null, nonDrawBarIme, NAV_BAR_BOTTOM));
220         assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
221                 nonDrawBarWin, nonDrawBarIme, NAV_BAR_BOTTOM));
222     }
223 
224     @SetupWindows(addWindows = W_NAVIGATION_BAR)
225     @Test
testUpdateLightNavigationBarLw()226     public void testUpdateLightNavigationBarLw() {
227         DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
228         final WindowState opaqueDarkNavBar = createOpaqueFullscreen(false);
229         final WindowState opaqueLightNavBar = createOpaqueFullscreen(true);
230 
231         final WindowState dimming = createDimmingDialogWindow(false);
232 
233         final WindowState imeDrawDarkNavBar = createInputMethodWindow(true, true, false);
234         final WindowState imeDrawLightNavBar = createInputMethodWindow(true, true, true);
235 
236         mDisplayContent.setLayoutNeeded();
237         mDisplayContent.performLayout(true /* initial */, false /* updateImeWindows */);
238 
239         final InsetsSource navSource = new InsetsSource(
240                 InsetsSource.createId(null, 0, navigationBars()), navigationBars());
241         navSource.setFrame(mNavBarWindow.getFrame());
242         opaqueDarkNavBar.mAboveInsetsState.addSource(navSource);
243         opaqueLightNavBar.mAboveInsetsState.addSource(navSource);
244         dimming.mAboveInsetsState.addSource(navSource);
245         imeDrawDarkNavBar.mAboveInsetsState.addSource(navSource);
246         imeDrawLightNavBar.mAboveInsetsState.addSource(navSource);
247 
248         // If there is no window, APPEARANCE_LIGHT_NAVIGATION_BARS is not allowed.
249         assertEquals(0,
250                 displayPolicy.updateLightNavigationBarLw(APPEARANCE_LIGHT_NAVIGATION_BARS, null));
251 
252         // Control window overrides APPEARANCE_LIGHT_NAVIGATION_BARS flag.
253         assertEquals(0, displayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar));
254         assertEquals(0, displayPolicy.updateLightNavigationBarLw(
255                 APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar));
256         assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(
257                 0, opaqueLightNavBar));
258         assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(
259                 APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar));
260     }
261 
262     @SetupWindows(addWindows = { W_ACTIVITY, W_STATUS_BAR })
263     @Test
testComputeTopFullscreenOpaqueWindow()264     public void testComputeTopFullscreenOpaqueWindow() {
265         final WindowManager.LayoutParams attrs = mAppWindow.mAttrs;
266         attrs.x = attrs.y = 0;
267         attrs.height = attrs.width = WindowManager.LayoutParams.MATCH_PARENT;
268         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
269         policy.addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs);
270 
271         policy.applyPostLayoutPolicyLw(
272                 mAppWindow, attrs, null /* attached */, null /* imeTarget */);
273 
274         assertEquals(mAppWindow, policy.getTopFullscreenOpaqueWindow());
275     }
276 
277     @Test(expected = IllegalArgumentException.class)
testMainAppWindowDisallowFitSystemWindowTypes()278     public void testMainAppWindowDisallowFitSystemWindowTypes() {
279         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
280         final WindowState activity = createBaseApplicationWindow();
281         activity.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
282 
283         policy.adjustWindowParamsLw(activity, activity.mAttrs);
284     }
285 
createApplicationWindow()286     private WindowState createApplicationWindow() {
287         final WindowState win = createWindow(null, TYPE_APPLICATION, "Application");
288         final WindowManager.LayoutParams attrs = win.mAttrs;
289         attrs.width = MATCH_PARENT;
290         attrs.height = MATCH_PARENT;
291         attrs.flags = FLAG_SHOW_WHEN_LOCKED | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
292         attrs.format = PixelFormat.OPAQUE;
293         win.mHasSurface = true;
294         return win;
295     }
296 
createBaseApplicationWindow()297     private WindowState createBaseApplicationWindow() {
298         final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "Application");
299         final WindowManager.LayoutParams attrs = win.mAttrs;
300         attrs.width = MATCH_PARENT;
301         attrs.height = MATCH_PARENT;
302         attrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
303         attrs.format = PixelFormat.OPAQUE;
304         win.mHasSurface = true;
305         return win;
306     }
307 
308     @Test
testOverlappingWithNavBar()309     public void testOverlappingWithNavBar() {
310         final InsetsSource navSource = new InsetsSource(
311                 InsetsSource.createId(null, 0, navigationBars()), navigationBars());
312         navSource.setFrame(new Rect(100, 200, 200, 300));
313         testOverlappingWithNavBarType(navSource);
314     }
315 
316     @Test
testOverlappingWithExtraNavBar()317     public void testOverlappingWithExtraNavBar() {
318         final InsetsSource navSource = new InsetsSource(
319                 InsetsSource.createId(null, 1, navigationBars()), navigationBars());
320         navSource.setFrame(new Rect(100, 200, 200, 300));
321         testOverlappingWithNavBarType(navSource);
322     }
323 
testOverlappingWithNavBarType(InsetsSource navSource)324     private void testOverlappingWithNavBarType(InsetsSource navSource) {
325         final WindowState targetWin = createApplicationWindow();
326         final WindowFrames winFrame = targetWin.getWindowFrames();
327         winFrame.mFrame.set(new Rect(100, 100, 200, 200));
328         targetWin.mAboveInsetsState.addSource(navSource);
329 
330         assertFalse("Freeform is overlapping with navigation bar",
331                 DisplayPolicy.isOverlappingWithNavBar(targetWin));
332 
333         winFrame.mFrame.set(new Rect(100, 101, 200, 201));
334         assertTrue("Freeform should be overlapping with navigation bar (bottom)",
335                 DisplayPolicy.isOverlappingWithNavBar(targetWin));
336 
337         winFrame.mFrame.set(new Rect(99, 200, 199, 300));
338         assertTrue("Freeform should be overlapping with navigation bar (right)",
339                 DisplayPolicy.isOverlappingWithNavBar(targetWin));
340 
341         winFrame.mFrame.set(new Rect(199, 200, 299, 300));
342         assertTrue("Freeform should be overlapping with navigation bar (left)",
343                 DisplayPolicy.isOverlappingWithNavBar(targetWin));
344     }
345 
346     @Test
testSwitchDecorInsets()347     public void testSwitchDecorInsets() {
348         createNavBarWithProvidedInsets(mDisplayContent);
349         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
350         final DisplayInfo info = mDisplayContent.getDisplayInfo();
351         final int w = info.logicalWidth;
352         final int h = info.logicalHeight;
353         displayPolicy.updateDecorInsetsInfo();
354         final Rect prevConfigFrame = new Rect(displayPolicy.getDecorInsetsInfo(info.rotation,
355                 info.logicalWidth, info.logicalHeight).mConfigFrame);
356 
357         displayPolicy.updateCachedDecorInsets();
358         mDisplayContent.updateBaseDisplayMetrics(w / 2, h / 2,
359                 info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi);
360         // There is no previous cache. But the current state will be cached.
361         assertFalse(displayPolicy.shouldKeepCurrentDecorInsets());
362 
363         // Switch to original state.
364         displayPolicy.updateCachedDecorInsets();
365         mDisplayContent.updateBaseDisplayMetrics(w, h,
366                 info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi);
367         assertTrue(displayPolicy.shouldKeepCurrentDecorInsets());
368         // The current insets are restored from cache directly.
369         assertEquals(prevConfigFrame, displayPolicy.getDecorInsetsInfo(info.rotation,
370                 info.logicalWidth, info.logicalHeight).mConfigFrame);
371     }
372 
373     @Test
testUpdateDisplayConfigurationByDecor()374     public void testUpdateDisplayConfigurationByDecor() {
375         doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
376         final WindowState navbar = createNavBarWithProvidedInsets(mDisplayContent);
377         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
378         final DisplayInfo di = mDisplayContent.getDisplayInfo();
379         final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp;
380         assertTrue(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
381         assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
382                 di.logicalWidth, di.logicalHeight).mConfigInsets.bottom);
383         mDisplayContent.sendNewConfiguration();
384         assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp);
385         assertFalse(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
386 
387         navbar.removeIfPossible();
388         assertEquals(0, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth,
389                 di.logicalHeight).mNonDecorInsets.bottom);
390 
391         final WindowState statusBar = createStatusBarWithProvidedInsets(mDisplayContent);
392         assertTrue(statusBar.providesDisplayDecorInsets()
393                 && displayPolicy.updateDecorInsetsInfo());
394         assertEquals(STATUS_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
395                 di.logicalWidth, di.logicalHeight).mConfigInsets.top);
396 
397         // Add a window that provides the same insets in current rotation. But it specifies
398         // different insets in other rotations.
399         final WindowState bar2 = createWindow(null, statusBar.mAttrs.type, "bar2");
400         bar2.mAttrs.providedInsets = new InsetsFrameProvider[] {
401                 new InsetsFrameProvider(bar2, 0, WindowInsets.Type.statusBars())
402                         .setInsetsSize(Insets.of(0, STATUS_BAR_HEIGHT, 0, 0))
403         };
404         bar2.mAttrs.setFitInsetsTypes(0);
405         bar2.mAttrs.paramsForRotation = new WindowManager.LayoutParams[4];
406         final int doubleHeightFor90 = STATUS_BAR_HEIGHT * 2;
407         for (int i = ROTATION_0; i <= Surface.ROTATION_270; i++) {
408             final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
409             params.setFitInsetsTypes(0);
410             if (i == Surface.ROTATION_90) {
411                 params.providedInsets = new InsetsFrameProvider[] {
412                         new InsetsFrameProvider(bar2, 0, WindowInsets.Type.statusBars())
413                                 .setInsetsSize(Insets.of(0, doubleHeightFor90, 0, 0))
414                 };
415             } else {
416                 params.providedInsets = bar2.mAttrs.providedInsets;
417             }
418             bar2.mAttrs.paramsForRotation[i] = params;
419         }
420         displayPolicy.addWindowLw(bar2, bar2.mAttrs);
421         // Current rotation is 0 and the top insets is still STATUS_BAR_HEIGHT, so no change.
422         assertFalse(displayPolicy.updateDecorInsetsInfo());
423         // The insets in other rotations should be still updated.
424         assertEquals(doubleHeightFor90, displayPolicy.getDecorInsetsInfo(Surface.ROTATION_90,
425                 di.logicalHeight, di.logicalWidth).mConfigInsets.top);
426     }
427 
428     @SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
429     @Test
testImeMinimalSourceFrame()430     public void testImeMinimalSourceFrame() {
431         Assume.assumeFalse("Behavior no longer needed with ENABLE_HIDE_IME_CAPTION_BAR",
432                 ENABLE_HIDE_IME_CAPTION_BAR);
433 
434         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
435         final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
436 
437         WindowManager.LayoutParams attrs = mNavBarWindow.mAttrs;
438         displayPolicy.addWindowLw(mNavBarWindow, attrs);
439         mNavBarWindow.setRequestedSize(attrs.width, attrs.height);
440         mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
441         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
442         mImeWindow.mAboveInsetsState.set(state);
443         mDisplayContent.mDisplayFrames = new DisplayFrames(
444                 state, displayInfo, NO_CUTOUT, NO_ROUNDED_CORNERS, new PrivacyIndicatorBounds(),
445                 DisplayShape.NONE);
446 
447         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
448         mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
449         mImeWindow.mGivenContentInsets.set(0, displayInfo.logicalHeight, 0, 0);
450         mImeWindow.getControllableInsetProvider().setServerVisible(true);
451 
452         displayPolicy.layoutWindowLw(mNavBarWindow, null, mDisplayContent.mDisplayFrames);
453         displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);
454 
455         final InsetsSource imeSource = state.peekSource(ID_IME);
456         final InsetsSource navBarSource = state.peekSource(
457                 mNavBarWindow.getControllableInsetProvider().getSource().getId());
458 
459         assertNotNull(imeSource);
460         assertNotNull(navBarSource);
461         assertFalse(imeSource.getFrame().isEmpty());
462         assertFalse(navBarSource.getFrame().isEmpty());
463         assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
464     }
465 
466     @SetupWindows(addWindows = W_INPUT_METHOD)
467     @Test
testImeInsetsGivenContentFrame()468     public void testImeInsetsGivenContentFrame() {
469         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
470 
471         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
472         mImeWindow.getControllableInsetProvider().setServerVisible(true);
473 
474         mImeWindow.mGivenContentInsets.set(0, 10, 0, 0);
475 
476         displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);
477         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
478         final InsetsSource imeSource = state.peekSource(ID_IME);
479 
480         assertNotNull(imeSource);
481         assertFalse(imeSource.getFrame().isEmpty());
482         assertEquals(mImeWindow.getWindowFrames().mFrame.height() - 10,
483                 imeSource.getFrame().height());
484     }
485 
486     @SetupWindows(addWindows = { W_ACTIVITY, W_NAVIGATION_BAR })
487     @Test
testCanSystemBarsBeShownByUser()488     public void testCanSystemBarsBeShownByUser() {
489         Assume.assumeFalse(CLIENT_TRANSIENT);
490         ((TestWindowManagerPolicy) mWm.mPolicy).mIsUserSetupComplete = true;
491         mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
492         mAppWindow.setRequestedVisibleTypes(0, navigationBars());
493         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
494         displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
495         final InsetsSourceProvider navBarProvider = mNavBarWindow.getControllableInsetProvider();
496         navBarProvider.updateControlForTarget(mAppWindow, false);
497         navBarProvider.getSource().setVisible(false);
498 
499         displayPolicy.setCanSystemBarsBeShownByUser(false);
500         displayPolicy.requestTransientBars(mNavBarWindow, true);
501         assertFalse(mDisplayContent.getInsetsPolicy().isTransient(navigationBars()));
502 
503         displayPolicy.setCanSystemBarsBeShownByUser(true);
504         displayPolicy.requestTransientBars(mNavBarWindow, true);
505         assertTrue(mDisplayContent.getInsetsPolicy().isTransient(navigationBars()));
506     }
507 
508     @UseTestDisplay(addWindows = { W_NAVIGATION_BAR })
509     @Test
testTransientBarsSuppressedOnDreams()510     public void testTransientBarsSuppressedOnDreams() {
511         Assume.assumeFalse(CLIENT_TRANSIENT);
512         final WindowState win = createDreamWindow();
513 
514         ((TestWindowManagerPolicy) mWm.mPolicy).mIsUserSetupComplete = true;
515         win.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
516         win.setRequestedVisibleTypes(0, navigationBars());
517 
518         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
519         displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
520         final InsetsSourceProvider navBarProvider = mNavBarWindow.getControllableInsetProvider();
521         navBarProvider.updateControlForTarget(win, false);
522         navBarProvider.getSource().setVisible(false);
523 
524         displayPolicy.setCanSystemBarsBeShownByUser(true);
525         displayPolicy.requestTransientBars(mNavBarWindow, true);
526 
527         assertFalse(mDisplayContent.getInsetsPolicy().isTransient(navigationBars()));
528     }
529 }
530