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_ASSISTANT; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 23 import static android.app.WindowConfiguration.ROTATION_UNDEFINED; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 26 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 27 import static android.app.WindowConfiguration.WINDOW_CONFIG_ALWAYS_ON_TOP; 28 import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; 29 import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS; 30 import static android.app.WindowConfiguration.WINDOW_CONFIG_MAX_BOUNDS; 31 import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION; 32 import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE; 33 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 34 import static android.view.Surface.ROTATION_270; 35 36 import static org.junit.Assert.assertEquals; 37 import static org.junit.Assert.assertFalse; 38 import static org.junit.Assert.assertNotEquals; 39 import static org.junit.Assert.assertTrue; 40 41 import android.app.WindowConfiguration; 42 import android.content.res.Configuration; 43 import android.graphics.Rect; 44 import android.platform.test.annotations.Presubmit; 45 import android.view.DisplayInfo; 46 import android.view.Surface; 47 48 import androidx.test.filters.SmallTest; 49 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 /** 55 * Test class to for {@link android.app.WindowConfiguration}. 56 * 57 * Build/Install/Run: 58 * atest WmTests:WindowConfigurationTests 59 */ 60 @SmallTest 61 @Presubmit 62 @RunWith(WindowTestRunner.class) 63 public class WindowConfigurationTests extends WindowTestsBase { 64 private Rect mParentBounds; 65 66 @Before setUp()67 public void setUp() throws Exception { 68 mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/); 69 } 70 71 /** Tests {@link android.app.WindowConfiguration#diff(WindowConfiguration, boolean)}. */ 72 @Test testDiff()73 public void testDiff() { 74 final Configuration config1 = new Configuration(); 75 final WindowConfiguration winConfig1 = config1.windowConfiguration; 76 final Configuration config2 = new Configuration(); 77 final WindowConfiguration winConfig2 = config2.windowConfiguration; 78 final Configuration config3 = new Configuration(); 79 final WindowConfiguration winConfig3 = config3.windowConfiguration; 80 final Configuration config4 = new Configuration(); 81 final WindowConfiguration winConfig4 = config4.windowConfiguration; 82 final Configuration config5 = new Configuration(); 83 final WindowConfiguration winConfig5 = config5.windowConfiguration; 84 85 winConfig1.setAppBounds(0, 1, 1, 0); 86 winConfig2.setAppBounds(1, 2, 2, 1); 87 winConfig3.setAppBounds(winConfig1.getAppBounds()); 88 winConfig4.setRotation(Surface.ROTATION_90); 89 winConfig5.setAppBounds(winConfig1.getAppBounds()); 90 91 assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config2)); 92 assertEquals(0, config1.diffPublicOnly(config2)); 93 assertEquals(WINDOW_CONFIG_APP_BOUNDS, 94 winConfig1.diff(winConfig2, false /* compareUndefined */)); 95 96 winConfig2.setWindowingMode(WINDOWING_MODE_FREEFORM); 97 assertEquals(WINDOW_CONFIG_APP_BOUNDS | WINDOW_CONFIG_WINDOWING_MODE, 98 winConfig1.diff(winConfig2, false /* compareUndefined */)); 99 100 winConfig2.setAlwaysOnTop(true); 101 assertEquals(WINDOW_CONFIG_APP_BOUNDS | WINDOW_CONFIG_WINDOWING_MODE 102 | WINDOW_CONFIG_ALWAYS_ON_TOP, 103 winConfig1.diff(winConfig2, false /* compareUndefined */)); 104 105 assertEquals(WINDOW_CONFIG_ROTATION, 106 winConfig1.diff(winConfig4, false /* compareUndefined */)); 107 108 assertEquals(0, config1.diff(config3)); 109 assertEquals(0, config1.diffPublicOnly(config3)); 110 assertEquals(0, winConfig1.diff(winConfig3, false /* compareUndefined */)); 111 112 winConfig1.setMaxBounds(1, 1, 1, 1); 113 winConfig5.setMaxBounds(2, 2, 2, 2); 114 assertEquals(WINDOW_CONFIG_MAX_BOUNDS, 115 winConfig1.diff(winConfig5, false /* compareUndefined */)); 116 assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config5)); 117 assertEquals(0, config1.diffPublicOnly(config5)); 118 } 119 120 /** Tests {@link android.app.WindowConfiguration#compareTo(WindowConfiguration)}. */ 121 @Test testConfigurationCompareTo()122 public void testConfigurationCompareTo() { 123 final Configuration blankConfig = new Configuration(); 124 final WindowConfiguration blankWinConfig = new WindowConfiguration(); 125 126 final Configuration config1 = new Configuration(); 127 final WindowConfiguration winConfig1 = config1.windowConfiguration; 128 winConfig1.setAppBounds(1, 2, 3, 4); 129 winConfig1.setMaxBounds(1, 2, 3, 4); 130 131 final Configuration config2 = new Configuration(config1); 132 final WindowConfiguration winConfig2 = config2.windowConfiguration; 133 134 assertEquals(0, config1.compareTo(config2)); 135 assertEquals(0, winConfig1.compareTo(winConfig2)); 136 137 // Different windowing mode 138 winConfig2.setWindowingMode(WINDOWING_MODE_FREEFORM); 139 assertNotEquals(0, config1.compareTo(config2)); 140 assertNotEquals(0, winConfig1.compareTo(winConfig2)); 141 winConfig2.setWindowingMode(winConfig1.getWindowingMode()); 142 143 // Different always on top state 144 winConfig2.setAlwaysOnTop(true); 145 assertNotEquals(0, config1.compareTo(config2)); 146 assertNotEquals(0, winConfig1.compareTo(winConfig2)); 147 winConfig2.setAlwaysOnTop(winConfig1.isAlwaysOnTop()); 148 149 // Different bounds 150 winConfig2.setAppBounds(0, 2, 3, 4); 151 assertNotEquals(0, config1.compareTo(config2)); 152 assertNotEquals(0, winConfig1.compareTo(winConfig2)); 153 winConfig2.setAppBounds(winConfig1.getAppBounds()); 154 155 // No bounds 156 assertEquals(-1, config1.compareTo(blankConfig)); 157 assertEquals(-1, winConfig1.compareTo(blankWinConfig)); 158 159 // Different rotation 160 winConfig2.setRotation(Surface.ROTATION_180); 161 assertNotEquals(0, config1.compareTo(config2)); 162 assertNotEquals(0, winConfig1.compareTo(winConfig2)); 163 winConfig2.setRotation(winConfig1.getRotation()); 164 165 // Different max bounds 166 winConfig2.setMaxBounds(0, 2, 3, 4); 167 assertNotEquals(0, config1.compareTo(config2)); 168 assertNotEquals(0, winConfig1.compareTo(winConfig2)); 169 winConfig2.setMaxBounds(winConfig1.getMaxBounds()); 170 171 assertEquals(1, blankConfig.compareTo(config1)); 172 assertEquals(1, blankWinConfig.compareTo(winConfig1)); 173 } 174 175 @Test testSetActivityType()176 public void testSetActivityType() { 177 final WindowConfiguration config = new WindowConfiguration(); 178 config.setActivityType(ACTIVITY_TYPE_HOME); 179 assertEquals(ACTIVITY_TYPE_HOME, config.getActivityType()); 180 181 // Allowed to change from app process. 182 config.setActivityType(ACTIVITY_TYPE_STANDARD); 183 assertEquals(ACTIVITY_TYPE_STANDARD, config.getActivityType()); 184 } 185 186 /** Ensures the configuration app bounds at the root level match the app dimensions. */ 187 @Test testAppBounds_RootConfigurationBounds()188 public void testAppBounds_RootConfigurationBounds() { 189 final DisplayInfo info = mDisplayContent.getDisplayInfo(); 190 info.appWidth = 1024; 191 info.appHeight = 768; 192 193 final Rect appBounds = mWm.computeNewConfiguration( 194 mDisplayContent.getDisplayId()).windowConfiguration.getAppBounds(); 195 // The bounds should always be positioned in the top left besides cutout. 196 final int expectedLeft = info.displayCutout != null 197 ? info.displayCutout.getSafeInsetLeft() : 0; 198 final int expectedTop = info.displayCutout != null 199 ? info.displayCutout.getSafeInsetTop() : 0; 200 assertEquals(expectedLeft, appBounds.left); 201 assertEquals(expectedTop, appBounds.top); 202 203 // The bounds should equal the defined app width and height 204 assertEquals(info.appWidth, appBounds.width()); 205 assertEquals(info.appHeight, appBounds.height()); 206 } 207 208 /** Ensure the window always has a caption in Freeform window mode or display mode. */ 209 @Test testCaptionShownForFreeformWindowingMode()210 public void testCaptionShownForFreeformWindowingMode() { 211 final WindowConfiguration config = new WindowConfiguration(); 212 config.setActivityType(ACTIVITY_TYPE_STANDARD); 213 config.setWindowingMode(WINDOWING_MODE_FREEFORM); 214 config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN); 215 assertTrue(config.hasWindowDecorCaption()); 216 217 config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); 218 assertTrue(config.hasWindowDecorCaption()); 219 220 config.setWindowingMode(WINDOWING_MODE_FULLSCREEN); 221 assertTrue(config.hasWindowDecorCaption()); 222 223 config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN); 224 assertFalse(config.hasWindowDecorCaption()); 225 } 226 227 /** Caption should not show for non-standard activity window. */ 228 @Test testCaptionNotShownForNonStandardActivityType()229 public void testCaptionNotShownForNonStandardActivityType() { 230 final WindowConfiguration config = new WindowConfiguration(); 231 config.setActivityType(ACTIVITY_TYPE_HOME); 232 config.setWindowingMode(WINDOWING_MODE_FREEFORM); 233 config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); 234 assertFalse(config.hasWindowDecorCaption()); 235 236 config.setActivityType(ACTIVITY_TYPE_ASSISTANT); 237 assertFalse(config.hasWindowDecorCaption()); 238 239 config.setActivityType(ACTIVITY_TYPE_RECENTS); 240 assertFalse(config.hasWindowDecorCaption()); 241 242 config.setActivityType(ACTIVITY_TYPE_STANDARD); 243 assertTrue(config.hasWindowDecorCaption()); 244 } 245 246 @Test testMaskedSetTo()247 public void testMaskedSetTo() { 248 final WindowConfiguration config = new WindowConfiguration(); 249 final WindowConfiguration other = new WindowConfiguration(); 250 other.setBounds(new Rect(10, 10, 100, 100)); 251 other.setRotation(ROTATION_270); 252 config.setWindowingMode(WINDOWING_MODE_FULLSCREEN); 253 config.setBounds(null); 254 255 // no change 256 config.setTo(other, 0); 257 assertTrue(config.getBounds().isEmpty()); 258 assertEquals(ROTATION_UNDEFINED, config.getRotation()); 259 assertEquals(WINDOWING_MODE_FULLSCREEN, config.getWindowingMode()); 260 261 final int justBoundsAndRotation = WINDOW_CONFIG_BOUNDS | WINDOW_CONFIG_ROTATION; 262 config.setTo(other, justBoundsAndRotation); 263 assertEquals(other.getBounds(), config.getBounds()); 264 assertEquals(other.getRotation(), config.getRotation()); 265 assertEquals(WINDOWING_MODE_FULLSCREEN, config.getWindowingMode()); 266 267 // unsets as well 268 final int justWindowingMode = WINDOW_CONFIG_WINDOWING_MODE; 269 config.setTo(other, justWindowingMode); 270 assertEquals(WINDOWING_MODE_UNDEFINED, config.getWindowingMode()); 271 } 272 } 273