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 android.server.wm; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotEquals; 22 import static org.junit.Assert.assertNotSame; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertSame; 25 import static org.junit.Assert.assertTrue; 26 27 import android.graphics.Insets; 28 import android.graphics.Rect; 29 import android.platform.test.annotations.Presubmit; 30 import android.view.DisplayCutout; 31 import android.view.WindowInsets; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.util.Collections; 40 41 /** 42 * Test {@link WindowInsets}. 43 */ 44 @SmallTest 45 @RunWith(AndroidJUnit4.class) 46 @Presubmit 47 public class WindowInsetsTest { 48 49 private static final DisplayCutout CUTOUT = new DisplayCutout(new Rect(0, 10, 0, 0), 50 Collections.singletonList(new Rect(5, 0, 15, 10))); 51 private static final DisplayCutout CUTOUT2 = new DisplayCutout(new Rect(0, 15, 0, 0), 52 Collections.singletonList(new Rect(5, 0, 15, 15))); 53 private static final int INSET_LEFT = 1; 54 private static final int INSET_TOP = 2; 55 private static final int INSET_RIGHT = 3; 56 private static final int INSET_BOTTOM = 4; 57 58 @Test 59 public void testBuilder() { 60 final WindowInsets insets = new WindowInsets.Builder() 61 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 62 .setStableInsets(Insets.of(5, 6, 7, 8)) 63 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 64 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 65 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 66 .setDisplayCutout(CUTOUT) 67 .build(); 68 69 assertEquals(Insets.of(1, 2, 3, 4), insets.getSystemWindowInsets()); 70 assertEquals(Insets.of(5, 6, 7, 8), insets.getStableInsets()); 71 assertEquals(Insets.of(9, 10, 11, 12), insets.getSystemGestureInsets()); 72 assertEquals(Insets.of(13, 14, 15, 16), insets.getMandatorySystemGestureInsets()); 73 assertEquals(Insets.of(17, 18, 19, 20), insets.getTappableElementInsets()); 74 assertSame(CUTOUT, insets.getDisplayCutout()); 75 } 76 77 @Test 78 public void testBuilder_copy() { 79 final WindowInsets insets = new WindowInsets.Builder() 80 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 81 .setStableInsets(Insets.of(5, 6, 7, 8)) 82 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 83 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 84 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 85 .setDisplayCutout(CUTOUT) 86 .build(); 87 final WindowInsets copy = new WindowInsets.Builder(insets).build(); 88 89 assertEquals(insets, copy); 90 } 91 92 @Test 93 public void testBuilder_consumed() { 94 final WindowInsets insets = new WindowInsets.Builder() 95 .build(); 96 97 assertFalse(insets.hasSystemWindowInsets()); 98 assertFalse(insets.hasStableInsets()); 99 assertEquals(Insets.NONE, insets.getSystemGestureInsets()); 100 assertNull(insets.getDisplayCutout()); 101 assertTrue(insets.isConsumed()); 102 } 103 104 @Test 105 public void testBuilder_emptyCutout() { 106 final WindowInsets insets = new WindowInsets.Builder() 107 .setDisplayCutout(null) 108 .build(); 109 110 assertFalse(insets.hasSystemWindowInsets()); 111 assertFalse(insets.hasStableInsets()); 112 assertEquals(Insets.NONE, insets.getSystemGestureInsets()); 113 114 assertNull(insets.getDisplayCutout()); 115 assertFalse(insets.isConsumed()); 116 assertTrue(insets.consumeDisplayCutout().isConsumed()); 117 } 118 119 @Test 120 public void testBuilder_producesImmutableWindowInsets() { 121 final WindowInsets.Builder builder = new WindowInsets.Builder() 122 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 123 .setStableInsets(Insets.of(5, 6, 7, 8)) 124 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 125 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 126 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 127 .setDisplayCutout(CUTOUT); 128 final WindowInsets insets = builder.build(); 129 130 builder.setSystemWindowInsets(Insets.NONE); 131 builder.setStableInsets(Insets.NONE); 132 builder.setDisplayCutout(null); 133 builder.setSystemGestureInsets(Insets.NONE); 134 builder.setMandatorySystemGestureInsets(Insets.NONE); 135 builder.setTappableElementInsets(Insets.NONE); 136 137 assertEquals(Insets.of(1, 2, 3, 4), insets.getSystemWindowInsets()); 138 assertEquals(Insets.of(5, 6, 7, 8), insets.getStableInsets()); 139 assertSame(CUTOUT, insets.getDisplayCutout()); 140 } 141 142 @Test 143 public void testEquality() { 144 final WindowInsets insets = new WindowInsets.Builder() 145 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 146 .setStableInsets(Insets.of(5, 6, 7, 8)) 147 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 148 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 149 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 150 .setDisplayCutout(CUTOUT).build(); 151 152 final WindowInsets insets2 = new WindowInsets.Builder() 153 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 154 .setStableInsets(Insets.of(5, 6, 7, 8)) 155 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 156 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 157 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 158 .setDisplayCutout(CUTOUT).build(); 159 160 assertNotSame("Test setup failed, insets and insets2 should not be identical", 161 insets, insets2); 162 163 assertEquals(insets, insets2); 164 assertEquals(insets.hashCode(), insets2.hashCode()); 165 } 166 167 @Test 168 public void testInEquality_consuming() { 169 final WindowInsets insets = new WindowInsets.Builder() 170 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 171 .setStableInsets(Insets.of(5, 6, 7, 8)) 172 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 173 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 174 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 175 .setDisplayCutout(CUTOUT).build(); 176 177 assertNotEquals(insets, insets.consumeSystemWindowInsets()); 178 assertNotEquals(insets, insets.consumeStableInsets()); 179 assertNotEquals(insets, insets.consumeDisplayCutout()); 180 } 181 182 @Test 183 public void testConsume_systemWindowInsets() { 184 final WindowInsets insets = new WindowInsets.Builder() 185 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 186 .setStableInsets(Insets.of(5, 6, 7, 8)) 187 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 188 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 189 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 190 .setDisplayCutout(CUTOUT).build(); 191 192 final WindowInsets consumed = insets.consumeSystemWindowInsets(); 193 194 assertEquals(Insets.NONE, consumed.getSystemWindowInsets()); 195 assertEquals(insets.getStableInsets(), consumed.getStableInsets()); 196 assertEquals(insets.getDisplayCutout(), consumed.getDisplayCutout()); 197 assertEquals(Insets.NONE, consumed.getSystemGestureInsets()); 198 assertEquals(Insets.NONE, consumed.getMandatorySystemGestureInsets()); 199 assertEquals(Insets.NONE, consumed.getTappableElementInsets()); 200 } 201 202 @Test 203 public void testConsume_stableInsets() { 204 final WindowInsets insets = new WindowInsets.Builder() 205 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 206 .setStableInsets(Insets.of(5, 6, 7, 8)) 207 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 208 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 209 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 210 .setDisplayCutout(CUTOUT).build(); 211 212 final WindowInsets consumed = insets.consumeStableInsets(); 213 214 assertEquals(insets.getSystemWindowInsets(), consumed.getSystemWindowInsets()); 215 assertEquals(Insets.NONE, consumed.getStableInsets()); 216 assertEquals(insets.getDisplayCutout(), consumed.getDisplayCutout()); 217 assertEquals(insets.getSystemGestureInsets(), consumed.getSystemGestureInsets()); 218 assertEquals(insets.getMandatorySystemGestureInsets(), consumed.getMandatorySystemGestureInsets()); 219 assertEquals(insets.getTappableElementInsets(), consumed.getTappableElementInsets()); 220 } 221 222 @Test 223 public void testConsume_displayCutout() { 224 final WindowInsets insets = new WindowInsets.Builder() 225 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 226 .setStableInsets(Insets.of(5, 6, 7, 8)) 227 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 228 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 229 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 230 .setDisplayCutout(CUTOUT).build(); 231 232 final WindowInsets consumed = insets.consumeDisplayCutout(); 233 234 assertEquals(insets.getSystemWindowInsets(), consumed.getSystemWindowInsets()); 235 assertEquals(insets.getStableInsets(), consumed.getStableInsets()); 236 assertNull(consumed.getDisplayCutout()); 237 assertEquals(insets.getSystemGestureInsets(), consumed.getSystemGestureInsets()); 238 assertEquals(insets.getMandatorySystemGestureInsets(), consumed.getMandatorySystemGestureInsets()); 239 assertEquals(insets.getTappableElementInsets(), consumed.getTappableElementInsets()); 240 } 241 242 @Test 243 public void testConsistency_individualSides() { 244 final WindowInsets insets = new WindowInsets.Builder() 245 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 246 .setStableInsets(Insets.of(5, 6, 7, 8)) 247 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 248 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 249 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 250 .setDisplayCutout(CUTOUT).build(); 251 252 assertEquals(insets.getSystemWindowInsets(), Insets.of( 253 insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), 254 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom())); 255 assertEquals(insets.getStableInsets(), Insets.of( 256 insets.getStableInsetLeft(), insets.getStableInsetTop(), 257 insets.getStableInsetRight(), insets.getStableInsetBottom())); 258 } 259 260 @Test 261 @SuppressWarnings("deprecation") 262 public void testReplacingConsumedSystemWindowInset_staysZeroAndConsumed() { 263 final WindowInsets consumed = new WindowInsets.Builder().build(); 264 final WindowInsets replaced = consumed.replaceSystemWindowInsets(new Rect(1, 2, 3, 4)); 265 266 assertEquals(Insets.NONE, replaced.getSystemWindowInsets()); 267 assertTrue(replaced.isConsumed()); 268 } 269 270 @Test 271 @SuppressWarnings("deprecation") 272 public void testReplacingSystemWindowInsets_works() { 273 final WindowInsets replaced = new WindowInsets.Builder() 274 .setSystemWindowInsets(Insets.of(100, 200, 300, 400)) 275 .setStableInsets(Insets.of(5, 6, 7, 8)) 276 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 277 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 278 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 279 .setDisplayCutout(CUTOUT).build() 280 .replaceSystemWindowInsets(new Rect(1, 2, 3, 4)); 281 final WindowInsets expected = new WindowInsets.Builder() 282 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 283 .setStableInsets(Insets.of(5, 6, 7, 8)) 284 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 285 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 286 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 287 .setDisplayCutout(CUTOUT).build(); 288 289 assertEquals(expected, replaced); 290 } 291 292 @Test 293 @SuppressWarnings("deprecation") 294 public void testReplacingSystemWindowInsets_consistencyAcrossOverloads() { 295 final Rect newInsets = new Rect(100, 200, 300, 400); 296 final WindowInsets insets = new WindowInsets.Builder() 297 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 298 .setStableInsets(Insets.of(5, 6, 7, 8)) 299 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 300 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 301 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 302 .setDisplayCutout(CUTOUT).build(); 303 304 assertEquals(insets.replaceSystemWindowInsets(newInsets), 305 insets.replaceSystemWindowInsets(newInsets.left, newInsets.top, newInsets.right, 306 newInsets.bottom)); 307 } 308 309 @Test 310 public void testInEquality_difference() { 311 final WindowInsets insets = new WindowInsets.Builder() 312 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 313 .setStableInsets(Insets.of(5, 6, 7, 8)) 314 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 315 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 316 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 317 .setDisplayCutout(CUTOUT).build(); 318 319 final WindowInsets insetsChangedSysWindowInsets = new WindowInsets.Builder() 320 .setSystemWindowInsets(Insets.of(10, 20, 30, 40)) 321 .setStableInsets(Insets.of(5, 6, 7, 8)) 322 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 323 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 324 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 325 .setDisplayCutout(CUTOUT).build(); 326 327 final WindowInsets insetsChangedStableInsets = new WindowInsets.Builder() 328 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 329 .setStableInsets(Insets.of(50, 60, 70, 80)) 330 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 331 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 332 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 333 .setDisplayCutout(CUTOUT).build(); 334 335 final WindowInsets insetsChangedCutout = new WindowInsets.Builder() 336 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 337 .setStableInsets(Insets.of(5, 6, 7, 8)) 338 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 339 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 340 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 341 .setDisplayCutout(CUTOUT2).build(); 342 343 final WindowInsets insetsChangedGesture = new WindowInsets.Builder() 344 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 345 .setStableInsets(Insets.of(5, 6, 7, 8)) 346 .setSystemGestureInsets(Insets.of(90, 100, 110, 120)) 347 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 348 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 349 .setDisplayCutout(CUTOUT).build(); 350 351 final WindowInsets insetsChangedMandatoryGesture = new WindowInsets.Builder() 352 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 353 .setStableInsets(Insets.of(5, 6, 7, 8)) 354 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 355 .setMandatorySystemGestureInsets(Insets.of(130, 140, 150, 160)) 356 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 357 .setDisplayCutout(CUTOUT).build(); 358 359 final WindowInsets insetsChangedTappableElement = new WindowInsets.Builder() 360 .setSystemWindowInsets(Insets.of(1, 2, 3, 4)) 361 .setStableInsets(Insets.of(5, 6, 7, 8)) 362 .setSystemGestureInsets(Insets.of(9, 10, 11, 12)) 363 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 364 .setTappableElementInsets(Insets.of(170, 180, 190, 200)) 365 .setDisplayCutout(CUTOUT).build(); 366 367 assertNotEquals(insets, insetsChangedSysWindowInsets); 368 assertNotEquals(insets, insetsChangedStableInsets); 369 assertNotEquals(insets, insetsChangedCutout); 370 assertNotEquals(insets, insetsChangedGesture); 371 assertNotEquals(insets, insetsChangedMandatoryGesture); 372 assertNotEquals(insets, insetsChangedTappableElement); 373 } 374 375 @Test 376 public void testInset() { 377 final WindowInsets insets = new WindowInsets.Builder() 378 .setSystemWindowInsets(Insets.of(10, 20, 30, 40)) 379 .setStableInsets(Insets.of(50, 60, 70, 80)) 380 .setSystemGestureInsets(Insets.of(90, 100, 110, 120)) 381 .setMandatorySystemGestureInsets(Insets.of(130, 140, 150, 160)) 382 .setTappableElementInsets(Insets.of(170, 180, 190, 200)) 383 .setDisplayCutout(CUTOUT).build(); 384 385 final WindowInsets insetInsets = insets.inset( 386 INSET_LEFT, INSET_TOP, INSET_RIGHT, INSET_BOTTOM); 387 388 assertEquals(applyInset(insets.getSystemWindowInsets()), 389 insetInsets.getSystemWindowInsets()); 390 assertEquals(applyInset(insets.getStableInsets()), insetInsets.getStableInsets()); 391 assertEquals(applyInset(insets.getSystemGestureInsets()), 392 insetInsets.getSystemGestureInsets()); 393 assertEquals(applyInset(insets.getMandatorySystemGestureInsets()), 394 insetInsets.getMandatorySystemGestureInsets()); 395 assertEquals(applyInset(insets.getTappableElementInsets()), 396 insetInsets.getTappableElementInsets()); 397 assertEquals(applyInset(getCutoutSafeInsets(insets)), getCutoutSafeInsets(insetInsets)); 398 } 399 400 @Test 401 public void testInset_clipsToZero() { 402 final WindowInsets insets = new WindowInsets.Builder() 403 .setSystemWindowInsets(Insets.of(10, 20, 30, 40)) 404 .setStableInsets(Insets.of(50, 60, 70, 80)) 405 .setSystemGestureInsets(Insets.of(90, 100, 110, 120)) 406 .setMandatorySystemGestureInsets(Insets.of(13, 14, 15, 16)) 407 .setTappableElementInsets(Insets.of(17, 18, 19, 20)) 408 .setDisplayCutout(CUTOUT).build(); 409 410 final WindowInsets insetInsets = insets.inset(1000, 1000, 1000, 1000); 411 412 assertEquals(Insets.NONE, insetInsets.getSystemWindowInsets()); 413 assertEquals(Insets.NONE, insetInsets.getStableInsets()); 414 assertEquals(Insets.NONE, insetInsets.getSystemGestureInsets()); 415 assertEquals(Insets.NONE, insetInsets.getMandatorySystemGestureInsets()); 416 assertEquals(Insets.NONE, insetInsets.getTappableElementInsets()); 417 assertNull(insetInsets.getDisplayCutout()); 418 } 419 420 @Test 421 public void testConsumed_copy() { 422 final WindowInsets insets = new WindowInsets.Builder() 423 .setSystemWindowInsets(Insets.of(10, 20, 30, 40)) 424 .setStableInsets(Insets.of(50, 60, 70, 80)) 425 .build(); 426 427 final WindowInsets consumed = insets.consumeSystemWindowInsets().consumeStableInsets(); 428 final WindowInsets copy = new WindowInsets(consumed); 429 assertTrue(copy.isConsumed()); 430 } 431 432 private static Insets applyInset(Insets res) { 433 return Insets.of(Math.max(0, res.left - INSET_LEFT), 434 Math.max(0, res.top - INSET_TOP), 435 Math.max(0, res.right - INSET_RIGHT), 436 Math.max(0, res.bottom - INSET_BOTTOM)); 437 } 438 439 private static Insets getCutoutSafeInsets(WindowInsets insets) { 440 final DisplayCutout dc = insets.getDisplayCutout(); 441 return Insets.of(dc.getSafeInsetLeft(), dc.getSafeInsetTop(), dc.getSafeInsetRight(), 442 dc.getSafeInsetBottom()); 443 } 444 } 445