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