1/* 2 * Copyright (C) 2017 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 17package com.android.server.policy; 18 19import static android.view.Surface.ROTATION_270; 20import static android.view.Surface.ROTATION_90; 21import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; 22import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 23import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 24import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 25import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; 26import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; 27import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 28import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 29import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; 30import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 31import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; 32import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 33import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 34 35import static org.hamcrest.Matchers.equalTo; 36import static org.hamcrest.Matchers.is; 37import static org.junit.Assert.assertEquals; 38import static org.junit.Assert.assertThat; 39 40import android.graphics.PixelFormat; 41import android.graphics.Rect; 42import android.platform.test.annotations.Presubmit; 43import android.support.test.filters.SmallTest; 44import android.support.test.runner.AndroidJUnit4; 45import android.view.DisplayCutout; 46import android.view.WindowManager; 47 48import org.junit.Before; 49import org.junit.Test; 50import org.junit.runner.RunWith; 51 52@RunWith(AndroidJUnit4.class) 53@SmallTest 54@Presubmit 55public class PhoneWindowManagerLayoutTest extends PhoneWindowManagerTestBase { 56 57 private FakeWindowState mAppWindow; 58 59 @Before 60 public void setUp() throws Exception { 61 mAppWindow = new FakeWindowState(); 62 mAppWindow.attrs = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT, 63 TYPE_APPLICATION, 64 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, 65 PixelFormat.TRANSLUCENT); 66 67 addStatusBar(); 68 addNavigationBar(); 69 } 70 71 @Test 72 public void layoutWindowLw_appDrawsBars() throws Exception { 73 mAppWindow.attrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 74 mPolicy.addWindow(mAppWindow); 75 76 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 77 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 78 79 assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0); 80 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 81 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 82 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 83 assertInsetBy(mAppWindow.displayFrame, 0, 0, 0, 0); 84 } 85 86 @Test 87 public void layoutWindowLw_appWontDrawBars() throws Exception { 88 mAppWindow.attrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 89 mPolicy.addWindow(mAppWindow); 90 91 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 92 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 93 94 assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT); 95 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 96 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 97 assertInsetByTopBottom(mAppWindow.decorFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 98 assertInsetByTopBottom(mAppWindow.displayFrame, 0, NAV_BAR_HEIGHT); 99 } 100 101 @Test 102 public void layoutWindowLw_appWontDrawBars_forceStatus() throws Exception { 103 mAppWindow.attrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 104 mAppWindow.attrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 105 mPolicy.addWindow(mAppWindow); 106 107 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 108 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 109 110 assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT); 111 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 112 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 113 assertInsetByTopBottom(mAppWindow.decorFrame, 0, NAV_BAR_HEIGHT); 114 assertInsetByTopBottom(mAppWindow.displayFrame, 0, NAV_BAR_HEIGHT); 115 } 116 117 @Test 118 public void addingWindow_doesNotTamperWithSysuiFlags() { 119 mAppWindow.attrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 120 mPolicy.addWindow(mAppWindow); 121 122 assertEquals(0, mAppWindow.attrs.systemUiVisibility); 123 assertEquals(0, mAppWindow.attrs.subtreeSystemUiVisibility); 124 } 125 126 @Test 127 public void layoutWindowLw_withDisplayCutout() { 128 addDisplayCutout(); 129 130 mPolicy.addWindow(mAppWindow); 131 132 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 133 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 134 135 assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0); 136 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 137 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 138 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 139 assertInsetByTopBottom(mAppWindow.displayFrame, 0, 0); 140 } 141 142 @Test 143 public void layoutWindowLw_withhDisplayCutout_never() { 144 addDisplayCutout(); 145 146 mAppWindow.attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; 147 mPolicy.addWindow(mAppWindow); 148 149 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 150 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 151 152 assertInsetByTopBottom(mAppWindow.parentFrame, STATUS_BAR_HEIGHT, 0); 153 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 154 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 155 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 156 assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, 0); 157 } 158 159 @Test 160 public void layoutWindowLw_withDisplayCutout_layoutFullscreen() { 161 addDisplayCutout(); 162 163 mAppWindow.attrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 164 mPolicy.addWindow(mAppWindow); 165 166 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 167 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 168 169 assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0); 170 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 171 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 172 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 173 assertInsetBy(mAppWindow.displayFrame, 0, 0, 0, 0); 174 } 175 176 @Test 177 public void layoutWindowLw_withDisplayCutout_fullscreen() { 178 addDisplayCutout(); 179 180 mAppWindow.attrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; 181 mPolicy.addWindow(mAppWindow); 182 183 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 184 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 185 186 assertInsetByTopBottom(mAppWindow.parentFrame, STATUS_BAR_HEIGHT, 0); 187 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 188 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 189 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 190 assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, 0); 191 } 192 193 @Test 194 public void layoutWindowLw_withDisplayCutout_fullscreenInCutout() { 195 addDisplayCutout(); 196 197 mAppWindow.attrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; 198 mAppWindow.attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 199 mPolicy.addWindow(mAppWindow); 200 201 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 202 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 203 204 assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0); 205 assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 206 assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 207 assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0); 208 assertInsetByTopBottom(mAppWindow.displayFrame, 0, 0); 209 } 210 211 212 @Test 213 public void layoutWindowLw_withDisplayCutout_landscape() { 214 addDisplayCutout(); 215 setRotation(ROTATION_90); 216 mPolicy.addWindow(mAppWindow); 217 218 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 219 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 220 221 assertInsetBy(mAppWindow.parentFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 222 assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 223 assertInsetBy(mAppWindow.contentFrame, 224 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 225 assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0); 226 assertInsetBy(mAppWindow.displayFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 227 } 228 229 @Test 230 public void layoutWindowLw_withDisplayCutout_seascape() { 231 addDisplayCutout(); 232 setRotation(ROTATION_270); 233 mPolicy.addWindow(mAppWindow); 234 235 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 236 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 237 238 assertInsetBy(mAppWindow.parentFrame, 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); 239 assertInsetBy(mAppWindow.stableFrame, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); 240 assertInsetBy(mAppWindow.contentFrame, 241 NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); 242 assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0); 243 assertInsetBy(mAppWindow.displayFrame, 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); 244 } 245 246 @Test 247 public void layoutWindowLw_withDisplayCutout_fullscreen_landscape() { 248 addDisplayCutout(); 249 setRotation(ROTATION_90); 250 251 mAppWindow.attrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 252 mPolicy.addWindow(mAppWindow); 253 254 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 255 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 256 257 assertInsetBy(mAppWindow.parentFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); 258 assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 259 assertInsetBy(mAppWindow.contentFrame, 260 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 261 assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0); 262 } 263 264 @Test 265 public void layoutWindowLw_withDisplayCutout_floatingInScreen() { 266 addDisplayCutout(); 267 268 mAppWindow.attrs.flags = FLAG_LAYOUT_IN_SCREEN; 269 mAppWindow.attrs.type = TYPE_APPLICATION_OVERLAY; 270 mAppWindow.attrs.width = DISPLAY_WIDTH; 271 mAppWindow.attrs.height = DISPLAY_HEIGHT; 272 mPolicy.addWindow(mAppWindow); 273 274 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 275 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 276 277 assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT); 278 assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); 279 } 280 281 @Test 282 public void layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape() { 283 addDisplayCutout(); 284 setRotation(ROTATION_90); 285 286 mAppWindow.attrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 287 mAppWindow.attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 288 mPolicy.addWindow(mAppWindow); 289 290 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 291 mPolicy.layoutWindowLw(mAppWindow, null, mFrames); 292 293 assertInsetBy(mAppWindow.parentFrame, 0, 0, 0, 0); 294 assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 295 assertInsetBy(mAppWindow.contentFrame, 296 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); 297 assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0); 298 } 299 300 @Test 301 public void layoutHint_screenDecorWindow() { 302 addDisplayCutout(); 303 mAppWindow.attrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR; 304 305 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 306 307 final Rect frame = new Rect(); 308 final Rect content = new Rect(); 309 final Rect stable = new Rect(); 310 final Rect outsets = new Rect(); 311 final DisplayCutout.ParcelableWrapper cutout = new DisplayCutout.ParcelableWrapper(); 312 mPolicy.getLayoutHintLw(mAppWindow.attrs, null /* taskBounds */, mFrames, frame, content, 313 stable, outsets, cutout); 314 315 assertThat(frame, equalTo(mFrames.mUnrestricted)); 316 assertThat(content, equalTo(new Rect())); 317 assertThat(stable, equalTo(new Rect())); 318 assertThat(outsets, equalTo(new Rect())); 319 assertThat(cutout.get(), equalTo(DisplayCutout.NO_CUTOUT)); 320 } 321 322 @Test 323 public void layoutHint_appWindow() { 324 // Initialize DisplayFrames 325 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 326 327 final Rect outFrame = new Rect(); 328 final Rect outContentInsets = new Rect(); 329 final Rect outStableInsets = new Rect(); 330 final Rect outOutsets = new Rect(); 331 final DisplayCutout.ParcelableWrapper outDisplayCutout = 332 new DisplayCutout.ParcelableWrapper(); 333 334 mPolicy.getLayoutHintLw(mAppWindow.attrs, null, mFrames, outFrame, outContentInsets, 335 outStableInsets, outOutsets, outDisplayCutout); 336 337 assertThat(outFrame, is(mFrames.mUnrestricted)); 338 assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); 339 assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); 340 assertThat(outOutsets, is(new Rect())); 341 assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); 342 } 343 344 @Test 345 public void layoutHint_appWindowInTask() { 346 // Initialize DisplayFrames 347 mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); 348 349 final Rect taskBounds = new Rect(100, 100, 200, 200); 350 351 final Rect outFrame = new Rect(); 352 final Rect outContentInsets = new Rect(); 353 final Rect outStableInsets = new Rect(); 354 final Rect outOutsets = new Rect(); 355 final DisplayCutout.ParcelableWrapper outDisplayCutout = 356 new DisplayCutout.ParcelableWrapper(); 357 358 mPolicy.getLayoutHintLw(mAppWindow.attrs, taskBounds, mFrames, outFrame, outContentInsets, 359 outStableInsets, outOutsets, outDisplayCutout); 360 361 assertThat(outFrame, is(taskBounds)); 362 assertThat(outContentInsets, is(new Rect())); 363 assertThat(outStableInsets, is(new Rect())); 364 assertThat(outOutsets, is(new Rect())); 365 assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); 366 } 367}