Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
     20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
     21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
     22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
     23 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
     24 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
     25 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
     26 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
     27 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
     28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
     29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
     30 import static android.content.res.Configuration.EMPTY;
     31 import static org.junit.Assert.assertEquals;
     32 import static org.junit.Assert.assertTrue;
     33 
     34 import android.content.res.Configuration;
     35 import android.platform.test.annotations.Presubmit;
     36 import android.support.test.filters.SmallTest;
     37 import android.support.test.runner.AndroidJUnit4;
     38 import org.junit.Test;
     39 import org.junit.runner.RunWith;
     40 
     41 import java.util.ArrayList;
     42 import java.util.List;
     43 
     44 /**
     45  * Test class for {@link ConfigurationContainer}.
     46  *
     47  * Build/Install/Run:
     48  *  bit FrameworksServicesTests:com.android.server.wm.ConfigurationContainerTests
     49  */
     50 @SmallTest
     51 @Presubmit
     52 @RunWith(AndroidJUnit4.class)
     53 public class ConfigurationContainerTests {
     54 
     55     @Test
     56     public void testConfigurationInit() throws Exception {
     57         // Check root container initial config.
     58         final TestConfigurationContainer root = new TestConfigurationContainer();
     59         assertEquals(EMPTY, root.getOverrideConfiguration());
     60         assertEquals(EMPTY, root.getMergedOverrideConfiguration());
     61         assertEquals(EMPTY, root.getConfiguration());
     62 
     63         // Check child initial config.
     64         final TestConfigurationContainer child1 = root.addChild();
     65         assertEquals(EMPTY, child1.getOverrideConfiguration());
     66         assertEquals(EMPTY, child1.getMergedOverrideConfiguration());
     67         assertEquals(EMPTY, child1.getConfiguration());
     68 
     69         // Check child initial config if root has overrides.
     70         final Configuration rootOverrideConfig = new Configuration();
     71         rootOverrideConfig.fontScale = 1.3f;
     72         root.onOverrideConfigurationChanged(rootOverrideConfig);
     73         final TestConfigurationContainer child2 = root.addChild();
     74         assertEquals(EMPTY, child2.getOverrideConfiguration());
     75         assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
     76         assertEquals(rootOverrideConfig, child2.getConfiguration());
     77 
     78         // Check child initial config if root has parent config set.
     79         final Configuration rootParentConfig = new Configuration();
     80         rootParentConfig.fontScale = 0.8f;
     81         rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE;
     82         root.onConfigurationChanged(rootParentConfig);
     83         final Configuration rootFullConfig = new Configuration(rootParentConfig);
     84         rootFullConfig.updateFrom(rootOverrideConfig);
     85 
     86         final TestConfigurationContainer child3 = root.addChild();
     87         assertEquals(EMPTY, child3.getOverrideConfiguration());
     88         assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
     89         assertEquals(rootFullConfig, child3.getConfiguration());
     90     }
     91 
     92     @Test
     93     public void testConfigurationChangeOnAddRemove() throws Exception {
     94         // Init root's config.
     95         final TestConfigurationContainer root = new TestConfigurationContainer();
     96         final Configuration rootOverrideConfig = new Configuration();
     97         rootOverrideConfig.fontScale = 1.3f;
     98         root.onOverrideConfigurationChanged(rootOverrideConfig);
     99 
    100         // Init child's config.
    101         final TestConfigurationContainer child = root.addChild();
    102         final Configuration childOverrideConfig = new Configuration();
    103         childOverrideConfig.densityDpi = 320;
    104         child.onOverrideConfigurationChanged(childOverrideConfig);
    105         final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
    106         mergedOverrideConfig.updateFrom(childOverrideConfig);
    107 
    108         // Check configuration update when child is removed from parent.
    109         root.removeChild(child);
    110         assertEquals(childOverrideConfig, child.getOverrideConfiguration());
    111         assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
    112         assertEquals(mergedOverrideConfig, child.getConfiguration());
    113 
    114         // It may be paranoia... but let's check if parent's config didn't change after removal.
    115         assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
    116         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
    117         assertEquals(rootOverrideConfig, root.getConfiguration());
    118 
    119         // Init different root
    120         final TestConfigurationContainer root2 = new TestConfigurationContainer();
    121         final Configuration rootOverrideConfig2 = new Configuration();
    122         rootOverrideConfig2.fontScale = 1.1f;
    123         root2.onOverrideConfigurationChanged(rootOverrideConfig2);
    124 
    125         // Check configuration update when child is added to different parent.
    126         mergedOverrideConfig.setTo(rootOverrideConfig2);
    127         mergedOverrideConfig.updateFrom(childOverrideConfig);
    128         root2.addChild(child);
    129         assertEquals(childOverrideConfig, child.getOverrideConfiguration());
    130         assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
    131         assertEquals(mergedOverrideConfig, child.getConfiguration());
    132     }
    133 
    134     @Test
    135     public void testConfigurationChangePropagation() throws Exception {
    136         // Builds 3-level vertical hierarchy with one configuration container on each level.
    137         // In addition to different overrides on each level, everyone in hierarchy will have one
    138         // common overridden value - orientation;
    139 
    140         // Init root's config.
    141         final TestConfigurationContainer root = new TestConfigurationContainer();
    142         final Configuration rootOverrideConfig = new Configuration();
    143         rootOverrideConfig.fontScale = 1.3f;
    144         rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
    145         root.onOverrideConfigurationChanged(rootOverrideConfig);
    146 
    147         // Init children.
    148         final TestConfigurationContainer child1 = root.addChild();
    149         final Configuration childOverrideConfig1 = new Configuration();
    150         childOverrideConfig1.densityDpi = 320;
    151         childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
    152         child1.onOverrideConfigurationChanged(childOverrideConfig1);
    153 
    154         final TestConfigurationContainer child2 = child1.addChild();
    155         final Configuration childOverrideConfig2 = new Configuration();
    156         childOverrideConfig2.screenWidthDp = 150;
    157         childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
    158         child2.onOverrideConfigurationChanged(childOverrideConfig2);
    159 
    160         // Check configuration on all levels when root override is updated.
    161         rootOverrideConfig.smallestScreenWidthDp = 200;
    162         root.onOverrideConfigurationChanged(rootOverrideConfig);
    163 
    164         final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
    165         mergedOverrideConfig1.updateFrom(childOverrideConfig1);
    166         final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1);
    167 
    168         final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1);
    169         mergedOverrideConfig2.updateFrom(childOverrideConfig2);
    170         final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
    171 
    172         assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
    173         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
    174         assertEquals(rootOverrideConfig, root.getConfiguration());
    175 
    176         assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
    177         assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
    178         assertEquals(mergedConfig1, child1.getConfiguration());
    179 
    180         assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
    181         assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
    182         assertEquals(mergedConfig2, child2.getConfiguration());
    183 
    184         // Check configuration on all levels when root parent config is updated.
    185         final Configuration rootParentConfig = new Configuration();
    186         rootParentConfig.screenHeightDp = 100;
    187         rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    188         root.onConfigurationChanged(rootParentConfig);
    189         final Configuration mergedRootConfig = new Configuration(rootParentConfig);
    190         mergedRootConfig.updateFrom(rootOverrideConfig);
    191 
    192         mergedConfig1.setTo(mergedRootConfig);
    193         mergedConfig1.updateFrom(mergedOverrideConfig1);
    194 
    195         mergedConfig2.setTo(mergedConfig1);
    196         mergedConfig2.updateFrom(mergedOverrideConfig2);
    197 
    198         assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
    199         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
    200         assertEquals(mergedRootConfig, root.getConfiguration());
    201 
    202         assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
    203         assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
    204         assertEquals(mergedConfig1, child1.getConfiguration());
    205 
    206         assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
    207         assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
    208         assertEquals(mergedConfig2, child2.getConfiguration());
    209     }
    210 
    211     @Test
    212     public void testSetWindowingMode() throws Exception {
    213         final TestConfigurationContainer root = new TestConfigurationContainer();
    214         root.setWindowingMode(WINDOWING_MODE_UNDEFINED);
    215         final TestConfigurationContainer child = root.addChild();
    216         child.setWindowingMode(WINDOWING_MODE_FREEFORM);
    217         assertEquals(WINDOWING_MODE_UNDEFINED, root.getWindowingMode());
    218         assertEquals(WINDOWING_MODE_FREEFORM, child.getWindowingMode());
    219 
    220         root.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
    221         assertEquals(WINDOWING_MODE_FULLSCREEN, root.getWindowingMode());
    222         assertEquals(WINDOWING_MODE_FREEFORM, child.getWindowingMode());
    223     }
    224 
    225     @Test
    226     public void testSetActivityType() throws Exception {
    227         final TestConfigurationContainer root = new TestConfigurationContainer();
    228         root.setActivityType(ACTIVITY_TYPE_UNDEFINED);
    229         final TestConfigurationContainer child = root.addChild();
    230         child.setActivityType(ACTIVITY_TYPE_STANDARD);
    231         assertEquals(ACTIVITY_TYPE_UNDEFINED, root.getActivityType());
    232         assertEquals(ACTIVITY_TYPE_STANDARD, child.getActivityType());
    233 
    234         boolean gotException = false;
    235         try {
    236             // Can't change activity type once set.
    237             child.setActivityType(ACTIVITY_TYPE_HOME);
    238         } catch (IllegalStateException e) {
    239             gotException = true;
    240         }
    241         assertTrue("Can't change activity type once set.", gotException);
    242 
    243         // TODO: Commenting out for now until we figure-out a good way to test these rules that
    244         // should only apply to system process.
    245         /*
    246         gotException = false;
    247         try {
    248             // Parent can't change child's activity type once set.
    249             root.setActivityType(ACTIVITY_TYPE_HOME);
    250         } catch (IllegalStateException e) {
    251             gotException = true;
    252         }
    253         assertTrue("Parent can't change activity type once set.", gotException);
    254         assertEquals(ACTIVITY_TYPE_HOME, root.getActivityType());
    255 
    256         final TestConfigurationContainer child2 = new TestConfigurationContainer();
    257         child2.setActivityType(ACTIVITY_TYPE_RECENTS);
    258 
    259         gotException = false;
    260         try {
    261             // Can't re-parent to a different activity type.
    262             root.addChild(child2);
    263         } catch (IllegalStateException e) {
    264             gotException = true;
    265         }
    266         assertTrue("Can't re-parent to a different activity type.", gotException);
    267         */
    268 
    269     }
    270 
    271     @Test
    272     public void testRegisterConfigurationChangeListener() throws Exception {
    273         final TestConfigurationContainer container = new TestConfigurationContainer();
    274         final TestConfigurationChangeListener listener = new TestConfigurationChangeListener();
    275         final Configuration config = new Configuration();
    276         config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
    277         config.windowConfiguration.setAppBounds(10, 10, 10, 10);
    278         container.onOverrideConfigurationChanged(config);
    279         container.registerConfigurationChangeListener(listener);
    280         // Assert listener got the current config. of the container after it was registered.
    281         assertEquals(config, listener.mOverrideConfiguration);
    282         // Assert listener gets changes to override configuration.
    283         container.onOverrideConfigurationChanged(EMPTY);
    284         assertEquals(EMPTY, listener.mOverrideConfiguration);
    285     }
    286 
    287     /**
    288      * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
    289      * for testing.
    290      */
    291     private class TestConfigurationContainer
    292             extends ConfigurationContainer<TestConfigurationContainer> {
    293         private List<TestConfigurationContainer> mChildren = new ArrayList<>();
    294         private TestConfigurationContainer mParent;
    295 
    296         TestConfigurationContainer addChild(TestConfigurationContainer childContainer) {
    297             childContainer.mParent = this;
    298             childContainer.onParentChanged();
    299             mChildren.add(childContainer);
    300             return childContainer;
    301         }
    302 
    303         TestConfigurationContainer addChild() {
    304             return addChild(new TestConfigurationContainer());
    305         }
    306 
    307         void removeChild(TestConfigurationContainer child) {
    308             child.mParent = null;
    309             child.onParentChanged();
    310         }
    311 
    312         @Override
    313         protected int getChildCount() {
    314             return mChildren.size();
    315         }
    316 
    317         @Override
    318         protected TestConfigurationContainer getChildAt(int index) {
    319             return mChildren.get(index);
    320         }
    321 
    322         @Override
    323         protected ConfigurationContainer getParent() {
    324             return mParent;
    325         }
    326     }
    327 
    328     private class TestConfigurationChangeListener implements ConfigurationContainerListener {
    329 
    330         final Configuration mOverrideConfiguration = new Configuration();
    331 
    332         public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
    333             mOverrideConfiguration.setTo(overrideConfiguration);
    334         }
    335     }
    336 }
    337