WindowContainerTests.java revision 441e4494682144aec2ec7f19060464af3d29c319
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;
36import static org.junit.Assert.assertEquals;
37import static org.junit.Assert.assertFalse;
38import static org.junit.Assert.assertNotNull;
39import static org.junit.Assert.assertNull;
40import static org.junit.Assert.assertTrue;
41
42/**
43 * Test class for {@link WindowContainer}.
44 *
45 * Build: mmma -j32 frameworks/base/services/tests/servicestests
46 * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
47 * Run: adb shell am instrument -w -e class com.android.server.wm.WindowContainerTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
48 */
49@SmallTest
50@Presubmit
51@RunWith(AndroidJUnit4.class)
52public class WindowContainerTests {
53
54    @Test
55    public void testCreation() throws Exception {
56        final TestWindowContainer w = new TestWindowContainerBuilder().setLayer(0).build();
57        assertNull("window must have no parent", w.getParentWindow());
58        assertEquals("window must have no children", 0, w.getChildrenCount());
59    }
60
61    @Test
62    public void testAdd() throws Exception {
63        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
64        final TestWindowContainer root = builder.setLayer(0).build();
65
66        final TestWindowContainer layer1 = root.addChildWindow(builder.setLayer(1));
67        final TestWindowContainer secondLayer1 = root.addChildWindow(builder.setLayer(1));
68        final TestWindowContainer layer2 = root.addChildWindow(builder.setLayer(2));
69        final TestWindowContainer layerNeg1 = root.addChildWindow(builder.setLayer(-1));
70        final TestWindowContainer layerNeg2 = root.addChildWindow(builder.setLayer(-2));
71        final TestWindowContainer secondLayerNeg1 = root.addChildWindow(builder.setLayer(-1));
72        final TestWindowContainer layer0 = root.addChildWindow(builder.setLayer(0));
73
74        assertEquals(7, root.getChildrenCount());
75
76        assertEquals(root, layer1.getParentWindow());
77        assertEquals(root, secondLayer1.getParentWindow());
78        assertEquals(root, layer2.getParentWindow());
79        assertEquals(root, layerNeg1.getParentWindow());
80        assertEquals(root, layerNeg2.getParentWindow());
81        assertEquals(root, secondLayerNeg1.getParentWindow());
82        assertEquals(root, layer0.getParentWindow());
83
84        assertEquals(layerNeg2, root.getChildAt(0));
85        assertEquals(secondLayerNeg1, root.getChildAt(1));
86        assertEquals(layerNeg1, root.getChildAt(2));
87        assertEquals(layer0, root.getChildAt(3));
88        assertEquals(layer1, root.getChildAt(4));
89        assertEquals(secondLayer1, root.getChildAt(5));
90        assertEquals(layer2, root.getChildAt(6));
91    }
92
93    @Test
94    public void testAdd_AlreadyHasParent() throws Exception {
95        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
96        final TestWindowContainer root = builder.setLayer(0).build();
97
98        final TestWindowContainer child1 = root.addChildWindow();
99        final TestWindowContainer child2 = root.addChildWindow();
100
101        boolean gotException = false;
102        try {
103            child1.addChildWindow(child2);
104        } catch (IllegalArgumentException e) {
105            gotException = true;
106        }
107        assertTrue(gotException);
108
109        gotException = false;
110        try {
111            root.addChildWindow(child2);
112        } catch (IllegalArgumentException e) {
113            gotException = true;
114        }
115        assertTrue(gotException);
116    }
117
118    @Test
119    public void testHasChild() throws Exception {
120        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
121        final TestWindowContainer root = builder.setLayer(0).build();
122
123        final TestWindowContainer child1 = root.addChildWindow();
124        final TestWindowContainer child2 = root.addChildWindow();
125        final TestWindowContainer child11 = child1.addChildWindow();
126        final TestWindowContainer child12 = child1.addChildWindow();
127        final TestWindowContainer child21 = child2.addChildWindow();
128
129        assertEquals(2, root.getChildrenCount());
130        assertEquals(2, child1.getChildrenCount());
131        assertEquals(1, child2.getChildrenCount());
132
133        assertTrue(root.hasChild(child1));
134        assertTrue(root.hasChild(child2));
135        assertTrue(root.hasChild(child11));
136        assertTrue(root.hasChild(child12));
137        assertTrue(root.hasChild(child21));
138
139        assertTrue(child1.hasChild(child11));
140        assertTrue(child1.hasChild(child12));
141        assertFalse(child1.hasChild(child21));
142
143        assertTrue(child2.hasChild(child21));
144        assertFalse(child2.hasChild(child11));
145        assertFalse(child2.hasChild(child12));
146    }
147
148    @Test
149    public void testRemoveImmediately() throws Exception {
150        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
151        final TestWindowContainer root = builder.setLayer(0).build();
152
153        final TestWindowContainer child1 = root.addChildWindow();
154        final TestWindowContainer child2 = root.addChildWindow();
155        final TestWindowContainer child11 = child1.addChildWindow();
156        final TestWindowContainer child12 = child1.addChildWindow();
157        final TestWindowContainer child21 = child2.addChildWindow();
158
159        assertNotNull(child12.getParentWindow());
160        child12.removeImmediately();
161        assertNull(child12.getParentWindow());
162        assertEquals(1, child1.getChildrenCount());
163        assertFalse(child1.hasChild(child12));
164        assertFalse(root.hasChild(child12));
165
166        assertTrue(root.hasChild(child2));
167        assertNotNull(child2.getParentWindow());
168        child2.removeImmediately();
169        assertNull(child2.getParentWindow());
170        assertNull(child21.getParentWindow());
171        assertEquals(0, child2.getChildrenCount());
172        assertEquals(1, root.getChildrenCount());
173        assertFalse(root.hasChild(child2));
174        assertFalse(root.hasChild(child21));
175
176        assertTrue(root.hasChild(child1));
177        assertTrue(root.hasChild(child11));
178
179        root.removeImmediately();
180        assertEquals(0, root.getChildrenCount());
181    }
182
183    @Test
184    public void testIsAnimating() throws Exception {
185        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
186        final TestWindowContainer root = builder.setLayer(0).build();
187
188        final TestWindowContainer child1 = root.addChildWindow(builder.setIsAnimating(true));
189        final TestWindowContainer child2 = root.addChildWindow();
190        final TestWindowContainer child11 = child1.addChildWindow();
191        final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true));
192        final TestWindowContainer child21 = child2.addChildWindow();
193
194        assertTrue(root.isAnimating());
195        assertTrue(child1.isAnimating());
196        assertFalse(child11.isAnimating());
197        assertTrue(child12.isAnimating());
198        assertFalse(child2.isAnimating());
199        assertFalse(child21.isAnimating());
200    }
201
202    @Test
203    public void testIsVisible() throws Exception {
204        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
205        final TestWindowContainer root = builder.setLayer(0).build();
206
207        final TestWindowContainer child1 = root.addChildWindow(builder.setIsVisible(true));
208        final TestWindowContainer child2 = root.addChildWindow();
209        final TestWindowContainer child11 = child1.addChildWindow();
210        final TestWindowContainer child12 = child1.addChildWindow(builder.setIsVisible(true));
211        final TestWindowContainer child21 = child2.addChildWindow();
212
213        assertFalse(root.isVisible());
214        assertTrue(child1.isVisible());
215        assertFalse(child11.isVisible());
216        assertTrue(child12.isVisible());
217        assertFalse(child2.isVisible());
218        assertFalse(child21.isVisible());
219    }
220
221    @Test
222    public void testRemoveChild() throws Exception {
223        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
224        final TestWindowContainer root = builder.setLayer(0).build();
225        final TestWindowContainer child1 = root.addChildWindow();
226        final TestWindowContainer child2 = root.addChildWindow();
227        final TestWindowContainer child11 = child1.addChildWindow();
228        final TestWindowContainer child21 = child2.addChildWindow();
229
230        assertTrue(root.hasChild(child2));
231        assertTrue(root.hasChild(child21));
232        root.removeChild(child2);
233        assertFalse(root.hasChild(child2));
234        assertFalse(root.hasChild(child21));
235        assertNull(child2.getParentWindow());
236
237        boolean gotException = false;
238        assertTrue(root.hasChild(child11));
239        try {
240            // Can only detach our direct children.
241            root.removeChild(child11);
242        } catch (IllegalArgumentException e) {
243            gotException = true;
244        }
245        assertTrue(gotException);
246    }
247
248    @Test
249    public void testGetOrientation_Unset() throws Exception {
250        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
251        final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
252        // Unspecified well because we didn't specify anything...
253        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
254    }
255
256    @Test
257    public void testGetOrientation_InvisibleParentUnsetVisibleChildren() throws Exception {
258        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
259        final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
260
261        builder.setIsVisible(false).setLayer(-1);
262        final TestWindowContainer invisible = root.addChildWindow(builder);
263        builder.setIsVisible(true).setLayer(-2);
264        final TestWindowContainer invisibleChild1VisibleAndSet = invisible.addChildWindow(builder);
265        invisibleChild1VisibleAndSet.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
266        // Landscape well because the container is visible and that is what we set on it above.
267        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, invisibleChild1VisibleAndSet.getOrientation());
268        // Unset because the container isn't visible even though it has a child that thinks it is
269        // visible.
270        assertEquals(SCREEN_ORIENTATION_UNSET, invisible.getOrientation());
271        // Unspecified because we are visible and we didn't specify an orientation and there isn't
272        // a visible child.
273        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
274
275        builder.setIsVisible(true).setLayer(-3);
276        final TestWindowContainer visibleUnset = root.addChildWindow(builder);
277        visibleUnset.setOrientation(SCREEN_ORIENTATION_UNSET);
278        assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnset.getOrientation());
279        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
280
281    }
282
283    @Test
284    public void testGetOrientation_setBehind() throws Exception {
285        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
286        final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
287
288        builder.setIsVisible(true).setLayer(-1);
289        final TestWindowContainer visibleUnset = root.addChildWindow(builder);
290        visibleUnset.setOrientation(SCREEN_ORIENTATION_UNSET);
291
292        builder.setIsVisible(true).setLayer(-2);
293        final TestWindowContainer visibleUnsetChild1VisibleSetBehind =
294                visibleUnset.addChildWindow(builder);
295        visibleUnsetChild1VisibleSetBehind.setOrientation(SCREEN_ORIENTATION_BEHIND);
296        // Setting to visible behind will be used by the parents if there isn't another other
297        // container behind this one that has an orientation set.
298        assertEquals(SCREEN_ORIENTATION_BEHIND,
299                visibleUnsetChild1VisibleSetBehind.getOrientation());
300        assertEquals(SCREEN_ORIENTATION_BEHIND, visibleUnset.getOrientation());
301        assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation());
302    }
303
304    @Test
305    public void testGetOrientation_fillsParent() throws Exception {
306        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
307        final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
308
309        builder.setIsVisible(true).setLayer(-1);
310        final TestWindowContainer visibleUnset = root.addChildWindow(builder);
311        visibleUnset.setOrientation(SCREEN_ORIENTATION_BEHIND);
312
313        builder.setLayer(1).setIsVisible(true);
314        final TestWindowContainer visibleUnspecifiedRootChild = root.addChildWindow(builder);
315        visibleUnspecifiedRootChild.setFillsParent(false);
316        visibleUnspecifiedRootChild.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
317        // Unset because the child doesn't fill the parent. May as well be invisible...
318        assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnspecifiedRootChild.getOrientation());
319        // The parent uses whatever orientation is set behind this container since it doesn't fill
320        // the parent.
321        assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation());
322
323        // Test case of child filling its parent, but its parent isn't filling its own parent.
324        builder.setLayer(2).setIsVisible(true);
325        final TestWindowContainer visibleUnspecifiedRootChildChildFillsParent =
326                visibleUnspecifiedRootChild.addChildWindow(builder);
327        visibleUnspecifiedRootChildChildFillsParent.setOrientation(
328                SCREEN_ORIENTATION_PORTRAIT);
329        assertEquals(SCREEN_ORIENTATION_PORTRAIT,
330                visibleUnspecifiedRootChildChildFillsParent.getOrientation());
331        assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnspecifiedRootChild.getOrientation());
332        assertEquals(SCREEN_ORIENTATION_BEHIND, root.getOrientation());
333
334
335        visibleUnspecifiedRootChild.setFillsParent(true);
336        assertEquals(SCREEN_ORIENTATION_PORTRAIT, visibleUnspecifiedRootChild.getOrientation());
337        assertEquals(SCREEN_ORIENTATION_PORTRAIT, root.getOrientation());
338    }
339
340    @Test
341    public void testCompareTo() throws Exception {
342        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
343        final TestWindowContainer root = builder.setLayer(0).build();
344
345        final TestWindowContainer child1 = root.addChildWindow();
346        final TestWindowContainer child11 = child1.addChildWindow();
347        final TestWindowContainer child12 = child1.addChildWindow();
348
349        final TestWindowContainer child2 = root.addChildWindow();
350        final TestWindowContainer child21 = child2.addChildWindow();
351        final TestWindowContainer child22 = child2.addChildWindow();
352        final TestWindowContainer child23 = child2.addChildWindow();
353        final TestWindowContainer child221 = child22.addChildWindow();
354        final TestWindowContainer child222 = child22.addChildWindow();
355        final TestWindowContainer child223 = child22.addChildWindow();
356        final TestWindowContainer child2221 = child222.addChildWindow();
357        final TestWindowContainer child2222 = child222.addChildWindow();
358        final TestWindowContainer child2223 = child222.addChildWindow();
359
360        final TestWindowContainer root2 = builder.setLayer(0).build();
361
362        assertEquals(0, root.compareTo(root));
363        assertEquals(-1, child1.compareTo(child2));
364        assertEquals(1, child2.compareTo(child1));
365
366        boolean inTheSameTree = true;
367        try {
368            root.compareTo(root2);
369        } catch (IllegalArgumentException e) {
370            inTheSameTree = false;
371        }
372        assertFalse(inTheSameTree);
373
374        assertEquals(-1, child1.compareTo(child11));
375        assertEquals(1, child21.compareTo(root));
376        assertEquals(1, child21.compareTo(child12));
377        assertEquals(-1, child11.compareTo(child2));
378        assertEquals(1, child2221.compareTo(child11));
379        assertEquals(-1, child2222.compareTo(child223));
380        assertEquals(1, child2223.compareTo(child21));
381    }
382
383    @Test
384    public void testConfigurationInit() throws Exception {
385        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
386
387        // Check root container initial config.
388        final TestWindowContainer root = builder.setLayer(0).build();
389        assertEquals(Configuration.EMPTY, root.getOverrideConfiguration());
390        assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration());
391        assertEquals(Configuration.EMPTY, root.getConfiguration());
392
393        // Check child initial config.
394        final TestWindowContainer child1 = root.addChildWindow();
395        assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration());
396        assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration());
397        assertEquals(Configuration.EMPTY, child1.getConfiguration());
398
399        // Check child initial config if root has overrides.
400        final Configuration rootOverrideConfig = new Configuration();
401        rootOverrideConfig.fontScale = 1.3f;
402        root.onOverrideConfigurationChanged(rootOverrideConfig);
403        final TestWindowContainer child2 = root.addChildWindow();
404        assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration());
405        assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
406        assertEquals(rootOverrideConfig, child2.getConfiguration());
407
408        // Check child initial config if root has parent config set.
409        final Configuration rootParentConfig = new Configuration();
410        rootParentConfig.fontScale = 0.8f;
411        rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE;
412        root.onConfigurationChanged(rootParentConfig);
413        final Configuration rootFullConfig = new Configuration(rootParentConfig);
414        rootFullConfig.updateFrom(rootOverrideConfig);
415
416        final TestWindowContainer child3 = root.addChildWindow();
417        assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration());
418        assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
419        assertEquals(rootFullConfig, child3.getConfiguration());
420    }
421
422    @Test
423    public void testConfigurationChangeOnAddRemove() throws Exception {
424        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
425
426        // Init root's config.
427        final TestWindowContainer root = builder.setLayer(0).build();
428        final Configuration rootOverrideConfig = new Configuration();
429        rootOverrideConfig.fontScale = 1.3f;
430        root.onOverrideConfigurationChanged(rootOverrideConfig);
431
432        // Init child's config.
433        final TestWindowContainer child = root.addChildWindow();
434        final Configuration childOverrideConfig = new Configuration();
435        childOverrideConfig.densityDpi = 320;
436        child.onOverrideConfigurationChanged(childOverrideConfig);
437
438        // Check configuration update when child is removed from parent.
439        root.removeChild(child);
440        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
441        assertEquals(childOverrideConfig, child.getMergedOverrideConfiguration());
442        assertEquals(childOverrideConfig, child.getConfiguration());
443
444        // It may be paranoia... but let's check if parent's config didn't change after removal.
445        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
446        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
447        assertEquals(rootOverrideConfig, root.getConfiguration());
448
449        // Check configuration update when child is added to parent.
450        final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
451        mergedOverrideConfig.updateFrom(childOverrideConfig);
452        root.addChildWindow(child);
453        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
454        assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
455        assertEquals(mergedOverrideConfig, child.getConfiguration());
456    }
457
458    @Test
459    public void testConfigurationChangePropagation() throws Exception {
460        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
461
462        // Builds 3-level vertical hierarchy with one window container on each level.
463        // In addition to different overrides on each level, everyone in hierarchy will have one
464        // common overridden value - orientation;
465
466        // Init root's config.
467        final TestWindowContainer root = builder.setLayer(0).build();
468        final Configuration rootOverrideConfig = new Configuration();
469        rootOverrideConfig.fontScale = 1.3f;
470        rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
471        root.onOverrideConfigurationChanged(rootOverrideConfig);
472
473        // Init children.
474        final TestWindowContainer child1 = root.addChildWindow();
475        final Configuration childOverrideConfig1 = new Configuration();
476        childOverrideConfig1.densityDpi = 320;
477        childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
478        child1.onOverrideConfigurationChanged(childOverrideConfig1);
479
480        final TestWindowContainer child2 = child1.addChildWindow();
481        final Configuration childOverrideConfig2 = new Configuration();
482        childOverrideConfig2.screenWidthDp = 150;
483        childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
484        child2.onOverrideConfigurationChanged(childOverrideConfig2);
485
486        // Check configuration on all levels when root override is updated.
487        rootOverrideConfig.smallestScreenWidthDp = 200;
488        root.onOverrideConfigurationChanged(rootOverrideConfig);
489
490        final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
491        mergedOverrideConfig1.updateFrom(childOverrideConfig1);
492        final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1);
493
494        final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1);
495        mergedOverrideConfig2.updateFrom(childOverrideConfig2);
496        final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
497
498        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
499        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
500        assertEquals(rootOverrideConfig, root.getConfiguration());
501
502        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
503        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
504        assertEquals(mergedConfig1, child1.getConfiguration());
505
506        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
507        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
508        assertEquals(mergedConfig2, child2.getConfiguration());
509
510        // Check configuration on all levels when root parent config is updated.
511        final Configuration rootParentConfig = new Configuration();
512        rootParentConfig.screenHeightDp = 100;
513        rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT;
514        root.onConfigurationChanged(rootParentConfig);
515        final Configuration mergedRootConfig = new Configuration(rootParentConfig);
516        mergedRootConfig.updateFrom(rootOverrideConfig);
517
518        mergedConfig1.setTo(mergedRootConfig);
519        mergedConfig1.updateFrom(mergedOverrideConfig1);
520
521        mergedConfig2.setTo(mergedConfig1);
522        mergedConfig2.updateFrom(mergedOverrideConfig2);
523
524        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
525        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
526        assertEquals(mergedRootConfig, root.getConfiguration());
527
528        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
529        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
530        assertEquals(mergedConfig1, child1.getConfiguration());
531
532        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
533        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
534        assertEquals(mergedConfig2, child2.getConfiguration());
535    }
536
537    /* Used so we can gain access to some protected members of the {@link WindowContainer} class */
538    private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
539        private final int mLayer;
540        private boolean mIsAnimating;
541        private boolean mIsVisible;
542        private boolean mFillsParent;
543
544        /**
545         * Compares 2 window layers and returns -1 if the first is lesser than the second in terms
546         * of z-order and 1 otherwise.
547         */
548        private final Comparator<TestWindowContainer> mWindowSubLayerComparator = (w1, w2) -> {
549            final int layer1 = w1.mLayer;
550            final int layer2 = w2.mLayer;
551            if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
552                // We insert the child window into the list ordered by the mLayer. For same layers,
553                // the negative one should go below others; the positive one should go above others.
554                return -1;
555            }
556            return 1;
557        };
558
559        TestWindowContainer(int layer, boolean isAnimating, boolean isVisible) {
560            mLayer = layer;
561            mIsAnimating = isAnimating;
562            mIsVisible = isVisible;
563            mFillsParent = true;
564        }
565
566        TestWindowContainer getParentWindow() {
567            return (TestWindowContainer) getParent();
568        }
569
570        int getChildrenCount() {
571            return mChildren.size();
572        }
573
574        TestWindowContainer addChildWindow(TestWindowContainer child) {
575            addChild(child, mWindowSubLayerComparator);
576            return child;
577        }
578
579        TestWindowContainer addChildWindow(TestWindowContainerBuilder childBuilder) {
580            TestWindowContainer child = childBuilder.build();
581            addChild(child, mWindowSubLayerComparator);
582            return child;
583        }
584
585        TestWindowContainer addChildWindow() {
586            return addChildWindow(new TestWindowContainerBuilder().setLayer(1));
587        }
588
589        TestWindowContainer getChildAt(int index) {
590            return mChildren.get(index);
591        }
592
593        @Override
594        boolean isAnimating() {
595            return mIsAnimating || super.isAnimating();
596        }
597
598        @Override
599        boolean isVisible() {
600            return mIsVisible;
601        }
602
603        @Override
604        boolean fillsParent() {
605            return mFillsParent;
606        }
607
608        void setFillsParent(boolean fillsParent) {
609            mFillsParent = fillsParent;
610        }
611    }
612
613    private class TestWindowContainerBuilder {
614        private int mLayer;
615        private boolean mIsAnimating;
616        private boolean mIsVisible;
617
618        public TestWindowContainerBuilder() {
619            reset();
620        }
621
622        TestWindowContainerBuilder setLayer(int layer) {
623            mLayer = layer;
624            return this;
625        }
626
627        TestWindowContainerBuilder setIsAnimating(boolean isAnimating) {
628            mIsAnimating = isAnimating;
629            return this;
630        }
631
632        TestWindowContainerBuilder setIsVisible(boolean isVisible) {
633            mIsVisible = isVisible;
634            return this;
635        }
636
637        TestWindowContainerBuilder reset() {
638            mLayer = 0;
639            mIsAnimating = false;
640            mIsVisible = false;
641            return this;
642        }
643
644        TestWindowContainer build() {
645            return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible);
646        }
647    }
648}
649