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