• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android.server.wm;
18 
19 import static android.server.wm.app.Components.UI_SCALING_TEST_ACTIVITY;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25 
26 import android.content.ComponentName;
27 
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.Parameterized;
33 
34 import java.util.Arrays;
35 
36 /**
37  * The test is focused on compatibility scaling, and tests the feature form two sides.
38  * 1. It checks that the applications "sees" the metrics in PXs, but the DP metrics remain the same.
39  * 2. It checks the WindowManagerServer state, and makes sure that the scaling is correctly
40  * reflected in the WindowState.
41  *
42  * This is achieved by launching a {@link android.server.wm.app.UiScalingTestActivity} and having it
43  * reporting the metrics it receives.
44  * The Activity also draws 3 UI elements: a text, a red square with a 100dp side and a blue square
45  * with a 100px side.
46  * The text and the red square should have the same when rendered on the screen (by HWC) both when
47  * the compat downscaling is enabled and disabled.
48  * TODO(b/180098454): Add tests to make sure that the UI elements, which have their sizes declared
49  * in DPs (the text and the red square) have the same sizes on the screen (after composition).
50  *
51  * <p>Build/Install/Run:
52  *     atest CtsWindowManagerDeviceTestCases:CompatScaleTests
53  */
54 @RunWith(Parameterized.class)
55 public class CompatScaleTests extends ActivityManagerTestBase {
56 
57     @Parameterized.Parameters(name = "{0}")
data()58     public static Iterable<Object[]> data() {
59         return Arrays.asList(new Object[][] {
60                 { "DOWNSCALE_30", 0.3f },
61                 { "DOWNSCALE_35", 0.35f },
62                 { "DOWNSCALE_40", 0.4f },
63                 { "DOWNSCALE_45", 0.45f },
64                 { "DOWNSCALE_50", 0.5f },
65                 { "DOWNSCALE_55", 0.55f },
66                 { "DOWNSCALE_60", 0.6f },
67                 { "DOWNSCALE_65", 0.65f },
68                 { "DOWNSCALE_70", 0.7f },
69                 { "DOWNSCALE_75", 0.75f },
70                 { "DOWNSCALE_80", 0.8f },
71                 { "DOWNSCALE_85", 0.85f },
72                 { "DOWNSCALE_90", 0.9f },
73         });
74     }
75 
76     private static final ComponentName ACTIVITY_UNDER_TEST = UI_SCALING_TEST_ACTIVITY;
77     private static final String PACKAGE_UNDER_TEST = ACTIVITY_UNDER_TEST.getPackageName();
78     private static final float EPSILON_GLOBAL_SCALE = 0.01f;
79 
80     private final String mCompatChangeName;
81     private final float mCompatScale;
82     private final float mInvCompatScale;
83     private CommandSession.SizeInfo mAppSizesNormal;
84     private CommandSession.SizeInfo mAppSizesDownscaled;
85     private WindowManagerState.WindowState mWindowStateNormal;
86     private WindowManagerState.WindowState mWindowStateDownscaled;
87 
CompatScaleTests(String compatChangeName, float compatScale)88     public CompatScaleTests(String compatChangeName, float compatScale) {
89         mCompatChangeName = compatChangeName;
90         mCompatScale = compatScale;
91         mInvCompatScale = 1 / mCompatScale;
92     }
93 
94     // TODO(b/180343437): replace @Before with @BeforeParam
95     @Before
launchInNormalAndDownscaleMode_collectSizesAndWindowState()96     public void launchInNormalAndDownscaleMode_collectSizesAndWindowState() {
97         // Launch activity with downscaling *disabled* and get the sizes it reports and its Window
98         // state.
99         launchActivity();
100         mAppSizesNormal = getActivityReportedSizes();
101         mWindowStateNormal = getPackageWindowState();
102 
103         // Now launch the same activity with downscaling *enabled* and get the sizes it reports and
104         // its Window state.
105         enableDownscaling(mCompatChangeName);
106         mWmState.waitForActivityRemoved(ACTIVITY_UNDER_TEST);
107         launchActivity();
108         mAppSizesDownscaled = getActivityReportedSizes();
109         mWindowStateDownscaled = getPackageWindowState();
110     }
111 
112     /**
113      * Tests that the Density DPI that the application receives from the
114      * {@link android.content.res.Configuration} is correctly scaled in the downscaled mode.
115      * @see android.content.res.Configuration#densityDpi
116      */
117     @Test
test_config_densityDpi_scalesCorrectly_inCompatDownscalingMode()118     public void test_config_densityDpi_scalesCorrectly_inCompatDownscalingMode() {
119         assertScaled("Density DPI should scale by " + mCompatScale,
120                 mAppSizesNormal.densityDpi, mCompatScale, mAppSizesDownscaled.densityDpi);
121     }
122 
123     /**
124      * Tests that the screen sizes in DPs that the application receives from the
125      * {@link android.content.res.Configuration} are NOT scaled in the downscaled mode.
126      * @see android.content.res.Configuration#screenWidthDp
127      * @see android.content.res.Configuration#screenHeightDp
128      * @see android.content.res.Configuration#smallestScreenWidthDp
129      */
130     @Test
test_config_screenSize_inDPs_doesNotChange_inCompatDownscalingMode()131     public void test_config_screenSize_inDPs_doesNotChange_inCompatDownscalingMode() {
132         assertEquals("Width shouldn't change",
133                 mAppSizesNormal.widthDp, mAppSizesDownscaled.widthDp);
134         assertEquals("Height shouldn't change",
135                 mAppSizesNormal.heightDp, mAppSizesDownscaled.heightDp);
136         assertEquals("Smallest Width shouldn't change",
137                 mAppSizesNormal.smallestWidthDp, mAppSizesDownscaled.smallestWidthDp);
138     }
139 
140     /**
141      * Tests that the Window sizes in PXs that the application receives from the
142      * {@link android.content.res.Configuration} are scaled correctly in the downscaled mode.
143      * @see android.content.res.Configuration#windowConfiguration
144      * @see android.app.WindowConfiguration#getBounds()
145      * @see android.app.WindowConfiguration#getAppBounds()
146      */
147     @Test
test_config_windowSizes_inPXs_scaleCorrectly_inCompatDownscalingMode()148     public void test_config_windowSizes_inPXs_scaleCorrectly_inCompatDownscalingMode() {
149         assertScaled("Width should scale by " + mCompatScale,
150                 mAppSizesNormal.windowWidth, mCompatScale, mAppSizesDownscaled.windowWidth);
151         assertScaled("Height should scale by " + mCompatScale,
152                 mAppSizesNormal.windowHeight, mCompatScale, mAppSizesDownscaled.windowHeight);
153         assertScaled("App width should scale by " + mCompatScale,
154                 mAppSizesNormal.windowAppWidth, mCompatScale, mAppSizesDownscaled.windowAppWidth);
155         assertScaled("App height should scale by " + mCompatScale,
156                 mAppSizesNormal.windowAppHeight, mCompatScale, mAppSizesDownscaled.windowAppHeight);
157     }
158 
159     /**
160      * Tests that the {@link android.util.DisplayMetrics} in PXs that the application can obtain via
161      * {@link android.content.res.Resources#getDisplayMetrics()} are scaled correctly in the
162      * downscaled mode.
163      * @see android.util.DisplayMetrics#widthPixels
164      * @see android.util.DisplayMetrics#heightPixels
165      */
166     @Test
test_displayMetrics_inPXs_scaleCorrectly_inCompatDownscalingMode()167     public void test_displayMetrics_inPXs_scaleCorrectly_inCompatDownscalingMode() {
168         assertScaled("Width should scale by " + mCompatScale,
169                 mAppSizesNormal.metricsWidth, mCompatScale, mAppSizesDownscaled.metricsWidth);
170         assertScaled("Height should scale by " + mCompatScale,
171                 mAppSizesNormal.metricsHeight, mCompatScale, mAppSizesDownscaled.metricsHeight);
172     }
173 
174     /**
175      * Tests that the dimensions of a {@link android.view.Display} in PXs that the application can
176      * obtain via {@link android.view.View#getDisplay()} are scaled correctly in the downscaled
177      * mode.
178      * @see android.view.Display#getSize(android.graphics.Point)
179      */
180     @Test
test_displaySize_inPXs_scaleCorrectly_inCompatDownscalingMode()181     public void test_displaySize_inPXs_scaleCorrectly_inCompatDownscalingMode() {
182         assertScaled("Width should scale by " + mCompatScale,
183                 mAppSizesNormal.displayWidth, mCompatScale, mAppSizesDownscaled.displayWidth);
184         assertScaled("Height should scale by " + mCompatScale,
185                 mAppSizesNormal.displayHeight, mCompatScale, mAppSizesDownscaled.displayHeight);
186     }
187 
188     /**
189      * Test that compatibility downscaling is reflected correctly on the WM side.
190      * @see android.server.wm.WindowManagerState.WindowState
191      */
192     @Test
test_windowState_inCompatDownscalingMode()193     public void test_windowState_inCompatDownscalingMode() {
194         // Check the "normal" window's state for disabled compat mode and appropriate global scale.
195         assertFalse("The Window should not be in the size compat mode",
196                 mWindowStateNormal.hasCompatScale());
197         assertEquals("The window should not be scaled",
198                 1f, mWindowStateNormal.getGlobalScale(), EPSILON_GLOBAL_SCALE);
199 
200         // Check the "downscaled" window's state for enabled compat mode and appropriate global
201         // scale.
202         assertTrue("The Window should be in the size compat mode",
203                 mWindowStateDownscaled.hasCompatScale());
204         assertEquals("The window should have global scale of " + mInvCompatScale,
205                 mInvCompatScale, mWindowStateDownscaled.getGlobalScale(), EPSILON_GLOBAL_SCALE);
206 
207         // Make sure the frame sizes changed correctly.
208         assertEquals("Window frame on should not change",
209                 mWindowStateNormal.getFrame(), mWindowStateDownscaled.getFrame());
210         assertScaled("Requested width should scale by " + mCompatScale,
211                 mWindowStateNormal.getRequestedWidth(), mCompatScale,
212                 mWindowStateDownscaled.getRequestedWidth());
213         assertScaled("Requested height should scale by " + mCompatScale,
214                 mWindowStateNormal.getRequestedHeight(), mCompatScale,
215                 mWindowStateDownscaled.getRequestedHeight());
216     }
217 
218     @After
tearDown()219     public void tearDown() {
220         disableDownscaling(mCompatChangeName);
221     }
222 
launchActivity()223     private void launchActivity() {
224         launchActivityInNewTask(ACTIVITY_UNDER_TEST);
225         mWmState.computeState(new WaitForValidActivityState(ACTIVITY_UNDER_TEST));
226     }
227 
getActivityReportedSizes()228     private CommandSession.SizeInfo getActivityReportedSizes() {
229         final CommandSession.SizeInfo details =
230                 getLastReportedSizesForActivity(ACTIVITY_UNDER_TEST);
231         assertNotNull(details);
232         return details;
233     }
234 
getPackageWindowState()235     private WindowManagerState.WindowState getPackageWindowState() {
236         return getPackageWindowState(PACKAGE_UNDER_TEST);
237     }
238 
enableDownscaling(String compatChangeName)239     private static void enableDownscaling(String compatChangeName) {
240         executeShellCommand("am compat enable " + compatChangeName + " " + PACKAGE_UNDER_TEST);
241         executeShellCommand("am compat enable DOWNSCALED " + PACKAGE_UNDER_TEST);
242     }
243 
disableDownscaling(String compatChangeName)244     private static void disableDownscaling(String compatChangeName) {
245         executeShellCommand("am compat disable DOWNSCALED " + PACKAGE_UNDER_TEST);
246         executeShellCommand("am compat disable " + compatChangeName + " " + PACKAGE_UNDER_TEST);
247     }
248 
assertScaled(String message, int baseValue, float expectedScale, int actualValue)249     private static void assertScaled(String message, int baseValue, float expectedScale,
250             int actualValue) {
251         // In order to account for possible rounding errors, let's calculate the actual scale and
252         // compare it's against the expected scale (allowing a small delta).
253         final float actualScale = ((float) actualValue) / baseValue;
254         assertEquals(message, expectedScale, actualScale, EPSILON_GLOBAL_SCALE);
255     }
256 }
257