WindowContainerTests.java revision f0a6fdbf53882949db0a141693dd33302b42d51b
1/* 2 * Copyright (C) 2016 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.wm; 18 19import org.junit.Test; 20import org.junit.runner.RunWith; 21 22import android.content.res.Configuration; 23import android.platform.test.annotations.Presubmit; 24import android.support.test.filters.SmallTest; 25import android.support.test.runner.AndroidJUnit4; 26 27import java.util.Comparator; 28 29import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 30import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; 31import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 32import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; 33import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; 34import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 35import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 36 37import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; 38import static com.android.server.wm.WindowContainer.POSITION_TOP; 39 40import static org.junit.Assert.assertEquals; 41import static org.junit.Assert.assertFalse; 42import static org.junit.Assert.assertNotNull; 43import static org.junit.Assert.assertNull; 44import static org.junit.Assert.assertTrue; 45 46/** 47 * Test class for {@link WindowContainer}. 48 * 49 * Build/Install/Run: 50 * bit FrameworksServicesTests:com.android.server.wm.WindowContainerTests 51 */ 52@SmallTest 53@Presubmit 54@RunWith(AndroidJUnit4.class) 55public class WindowContainerTests extends WindowTestsBase { 56 57 @Test 58 public void testCreation() throws Exception { 59 final TestWindowContainer w = new TestWindowContainerBuilder().setLayer(0).build(); 60 assertNull("window must have no parent", w.getParentWindow()); 61 assertEquals("window must have no children", 0, w.getChildrenCount()); 62 } 63 64 @Test 65 public void testAdd() throws Exception { 66 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 67 final TestWindowContainer root = builder.setLayer(0).build(); 68 69 final TestWindowContainer layer1 = root.addChildWindow(builder.setLayer(1)); 70 final TestWindowContainer secondLayer1 = root.addChildWindow(builder.setLayer(1)); 71 final TestWindowContainer layer2 = root.addChildWindow(builder.setLayer(2)); 72 final TestWindowContainer layerNeg1 = root.addChildWindow(builder.setLayer(-1)); 73 final TestWindowContainer layerNeg2 = root.addChildWindow(builder.setLayer(-2)); 74 final TestWindowContainer secondLayerNeg1 = root.addChildWindow(builder.setLayer(-1)); 75 final TestWindowContainer layer0 = root.addChildWindow(builder.setLayer(0)); 76 77 assertEquals(7, root.getChildrenCount()); 78 79 assertEquals(root, layer1.getParentWindow()); 80 assertEquals(root, secondLayer1.getParentWindow()); 81 assertEquals(root, layer2.getParentWindow()); 82 assertEquals(root, layerNeg1.getParentWindow()); 83 assertEquals(root, layerNeg2.getParentWindow()); 84 assertEquals(root, secondLayerNeg1.getParentWindow()); 85 assertEquals(root, layer0.getParentWindow()); 86 87 assertEquals(layerNeg2, root.getChildAt(0)); 88 assertEquals(secondLayerNeg1, root.getChildAt(1)); 89 assertEquals(layerNeg1, root.getChildAt(2)); 90 assertEquals(layer0, root.getChildAt(3)); 91 assertEquals(layer1, root.getChildAt(4)); 92 assertEquals(secondLayer1, root.getChildAt(5)); 93 assertEquals(layer2, root.getChildAt(6)); 94 95 assertTrue(layer1.mOnParentSetCalled); 96 assertTrue(secondLayer1.mOnParentSetCalled); 97 assertTrue(layer2.mOnParentSetCalled); 98 assertTrue(layerNeg1.mOnParentSetCalled); 99 assertTrue(layerNeg2.mOnParentSetCalled); 100 assertTrue(secondLayerNeg1.mOnParentSetCalled); 101 assertTrue(layer0.mOnParentSetCalled); 102 } 103 104 @Test 105 public void testAdd_AlreadyHasParent() throws Exception { 106 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 107 final TestWindowContainer root = builder.setLayer(0).build(); 108 109 final TestWindowContainer child1 = root.addChildWindow(); 110 final TestWindowContainer child2 = root.addChildWindow(); 111 112 boolean gotException = false; 113 try { 114 child1.addChildWindow(child2); 115 } catch (IllegalArgumentException e) { 116 gotException = true; 117 } 118 assertTrue(gotException); 119 120 gotException = false; 121 try { 122 root.addChildWindow(child2); 123 } catch (IllegalArgumentException e) { 124 gotException = true; 125 } 126 assertTrue(gotException); 127 } 128 129 @Test 130 public void testHasChild() throws Exception { 131 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 132 final TestWindowContainer root = builder.setLayer(0).build(); 133 134 final TestWindowContainer child1 = root.addChildWindow(); 135 final TestWindowContainer child2 = root.addChildWindow(); 136 final TestWindowContainer child11 = child1.addChildWindow(); 137 final TestWindowContainer child12 = child1.addChildWindow(); 138 final TestWindowContainer child21 = child2.addChildWindow(); 139 140 assertEquals(2, root.getChildrenCount()); 141 assertEquals(2, child1.getChildrenCount()); 142 assertEquals(1, child2.getChildrenCount()); 143 144 assertTrue(root.hasChild(child1)); 145 assertTrue(root.hasChild(child2)); 146 assertTrue(root.hasChild(child11)); 147 assertTrue(root.hasChild(child12)); 148 assertTrue(root.hasChild(child21)); 149 150 assertTrue(child1.hasChild(child11)); 151 assertTrue(child1.hasChild(child12)); 152 assertFalse(child1.hasChild(child21)); 153 154 assertTrue(child2.hasChild(child21)); 155 assertFalse(child2.hasChild(child11)); 156 assertFalse(child2.hasChild(child12)); 157 } 158 159 @Test 160 public void testRemoveImmediately() throws Exception { 161 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 162 final TestWindowContainer root = builder.setLayer(0).build(); 163 164 final TestWindowContainer child1 = root.addChildWindow(); 165 final TestWindowContainer child2 = root.addChildWindow(); 166 final TestWindowContainer child11 = child1.addChildWindow(); 167 final TestWindowContainer child12 = child1.addChildWindow(); 168 final TestWindowContainer child21 = child2.addChildWindow(); 169 170 assertNotNull(child12.getParentWindow()); 171 child12.removeImmediately(); 172 assertNull(child12.getParentWindow()); 173 assertEquals(1, child1.getChildrenCount()); 174 assertFalse(child1.hasChild(child12)); 175 assertFalse(root.hasChild(child12)); 176 177 assertTrue(root.hasChild(child2)); 178 assertNotNull(child2.getParentWindow()); 179 child2.removeImmediately(); 180 assertNull(child2.getParentWindow()); 181 assertNull(child21.getParentWindow()); 182 assertEquals(0, child2.getChildrenCount()); 183 assertEquals(1, root.getChildrenCount()); 184 assertFalse(root.hasChild(child2)); 185 assertFalse(root.hasChild(child21)); 186 187 assertTrue(root.hasChild(child1)); 188 assertTrue(root.hasChild(child11)); 189 190 root.removeImmediately(); 191 assertEquals(0, root.getChildrenCount()); 192 } 193 194 @Test 195 public void testRemoveImmediately_WithController() throws Exception { 196 final WindowContainer container = new WindowContainer(); 197 final WindowContainerController controller = new WindowContainerController(null, sWm); 198 199 container.setController(controller); 200 assertEquals(controller, container.getController()); 201 assertEquals(container, controller.mContainer); 202 203 container.removeImmediately(); 204 assertNull(container.getController()); 205 assertNull(controller.mContainer); 206 } 207 208 @Test 209 public void testSetController() throws Exception { 210 final WindowContainerController controller = new WindowContainerController(null, sWm); 211 final WindowContainer container = new WindowContainer(); 212 213 container.setController(controller); 214 assertEquals(controller, container.getController()); 215 assertEquals(container, controller.mContainer); 216 217 // Assert we can't change the controller to another one once set 218 boolean gotException = false; 219 try { 220 container.setController(new WindowContainerController(null, sWm)); 221 } catch (IllegalArgumentException e) { 222 gotException = true; 223 } 224 assertTrue(gotException); 225 226 // Assert that we can set the controller to null. 227 container.setController(null); 228 assertNull(container.getController()); 229 assertNull(controller.mContainer); 230 } 231 232 @Test 233 public void testPositionChildAt() throws Exception { 234 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 235 final TestWindowContainer root = builder.setLayer(0).build(); 236 237 final TestWindowContainer child1 = root.addChildWindow(); 238 final TestWindowContainer child2 = root.addChildWindow(); 239 final TestWindowContainer child3 = root.addChildWindow(); 240 241 // Test position at top. 242 root.positionChildAt(POSITION_TOP, child1, false /* includingParents */); 243 assertEquals(child1, root.getChildAt(root.getChildrenCount() - 1)); 244 245 // Test position at bottom. 246 root.positionChildAt(POSITION_BOTTOM, child1, false /* includingParents */); 247 assertEquals(child1, root.getChildAt(0)); 248 249 // Test position in the middle. 250 root.positionChildAt(1, child3, false /* includingParents */); 251 assertEquals(child1, root.getChildAt(0)); 252 assertEquals(child3, root.getChildAt(1)); 253 assertEquals(child2, root.getChildAt(2)); 254 } 255 256 @Test 257 public void testPositionChildAtIncludeParents() throws Exception { 258 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 259 final TestWindowContainer root = builder.setLayer(0).build(); 260 261 final TestWindowContainer child1 = root.addChildWindow(); 262 final TestWindowContainer child2 = root.addChildWindow(); 263 final TestWindowContainer child11 = child1.addChildWindow(); 264 final TestWindowContainer child12 = child1.addChildWindow(); 265 final TestWindowContainer child13 = child1.addChildWindow(); 266 final TestWindowContainer child21 = child2.addChildWindow(); 267 final TestWindowContainer child22 = child2.addChildWindow(); 268 final TestWindowContainer child23 = child2.addChildWindow(); 269 270 // Test moving to top. 271 child1.positionChildAt(POSITION_TOP, child11, true /* includingParents */); 272 assertEquals(child12, child1.getChildAt(0)); 273 assertEquals(child13, child1.getChildAt(1)); 274 assertEquals(child11, child1.getChildAt(2)); 275 assertEquals(child2, root.getChildAt(0)); 276 assertEquals(child1, root.getChildAt(1)); 277 278 // Test moving to bottom. 279 child1.positionChildAt(POSITION_BOTTOM, child11, true /* includingParents */); 280 assertEquals(child11, child1.getChildAt(0)); 281 assertEquals(child12, child1.getChildAt(1)); 282 assertEquals(child13, child1.getChildAt(2)); 283 assertEquals(child1, root.getChildAt(0)); 284 assertEquals(child2, root.getChildAt(1)); 285 286 // Test moving to middle, includeParents shouldn't do anything. 287 child2.positionChildAt(1, child21, true /* includingParents */); 288 assertEquals(child11, child1.getChildAt(0)); 289 assertEquals(child12, child1.getChildAt(1)); 290 assertEquals(child13, child1.getChildAt(2)); 291 assertEquals(child22, child2.getChildAt(0)); 292 assertEquals(child21, child2.getChildAt(1)); 293 assertEquals(child23, child2.getChildAt(2)); 294 assertEquals(child1, root.getChildAt(0)); 295 assertEquals(child2, root.getChildAt(1)); 296 } 297 298 @Test 299 public void testPositionChildAtInvalid() throws Exception { 300 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 301 final TestWindowContainer root = builder.setLayer(0).build(); 302 303 final TestWindowContainer child1 = root.addChildWindow(); 304 final TestWindowContainer child2 = root.addChildWindow(); 305 306 boolean gotException = false; 307 try { 308 // Check response to negative position. 309 root.positionChildAt(-1, child1, false /* includingParents */); 310 } catch (IllegalArgumentException e) { 311 gotException = true; 312 } 313 assertTrue(gotException); 314 315 gotException = false; 316 try { 317 // Check response to position that's bigger than child number. 318 root.positionChildAt(3, child1, false /* includingParents */); 319 } catch (IllegalArgumentException e) { 320 gotException = true; 321 } 322 assertTrue(gotException); 323 } 324 325 @Test 326 public void testIsAnimating() throws Exception { 327 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 328 final TestWindowContainer root = builder.setLayer(0).build(); 329 330 final TestWindowContainer child1 = root.addChildWindow(builder.setIsAnimating(true)); 331 final TestWindowContainer child2 = root.addChildWindow(); 332 final TestWindowContainer child11 = child1.addChildWindow(); 333 final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true)); 334 final TestWindowContainer child21 = child2.addChildWindow(); 335 336 assertTrue(root.isAnimating()); 337 assertTrue(child1.isAnimating()); 338 assertFalse(child11.isAnimating()); 339 assertTrue(child12.isAnimating()); 340 assertFalse(child2.isAnimating()); 341 assertFalse(child21.isAnimating()); 342 } 343 344 @Test 345 public void testIsVisible() throws Exception { 346 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 347 final TestWindowContainer root = builder.setLayer(0).build(); 348 349 final TestWindowContainer child1 = root.addChildWindow(builder.setIsVisible(true)); 350 final TestWindowContainer child2 = root.addChildWindow(); 351 final TestWindowContainer child11 = child1.addChildWindow(); 352 final TestWindowContainer child12 = child1.addChildWindow(builder.setIsVisible(true)); 353 final TestWindowContainer child21 = child2.addChildWindow(); 354 355 assertFalse(root.isVisible()); 356 assertTrue(child1.isVisible()); 357 assertFalse(child11.isVisible()); 358 assertTrue(child12.isVisible()); 359 assertFalse(child2.isVisible()); 360 assertFalse(child21.isVisible()); 361 } 362 363 @Test 364 public void testRemoveChild() throws Exception { 365 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 366 final TestWindowContainer root = builder.setLayer(0).build(); 367 final TestWindowContainer child1 = root.addChildWindow(); 368 final TestWindowContainer child2 = root.addChildWindow(); 369 final TestWindowContainer child11 = child1.addChildWindow(); 370 final TestWindowContainer child21 = child2.addChildWindow(); 371 372 assertTrue(root.hasChild(child2)); 373 assertTrue(root.hasChild(child21)); 374 root.removeChild(child2); 375 assertFalse(root.hasChild(child2)); 376 assertFalse(root.hasChild(child21)); 377 assertNull(child2.getParentWindow()); 378 379 boolean gotException = false; 380 assertTrue(root.hasChild(child11)); 381 try { 382 // Can only detach our direct children. 383 root.removeChild(child11); 384 } catch (IllegalArgumentException e) { 385 gotException = true; 386 } 387 assertTrue(gotException); 388 } 389 390 @Test 391 public void testGetOrientation_childSpecified() throws Exception { 392 testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE, 393 SCREEN_ORIENTATION_LANDSCAPE); 394 testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET, 395 SCREEN_ORIENTATION_UNSET); 396 } 397 398 private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation, 399 int expectedOrientation) { 400 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 401 final TestWindowContainer root = builder.setLayer(0).build(); 402 root.setFillsParent(true); 403 404 builder.setIsVisible(childVisible); 405 406 if (childOrientation != SCREEN_ORIENTATION_UNSET) { 407 builder.setOrientation(childOrientation); 408 } 409 410 final TestWindowContainer child1 = root.addChildWindow(builder); 411 child1.setFillsParent(true); 412 413 assertTrue(root.getOrientation() == expectedOrientation); 414 } 415 416 @Test 417 public void testGetOrientation_Unset() throws Exception { 418 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 419 final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build(); 420 // Unspecified well because we didn't specify anything... 421 assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation()); 422 } 423 424 @Test 425 public void testGetOrientation_InvisibleParentUnsetVisibleChildren() throws Exception { 426 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 427 final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build(); 428 429 builder.setIsVisible(false).setLayer(-1); 430 final TestWindowContainer invisible = root.addChildWindow(builder); 431 builder.setIsVisible(true).setLayer(-2); 432 final TestWindowContainer invisibleChild1VisibleAndSet = invisible.addChildWindow(builder); 433 invisibleChild1VisibleAndSet.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); 434 // Landscape well because the container is visible and that is what we set on it above. 435 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, invisibleChild1VisibleAndSet.getOrientation()); 436 // Landscape because even though the container isn't visible it has a child that is 437 // specifying it can influence the orientation by being visible. 438 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, invisible.getOrientation()); 439 // Landscape because the grandchild is visible and therefore can participate. 440 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation()); 441 442 builder.setIsVisible(true).setLayer(-3); 443 final TestWindowContainer visibleUnset = root.addChildWindow(builder); 444 visibleUnset.setOrientation(SCREEN_ORIENTATION_UNSET); 445 assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnset.getOrientation()); 446 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation()); 447 448 } 449 450 @Test 451 public void testGetOrientation_setBehind() throws Exception { 452 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 453 final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build(); 454 455 builder.setIsVisible(true).setLayer(-1); 456 final TestWindowContainer visibleUnset = root.addChildWindow(builder); 457 visibleUnset.setOrientation(SCREEN_ORIENTATION_UNSET); 458 459 builder.setIsVisible(true).setLayer(-2); 460 final TestWindowContainer visibleUnsetChild1VisibleSetBehind = 461 visibleUnset.addChildWindow(builder); 462 visibleUnsetChild1VisibleSetBehind.setOrientation(SCREEN_ORIENTATION_BEHIND); 463 // Setting to visible behind will be used by the parents if there isn't another other 464 // container behind this one that has an orientation set. 465 assertEquals(SCREEN_ORIENTATION_BEHIND, 466 visibleUnsetChild1VisibleSetBehind.getOrientation()); 467 assertEquals(SCREEN_ORIENTATION_BEHIND, visibleUnset.getOrientation()); 468 assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation()); 469 } 470 471 @Test 472 public void testGetOrientation_fillsParent() throws Exception { 473 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 474 final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build(); 475 476 builder.setIsVisible(true).setLayer(-1); 477 final TestWindowContainer visibleUnset = root.addChildWindow(builder); 478 visibleUnset.setOrientation(SCREEN_ORIENTATION_BEHIND); 479 480 builder.setLayer(1).setIsVisible(true); 481 final TestWindowContainer visibleUnspecifiedRootChild = root.addChildWindow(builder); 482 visibleUnspecifiedRootChild.setFillsParent(false); 483 visibleUnspecifiedRootChild.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED); 484 // Unset because the child doesn't fill the parent. May as well be invisible... 485 assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnspecifiedRootChild.getOrientation()); 486 // The parent uses whatever orientation is set behind this container since it doesn't fill 487 // the parent. 488 assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation()); 489 490 // Test case of child filling its parent, but its parent isn't filling its own parent. 491 builder.setLayer(2).setIsVisible(true); 492 final TestWindowContainer visibleUnspecifiedRootChildChildFillsParent = 493 visibleUnspecifiedRootChild.addChildWindow(builder); 494 visibleUnspecifiedRootChildChildFillsParent.setOrientation( 495 SCREEN_ORIENTATION_PORTRAIT); 496 assertEquals(SCREEN_ORIENTATION_PORTRAIT, 497 visibleUnspecifiedRootChildChildFillsParent.getOrientation()); 498 assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnspecifiedRootChild.getOrientation()); 499 assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation()); 500 501 502 visibleUnspecifiedRootChild.setFillsParent(true); 503 assertEquals(SCREEN_ORIENTATION_PORTRAIT, visibleUnspecifiedRootChild.getOrientation()); 504 assertEquals(SCREEN_ORIENTATION_PORTRAIT, root.getOrientation()); 505 } 506 507 @Test 508 public void testCompareTo() throws Exception { 509 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 510 final TestWindowContainer root = builder.setLayer(0).build(); 511 512 final TestWindowContainer child1 = root.addChildWindow(); 513 final TestWindowContainer child11 = child1.addChildWindow(); 514 final TestWindowContainer child12 = child1.addChildWindow(); 515 516 final TestWindowContainer child2 = root.addChildWindow(); 517 final TestWindowContainer child21 = child2.addChildWindow(); 518 final TestWindowContainer child22 = child2.addChildWindow(); 519 final TestWindowContainer child23 = child2.addChildWindow(); 520 final TestWindowContainer child221 = child22.addChildWindow(); 521 final TestWindowContainer child222 = child22.addChildWindow(); 522 final TestWindowContainer child223 = child22.addChildWindow(); 523 final TestWindowContainer child2221 = child222.addChildWindow(); 524 final TestWindowContainer child2222 = child222.addChildWindow(); 525 final TestWindowContainer child2223 = child222.addChildWindow(); 526 527 final TestWindowContainer root2 = builder.setLayer(0).build(); 528 529 assertEquals(0, root.compareTo(root)); 530 assertEquals(-1, child1.compareTo(child2)); 531 assertEquals(1, child2.compareTo(child1)); 532 533 boolean inTheSameTree = true; 534 try { 535 root.compareTo(root2); 536 } catch (IllegalArgumentException e) { 537 inTheSameTree = false; 538 } 539 assertFalse(inTheSameTree); 540 541 assertEquals(-1, child1.compareTo(child11)); 542 assertEquals(1, child21.compareTo(root)); 543 assertEquals(1, child21.compareTo(child12)); 544 assertEquals(-1, child11.compareTo(child2)); 545 assertEquals(1, child2221.compareTo(child11)); 546 assertEquals(-1, child2222.compareTo(child223)); 547 assertEquals(1, child2223.compareTo(child21)); 548 } 549 550 @Test 551 public void testConfigurationInit() throws Exception { 552 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 553 554 // Check root container initial config. 555 final TestWindowContainer root = builder.setLayer(0).build(); 556 assertEquals(Configuration.EMPTY, root.getOverrideConfiguration()); 557 assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration()); 558 assertEquals(Configuration.EMPTY, root.getConfiguration()); 559 560 // Check child initial config. 561 final TestWindowContainer child1 = root.addChildWindow(); 562 assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration()); 563 assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration()); 564 assertEquals(Configuration.EMPTY, child1.getConfiguration()); 565 566 // Check child initial config if root has overrides. 567 final Configuration rootOverrideConfig = new Configuration(); 568 rootOverrideConfig.fontScale = 1.3f; 569 root.onOverrideConfigurationChanged(rootOverrideConfig); 570 final TestWindowContainer child2 = root.addChildWindow(); 571 assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration()); 572 assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration()); 573 assertEquals(rootOverrideConfig, child2.getConfiguration()); 574 575 // Check child initial config if root has parent config set. 576 final Configuration rootParentConfig = new Configuration(); 577 rootParentConfig.fontScale = 0.8f; 578 rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE; 579 root.onConfigurationChanged(rootParentConfig); 580 final Configuration rootFullConfig = new Configuration(rootParentConfig); 581 rootFullConfig.updateFrom(rootOverrideConfig); 582 583 final TestWindowContainer child3 = root.addChildWindow(); 584 assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration()); 585 assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration()); 586 assertEquals(rootFullConfig, child3.getConfiguration()); 587 } 588 589 @Test 590 public void testConfigurationChangeOnAddRemove() throws Exception { 591 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 592 593 // Init root's config. 594 final TestWindowContainer root = builder.setLayer(0).build(); 595 final Configuration rootOverrideConfig = new Configuration(); 596 rootOverrideConfig.fontScale = 1.3f; 597 root.onOverrideConfigurationChanged(rootOverrideConfig); 598 599 // Init child's config. 600 final TestWindowContainer child = root.addChildWindow(); 601 final Configuration childOverrideConfig = new Configuration(); 602 childOverrideConfig.densityDpi = 320; 603 child.onOverrideConfigurationChanged(childOverrideConfig); 604 final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration()); 605 mergedOverrideConfig.updateFrom(childOverrideConfig); 606 607 // Check configuration update when child is removed from parent - it should remain same. 608 root.removeChild(child); 609 assertEquals(childOverrideConfig, child.getOverrideConfiguration()); 610 assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration()); 611 assertEquals(mergedOverrideConfig, child.getConfiguration()); 612 613 // It may be paranoia... but let's check if parent's config didn't change after removal. 614 assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); 615 assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); 616 assertEquals(rootOverrideConfig, root.getConfiguration()); 617 618 // Init different root 619 final TestWindowContainer root2 = builder.setLayer(0).build(); 620 final Configuration rootOverrideConfig2 = new Configuration(); 621 rootOverrideConfig2.fontScale = 1.1f; 622 root2.onOverrideConfigurationChanged(rootOverrideConfig2); 623 624 // Check configuration update when child is added to different parent. 625 mergedOverrideConfig.setTo(rootOverrideConfig2); 626 mergedOverrideConfig.updateFrom(childOverrideConfig); 627 root2.addChildWindow(child); 628 assertEquals(childOverrideConfig, child.getOverrideConfiguration()); 629 assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration()); 630 assertEquals(mergedOverrideConfig, child.getConfiguration()); 631 } 632 633 @Test 634 public void testConfigurationChangePropagation() throws Exception { 635 final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); 636 637 // Builds 3-level vertical hierarchy with one window container on each level. 638 // In addition to different overrides on each level, everyone in hierarchy will have one 639 // common overridden value - orientation; 640 641 // Init root's config. 642 final TestWindowContainer root = builder.setLayer(0).build(); 643 final Configuration rootOverrideConfig = new Configuration(); 644 rootOverrideConfig.fontScale = 1.3f; 645 rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE; 646 root.onOverrideConfigurationChanged(rootOverrideConfig); 647 648 // Init children. 649 final TestWindowContainer child1 = root.addChildWindow(); 650 final Configuration childOverrideConfig1 = new Configuration(); 651 childOverrideConfig1.densityDpi = 320; 652 childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE; 653 child1.onOverrideConfigurationChanged(childOverrideConfig1); 654 655 final TestWindowContainer child2 = child1.addChildWindow(); 656 final Configuration childOverrideConfig2 = new Configuration(); 657 childOverrideConfig2.screenWidthDp = 150; 658 childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT; 659 child2.onOverrideConfigurationChanged(childOverrideConfig2); 660 661 // Check configuration on all levels when root override is updated. 662 rootOverrideConfig.smallestScreenWidthDp = 200; 663 root.onOverrideConfigurationChanged(rootOverrideConfig); 664 665 final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig); 666 mergedOverrideConfig1.updateFrom(childOverrideConfig1); 667 final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1); 668 669 final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1); 670 mergedOverrideConfig2.updateFrom(childOverrideConfig2); 671 final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2); 672 673 assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); 674 assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); 675 assertEquals(rootOverrideConfig, root.getConfiguration()); 676 677 assertEquals(childOverrideConfig1, child1.getOverrideConfiguration()); 678 assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration()); 679 assertEquals(mergedConfig1, child1.getConfiguration()); 680 681 assertEquals(childOverrideConfig2, child2.getOverrideConfiguration()); 682 assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration()); 683 assertEquals(mergedConfig2, child2.getConfiguration()); 684 685 // Check configuration on all levels when root parent config is updated. 686 final Configuration rootParentConfig = new Configuration(); 687 rootParentConfig.screenHeightDp = 100; 688 rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT; 689 root.onConfigurationChanged(rootParentConfig); 690 final Configuration mergedRootConfig = new Configuration(rootParentConfig); 691 mergedRootConfig.updateFrom(rootOverrideConfig); 692 693 mergedConfig1.setTo(mergedRootConfig); 694 mergedConfig1.updateFrom(mergedOverrideConfig1); 695 696 mergedConfig2.setTo(mergedConfig1); 697 mergedConfig2.updateFrom(mergedOverrideConfig2); 698 699 assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); 700 assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); 701 assertEquals(mergedRootConfig, root.getConfiguration()); 702 703 assertEquals(childOverrideConfig1, child1.getOverrideConfiguration()); 704 assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration()); 705 assertEquals(mergedConfig1, child1.getConfiguration()); 706 707 assertEquals(childOverrideConfig2, child2.getOverrideConfiguration()); 708 assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration()); 709 assertEquals(mergedConfig2, child2.getConfiguration()); 710 } 711 712 /* Used so we can gain access to some protected members of the {@link WindowContainer} class */ 713 private class TestWindowContainer extends WindowContainer<TestWindowContainer> { 714 private final int mLayer; 715 private boolean mIsAnimating; 716 private boolean mIsVisible; 717 private boolean mFillsParent; 718 private Integer mOrientation; 719 720 private boolean mOnParentSetCalled; 721 722 /** 723 * Compares 2 window layers and returns -1 if the first is lesser than the second in terms 724 * of z-order and 1 otherwise. 725 */ 726 private final Comparator<TestWindowContainer> mWindowSubLayerComparator = (w1, w2) -> { 727 final int layer1 = w1.mLayer; 728 final int layer2 = w2.mLayer; 729 if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) { 730 // We insert the child window into the list ordered by the mLayer. For same layers, 731 // the negative one should go below others; the positive one should go above others. 732 return -1; 733 } 734 return 1; 735 }; 736 737 TestWindowContainer(int layer, boolean isAnimating, boolean isVisible, 738 Integer orientation) { 739 mLayer = layer; 740 mIsAnimating = isAnimating; 741 mIsVisible = isVisible; 742 mFillsParent = true; 743 mOrientation = orientation; 744 } 745 746 TestWindowContainer getParentWindow() { 747 return (TestWindowContainer) getParent(); 748 } 749 750 int getChildrenCount() { 751 return mChildren.size(); 752 } 753 754 TestWindowContainer addChildWindow(TestWindowContainer child) { 755 addChild(child, mWindowSubLayerComparator); 756 return child; 757 } 758 759 TestWindowContainer addChildWindow(TestWindowContainerBuilder childBuilder) { 760 TestWindowContainer child = childBuilder.build(); 761 addChild(child, mWindowSubLayerComparator); 762 return child; 763 } 764 765 TestWindowContainer addChildWindow() { 766 return addChildWindow(new TestWindowContainerBuilder().setLayer(1)); 767 } 768 769 TestWindowContainer getChildAt(int index) { 770 return mChildren.get(index); 771 } 772 773 @Override 774 void onParentSet() { 775 mOnParentSetCalled = true; 776 } 777 778 @Override 779 boolean isAnimating() { 780 return mIsAnimating || super.isAnimating(); 781 } 782 783 @Override 784 boolean isVisible() { 785 return mIsVisible; 786 } 787 788 @Override 789 int getOrientation() { 790 return mOrientation != null ? mOrientation : super.getOrientation(); 791 } 792 793 @Override 794 boolean fillsParent() { 795 return mFillsParent; 796 } 797 798 void setFillsParent(boolean fillsParent) { 799 mFillsParent = fillsParent; 800 } 801 } 802 803 private class TestWindowContainerBuilder { 804 private int mLayer; 805 private boolean mIsAnimating; 806 private boolean mIsVisible; 807 private Integer mOrientation; 808 809 public TestWindowContainerBuilder() { 810 reset(); 811 } 812 813 TestWindowContainerBuilder setLayer(int layer) { 814 mLayer = layer; 815 return this; 816 } 817 818 TestWindowContainerBuilder setIsAnimating(boolean isAnimating) { 819 mIsAnimating = isAnimating; 820 return this; 821 } 822 823 TestWindowContainerBuilder setIsVisible(boolean isVisible) { 824 mIsVisible = isVisible; 825 return this; 826 } 827 828 TestWindowContainerBuilder setOrientation(int orientation) { 829 mOrientation = orientation; 830 return this; 831 } 832 833 TestWindowContainerBuilder reset() { 834 mLayer = 0; 835 mIsAnimating = false; 836 mIsVisible = false; 837 mOrientation = null; 838 return this; 839 } 840 841 TestWindowContainer build() { 842 return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible, mOrientation); 843 } 844 } 845} 846