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.view.Gravity.BOTTOM; 20 import static android.view.Gravity.LEFT; 21 import static android.view.Gravity.RIGHT; 22 import static android.view.Gravity.TOP; 23 import static android.view.Surface.ROTATION_0; 24 import static android.view.Surface.ROTATION_270; 25 import static android.view.Surface.ROTATION_90; 26 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; 27 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 28 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 29 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 30 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 31 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; 32 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 33 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 34 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 35 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; 36 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; 37 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; 38 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 39 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 40 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 41 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 42 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 43 44 import static org.hamcrest.Matchers.is; 45 import static org.junit.Assert.assertEquals; 46 import static org.junit.Assert.assertThat; 47 import static org.mockito.Mockito.doNothing; 48 import static org.mockito.Mockito.spy; 49 50 import android.graphics.Insets; 51 import android.graphics.PixelFormat; 52 import android.graphics.Rect; 53 import android.platform.test.annotations.Presubmit; 54 import android.util.Pair; 55 import android.view.DisplayCutout; 56 import android.view.DisplayInfo; 57 import android.view.WindowManager; 58 59 import androidx.test.filters.SmallTest; 60 61 import com.android.server.policy.WindowManagerPolicy; 62 import com.android.server.wm.utils.WmDisplayCutout; 63 64 import org.junit.Before; 65 import org.junit.Test; 66 67 @SmallTest 68 @Presubmit 69 public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { 70 71 private DisplayFrames mFrames; 72 private WindowState mWindow; 73 private int mRotation = ROTATION_0; 74 private boolean mHasDisplayCutout; 75 private static final int DECOR_WINDOW_INSET = 50; 76 77 @Before setUp()78 public void setUp() throws Exception { 79 updateDisplayFrames(); 80 81 mWindow = spy(createWindow(null, TYPE_APPLICATION, "window")); 82 // We only test window frames set by DisplayPolicy, so here prevents computeFrameLw from 83 // changing those frames. 84 doNothing().when(mWindow).computeFrameLw(); 85 86 final WindowManager.LayoutParams attrs = mWindow.mAttrs; 87 attrs.width = MATCH_PARENT; 88 attrs.height = MATCH_PARENT; 89 attrs.flags = 90 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 91 attrs.format = PixelFormat.TRANSLUCENT; 92 } 93 setRotation(int rotation)94 public void setRotation(int rotation) { 95 mRotation = rotation; 96 updateDisplayFrames(); 97 } 98 addDisplayCutout()99 public void addDisplayCutout() { 100 mHasDisplayCutout = true; 101 updateDisplayFrames(); 102 } 103 updateDisplayFrames()104 private void updateDisplayFrames() { 105 final Pair<DisplayInfo, WmDisplayCutout> info = displayInfoAndCutoutForRotation(mRotation, 106 mHasDisplayCutout); 107 mFrames = new DisplayFrames(mDisplayContent.getDisplayId(), info.first, info.second); 108 } 109 110 @Test addingWindow_doesNotTamperWithSysuiFlags()111 public void addingWindow_doesNotTamperWithSysuiFlags() { 112 mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 113 addWindow(mWindow); 114 115 assertEquals(0, mWindow.mAttrs.systemUiVisibility); 116 assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility); 117 } 118 119 @Test layoutWindowLw_appDrawsBars()120 public void layoutWindowLw_appDrawsBars() { 121 synchronized (mWm.mGlobalLock) { 122 mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 123 addWindow(mWindow); 124 125 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 126 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 127 128 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 129 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 130 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 131 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 132 assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); 133 } 134 } 135 136 @Test layoutWindowLw_appWontDrawBars()137 public void layoutWindowLw_appWontDrawBars() { 138 synchronized (mWm.mGlobalLock) { 139 mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 140 addWindow(mWindow); 141 142 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 143 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 144 145 assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); 146 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 147 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 148 assertInsetByTopBottom(mWindow.getDecorFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 149 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT); 150 } 151 } 152 153 @Test layoutWindowLw_appWontDrawBars_forceStatusAndNav()154 public void layoutWindowLw_appWontDrawBars_forceStatusAndNav() throws Exception { 155 synchronized (mWm.mGlobalLock) { 156 mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 157 mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; 158 addWindow(mWindow); 159 160 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 161 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 162 163 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 164 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 165 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 166 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 167 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); 168 } 169 } 170 171 @Test layoutWindowLw_keyguardDialog_hideNav()172 public void layoutWindowLw_keyguardDialog_hideNav() { 173 synchronized (mWm.mGlobalLock) { 174 mWindow.mAttrs.type = TYPE_KEYGUARD_DIALOG; 175 mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 176 mWindow.mAttrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 177 addWindow(mWindow); 178 179 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* uiMode */); 180 mDisplayPolicy.layoutWindowLw(mWindow, null /* attached */, mFrames); 181 182 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 183 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 184 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 185 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 186 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); 187 } 188 } 189 190 @Test layoutWindowLw_withDisplayCutout()191 public void layoutWindowLw_withDisplayCutout() { 192 synchronized (mWm.mGlobalLock) { 193 addDisplayCutout(); 194 195 addWindow(mWindow); 196 197 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 198 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 199 200 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 201 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 202 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 203 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 204 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); 205 } 206 } 207 208 @Test layoutWindowLw_withDisplayCutout_never()209 public void layoutWindowLw_withDisplayCutout_never() { 210 synchronized (mWm.mGlobalLock) { 211 addDisplayCutout(); 212 213 mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; 214 addWindow(mWindow); 215 216 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 217 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 218 219 assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); 220 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 221 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 222 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 223 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); 224 } 225 } 226 227 @Test layoutWindowLw_withDisplayCutout_layoutFullscreen()228 public void layoutWindowLw_withDisplayCutout_layoutFullscreen() { 229 synchronized (mWm.mGlobalLock) { 230 addDisplayCutout(); 231 232 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 233 addWindow(mWindow); 234 235 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 236 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 237 238 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 239 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 240 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 241 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 242 assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); 243 } 244 } 245 246 @Test layoutWindowLw_withDisplayCutout_fullscreen()247 public void layoutWindowLw_withDisplayCutout_fullscreen() { 248 synchronized (mWm.mGlobalLock) { 249 addDisplayCutout(); 250 251 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; 252 addWindow(mWindow); 253 254 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 255 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 256 257 assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); 258 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 259 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 260 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 261 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); 262 } 263 } 264 265 @Test layoutWindowLw_withDisplayCutout_fullscreenInCutout()266 public void layoutWindowLw_withDisplayCutout_fullscreenInCutout() { 267 synchronized (mWm.mGlobalLock) { 268 addDisplayCutout(); 269 270 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; 271 mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 272 addWindow(mWindow); 273 274 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 275 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 276 277 assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); 278 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 279 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 280 assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); 281 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); 282 } 283 } 284 285 286 @Test layoutWindowLw_withDisplayCutout_landscape()287 public void layoutWindowLw_withDisplayCutout_landscape() { 288 synchronized (mWm.mGlobalLock) { 289 addDisplayCutout(); 290 setRotation(ROTATION_90); 291 addWindow(mWindow); 292 293 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 294 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 295 296 assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 297 assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 298 assertInsetBy(mWindow.getContentFrameLw(), 299 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 300 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 301 assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 302 } 303 } 304 305 @Test layoutWindowLw_withDisplayCutout_seascape()306 public void layoutWindowLw_withDisplayCutout_seascape() { 307 synchronized (mWm.mGlobalLock) { 308 addDisplayCutout(); 309 setRotation(ROTATION_270); 310 addWindow(mWindow); 311 312 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 313 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 314 315 assertInsetBy(mWindow.getParentFrame(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); 316 assertInsetBy(mWindow.getStableFrameLw(), NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); 317 assertInsetBy(mWindow.getContentFrameLw(), 318 NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); 319 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 320 assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); 321 } 322 } 323 324 @Test layoutWindowLw_withDisplayCutout_fullscreen_landscape()325 public void layoutWindowLw_withDisplayCutout_fullscreen_landscape() { 326 synchronized (mWm.mGlobalLock) { 327 addDisplayCutout(); 328 setRotation(ROTATION_90); 329 330 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 331 addWindow(mWindow); 332 333 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 334 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 335 336 assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 337 assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 338 assertInsetBy(mWindow.getContentFrameLw(), 339 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 340 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 341 } 342 } 343 344 @Test layoutWindowLw_withDisplayCutout_floatingInScreen()345 public void layoutWindowLw_withDisplayCutout_floatingInScreen() { 346 synchronized (mWm.mGlobalLock) { 347 addDisplayCutout(); 348 349 mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN; 350 mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY; 351 mWindow.mAttrs.width = DISPLAY_WIDTH; 352 mWindow.mAttrs.height = DISPLAY_HEIGHT; 353 addWindow(mWindow); 354 355 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 356 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 357 358 assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); 359 assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 360 } 361 } 362 363 @Test layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape()364 public void layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape() { 365 synchronized (mWm.mGlobalLock) { 366 addDisplayCutout(); 367 setRotation(ROTATION_90); 368 369 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 370 mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 371 addWindow(mWindow); 372 373 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 374 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 375 376 assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); 377 assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 378 assertInsetBy(mWindow.getContentFrameLw(), 379 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 380 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 381 } 382 } 383 384 @Test layoutWindowLw_withForwardInset_SoftInputAdjustResize()385 public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() { 386 synchronized (mWm.mGlobalLock) { 387 mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE; 388 addWindow(mWindow); 389 390 final int forwardedInsetBottom = 50; 391 mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom)); 392 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 393 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 394 395 assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); 396 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 397 assertInsetByTopBottom(mWindow.getContentFrameLw(), 398 STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom); 399 assertInsetByTopBottom(mWindow.getVisibleFrameLw(), 400 STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom); 401 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 402 assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); 403 } 404 } 405 406 @Test layoutWindowLw_withForwardInset_SoftInputAdjustNothing()407 public void layoutWindowLw_withForwardInset_SoftInputAdjustNothing() { 408 synchronized (mWm.mGlobalLock) { 409 mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING; 410 addWindow(mWindow); 411 412 final int forwardedInsetBottom = 50; 413 mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom)); 414 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 415 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 416 417 assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); 418 assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 419 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 420 assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 421 assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); 422 assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); 423 } 424 } 425 426 @Test layoutHint_appWindow()427 public void layoutHint_appWindow() { 428 synchronized (mWm.mGlobalLock) { 429 // Initialize DisplayFrames 430 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 431 432 final Rect outFrame = new Rect(); 433 final Rect outContentInsets = new Rect(); 434 final Rect outStableInsets = new Rect(); 435 final Rect outOutsets = new Rect(); 436 final DisplayCutout.ParcelableWrapper outDisplayCutout = 437 new DisplayCutout.ParcelableWrapper(); 438 439 mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, null, mFrames, 440 false /* floatingStack */, outFrame, outContentInsets, outStableInsets, 441 outOutsets, outDisplayCutout); 442 443 assertThat(outFrame, is(mFrames.mUnrestricted)); 444 assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); 445 assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); 446 assertThat(outOutsets, is(new Rect())); 447 assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); 448 } 449 } 450 451 @Test layoutHint_appWindowInTask()452 public void layoutHint_appWindowInTask() { 453 synchronized (mWm.mGlobalLock) { 454 // Initialize DisplayFrames 455 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 456 457 final Rect taskBounds = new Rect(100, 100, 200, 200); 458 459 final Rect outFrame = new Rect(); 460 final Rect outContentInsets = new Rect(); 461 final Rect outStableInsets = new Rect(); 462 final Rect outOutsets = new Rect(); 463 final DisplayCutout.ParcelableWrapper outDisplayCutout = 464 new DisplayCutout.ParcelableWrapper(); 465 466 mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, 467 false /* floatingStack */, outFrame, outContentInsets, outStableInsets, 468 outOutsets, outDisplayCutout); 469 470 assertThat(outFrame, is(taskBounds)); 471 assertThat(outContentInsets, is(new Rect())); 472 assertThat(outStableInsets, is(new Rect())); 473 assertThat(outOutsets, is(new Rect())); 474 assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); 475 } 476 } 477 478 @Test layoutHint_appWindowInTask_outsideContentFrame()479 public void layoutHint_appWindowInTask_outsideContentFrame() { 480 synchronized (mWm.mGlobalLock) { 481 // Initialize DisplayFrames 482 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 483 484 // Task is in the nav bar area (usually does not happen, but this is similar enough to 485 // the possible overlap with the IME) 486 final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1, 487 200, mFrames.mContent.bottom + 10); 488 489 final Rect outFrame = new Rect(); 490 final Rect outContentInsets = new Rect(); 491 final Rect outStableInsets = new Rect(); 492 final Rect outOutsets = new Rect(); 493 final DisplayCutout.ParcelableWrapper outDisplayCutout = 494 new DisplayCutout.ParcelableWrapper(); 495 496 mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, 497 true /* floatingStack */, outFrame, outContentInsets, outStableInsets, 498 outOutsets, outDisplayCutout); 499 500 assertThat(outFrame, is(taskBounds)); 501 assertThat(outContentInsets, is(new Rect())); 502 assertThat(outStableInsets, is(new Rect())); 503 assertThat(outOutsets, is(new Rect())); 504 assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); 505 } 506 } 507 508 @Test forceShowSystemBars_clearsSystemUIFlags()509 public void forceShowSystemBars_clearsSystemUIFlags() { 510 synchronized (mWm.mGlobalLock) { 511 mDisplayPolicy.mLastSystemUiFlags |= SYSTEM_UI_FLAG_FULLSCREEN; 512 mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 513 mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 514 mWindow.mSystemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN; 515 mDisplayPolicy.setForceShowSystemBars(true); 516 addWindow(mWindow); 517 518 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 519 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 520 // triggers updateSystemUiVisibilityLw which will reset the flags as needed 521 int finishPostLayoutPolicyLw = mDisplayPolicy.focusChangedLw(mWindow, mWindow); 522 523 assertEquals(WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT, finishPostLayoutPolicyLw); 524 assertEquals(0, mDisplayPolicy.mLastSystemUiFlags); 525 assertEquals(0, mWindow.mAttrs.systemUiVisibility); 526 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 527 } 528 } 529 530 @Test testScreenDecorWindows()531 public void testScreenDecorWindows() { 532 synchronized (mWm.mGlobalLock) { 533 final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, 534 "decorWindow"); 535 decorWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE; 536 decorWindow.mAttrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR; 537 addWindow(decorWindow); 538 addWindow(mWindow); 539 540 // Decor on top 541 updateDecorWindow(decorWindow, MATCH_PARENT, DECOR_WINDOW_INSET, TOP); 542 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 543 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 544 assertInsetByTopBottom(mWindow.getContentFrameLw(), DECOR_WINDOW_INSET, NAV_BAR_HEIGHT); 545 546 // Decor on bottom 547 updateDecorWindow(decorWindow, MATCH_PARENT, DECOR_WINDOW_INSET, BOTTOM); 548 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 549 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 550 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, 551 DECOR_WINDOW_INSET); 552 553 // Decor on the left 554 updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, MATCH_PARENT, LEFT); 555 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 556 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 557 assertInsetBy(mWindow.getContentFrameLw(), DECOR_WINDOW_INSET, STATUS_BAR_HEIGHT, 0, 558 NAV_BAR_HEIGHT); 559 560 // Decor on the right 561 updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, MATCH_PARENT, RIGHT); 562 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 563 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 564 assertInsetBy(mWindow.getContentFrameLw(), 0, STATUS_BAR_HEIGHT, DECOR_WINDOW_INSET, 565 NAV_BAR_HEIGHT); 566 567 // Decor not allowed as inset 568 updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, DECOR_WINDOW_INSET, TOP); 569 mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 570 mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); 571 assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 572 } 573 } 574 updateDecorWindow(WindowState decorWindow, int width, int height, int gravity)575 private void updateDecorWindow(WindowState decorWindow, int width, int height, int gravity) { 576 decorWindow.mAttrs.width = width; 577 decorWindow.mAttrs.height = height; 578 decorWindow.mAttrs.gravity = gravity; 579 decorWindow.setRequestedSize(width, height); 580 } 581 582 /** 583 * Asserts that {@code actual} is inset by the given amounts from the full display rect. 584 * 585 * Convenience wrapper for when only the top and bottom inset are non-zero. 586 */ assertInsetByTopBottom(Rect actual, int expectedInsetTop, int expectedInsetBottom)587 private void assertInsetByTopBottom(Rect actual, int expectedInsetTop, 588 int expectedInsetBottom) { 589 assertInsetBy(actual, 0, expectedInsetTop, 0, expectedInsetBottom); 590 } 591 592 /** Asserts that {@code actual} is inset by the given amounts from the full display rect. */ assertInsetBy(Rect actual, int expectedInsetLeft, int expectedInsetTop, int expectedInsetRight, int expectedInsetBottom)593 private void assertInsetBy(Rect actual, int expectedInsetLeft, int expectedInsetTop, 594 int expectedInsetRight, int expectedInsetBottom) { 595 assertEquals(new Rect(expectedInsetLeft, expectedInsetTop, 596 mFrames.mDisplayWidth - expectedInsetRight, 597 mFrames.mDisplayHeight - expectedInsetBottom), actual); 598 } 599 } 600