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