• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.view.ViewGroup.LayoutParams.MATCH_PARENT;
20 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
21 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
22 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
23 
24 import static androidx.test.InstrumentationRegistry.getInstrumentation;
25 
26 import static org.junit.Assert.assertEquals;
27 
28 import android.graphics.Insets;
29 import android.graphics.Point;
30 import android.platform.test.annotations.Presubmit;
31 import android.view.Display;
32 import android.view.View;
33 import android.view.WindowInsets;
34 import android.view.WindowInsets.Side;
35 import android.view.WindowInsets.Type;
36 import android.view.WindowManager;
37 
38 import androidx.test.filters.FlakyTest;
39 
40 import com.android.compatibility.common.util.PollingCheck;
41 
42 import org.junit.Ignore;
43 import org.junit.Test;
44 
45 /**
46  * Test whether WindowManager performs the correct layout while the app applies the fit-window-
47  * insets APIs.
48  *
49  * Build/Install/Run:
50  *     atest CtsWindowManagerDeviceTestCases:WindowInsetsLayoutTests
51  */
52 @FlakyTest(detail = "Promote once confirmed non-flaky")
53 @Presubmit
54 public class WindowInsetsLayoutTests extends WindowManagerTestBase {
55 
56     private final static long TIMEOUT = 1000; // milliseconds
57 
58     @Test
testSetFitInsetsTypes()59     public void testSetFitInsetsTypes() {
60         final TestActivity activity = startActivity(TestActivity.class);
61 
62         // Make sure the main window has been laid out.
63         final View mainWindowRoot = activity.getWindow().getDecorView();
64         PollingCheck.waitFor(TIMEOUT, () -> mainWindowRoot.getWidth() > 0);
65 
66         getInstrumentation().runOnMainSync(() -> {
67             activity.assertMatchDisplay();
68         });
69 
70         testSetFitInsetsTypesInner(Type.statusBars(), activity, mainWindowRoot);
71         testSetFitInsetsTypesInner(Type.navigationBars(), activity, mainWindowRoot);
72         testSetFitInsetsTypesInner(Type.systemBars(), activity, mainWindowRoot);
73     }
74 
testSetFitInsetsTypesInner( int types, TestActivity activity, View mainWindowRoot)75     private void testSetFitInsetsTypesInner(
76             int types, TestActivity activity, View mainWindowRoot) {
77         getInstrumentation().runOnMainSync(() -> {
78             activity.addChildWindow(types, Side.all(), false);
79         });
80 
81         // Make sure the child window has been laid out.
82         final View childWindowRoot = activity.getChildWindowRoot();
83         PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
84 
85         getInstrumentation().runOnMainSync(() -> {
86             final WindowInsets windowInsets = mainWindowRoot.getRootWindowInsets();
87             final Insets insets = windowInsets.getInsets(types);
88             final int[] locationOnScreen = new int[2];
89             childWindowRoot.getLocationOnScreen(locationOnScreen);
90             assertEquals(insets.left, locationOnScreen[0]);
91             assertEquals(insets.top, locationOnScreen[1]);
92             assertEquals(insets.right,
93                     mainWindowRoot.getWidth() - locationOnScreen[0] - childWindowRoot.getWidth());
94             assertEquals(insets.bottom,
95                     mainWindowRoot.getHeight()- locationOnScreen[1] - childWindowRoot.getHeight());
96             activity.removeChildWindow();
97         });
98     }
99 
100     @Test
testSetFitInsetsSides()101     public void testSetFitInsetsSides() {
102         final TestActivity activity = startActivity(TestActivity.class);
103 
104         // Make sure the main window has been laid out.
105         final View mainWindowRoot = activity.getWindow().getDecorView();
106         PollingCheck.waitFor(TIMEOUT, () -> mainWindowRoot.getWidth() > 0);
107 
108         getInstrumentation().runOnMainSync(() -> {
109             activity.assertMatchDisplay();
110         });
111 
112         testSetFitInsetsSidesInner(Side.LEFT, activity, mainWindowRoot);
113         testSetFitInsetsSidesInner(Side.TOP, activity, mainWindowRoot);
114         testSetFitInsetsSidesInner(Side.RIGHT, activity, mainWindowRoot);
115         testSetFitInsetsSidesInner(Side.BOTTOM, activity, mainWindowRoot);
116     }
117 
testSetFitInsetsSidesInner( int sides, TestActivity activity, View mainWindowRoot)118     private void testSetFitInsetsSidesInner(
119             int sides, TestActivity activity, View mainWindowRoot) {
120         final int types = Type.systemBars();
121         getInstrumentation().runOnMainSync(() -> {
122             activity.addChildWindow(types, sides, false);
123         });
124 
125         // Make sure the child window has been laid out.
126         final View childWindowRoot = activity.getChildWindowRoot();
127         PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
128 
129         getInstrumentation().runOnMainSync(() -> {
130             final WindowInsets windowInsets = mainWindowRoot.getRootWindowInsets();
131             final Insets insets = windowInsets.getInsets(types);
132             final int[] locationOnScreen = new int[2];
133             childWindowRoot.getLocationOnScreen(locationOnScreen);
134             assertEquals((sides & Side.LEFT) != 0 ? insets.left : 0, locationOnScreen[0]);
135             assertEquals((sides & Side.TOP) != 0 ? insets.top : 0, locationOnScreen[1]);
136             assertEquals((sides & Side.RIGHT) != 0 ? insets.right : 0,
137                     mainWindowRoot.getWidth() - locationOnScreen[0] - childWindowRoot.getWidth());
138             assertEquals((sides & Side.BOTTOM) != 0 ? insets.bottom : 0,
139                     mainWindowRoot.getHeight()- locationOnScreen[1] - childWindowRoot.getHeight());
140             activity.removeChildWindow();
141         });
142     }
143 
144     @Test
testSetFitInsetsIgnoringVisibility()145     public void testSetFitInsetsIgnoringVisibility() {
146         final TestActivity activity = startActivity(TestActivity.class);
147 
148         // Make sure the main window has been laid out.
149         final View mainWindowRoot = activity.getWindow().getDecorView();
150         PollingCheck.waitFor(TIMEOUT, () -> mainWindowRoot.getWidth() > 0);
151 
152         final int types = Type.systemBars();
153         final int sides = Side.all();
154         final int[] locationAndSize1 = new int[4];
155         final int[] locationAndSize2 = new int[4];
156 
157         getInstrumentation().runOnMainSync(() -> {
158             activity.assertMatchDisplay();
159             activity.addChildWindow(types, sides, false);
160         });
161 
162         // Make sure the 1st child window has been laid out.
163         final View childWindowRoot1 = activity.getChildWindowRoot();
164         PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot1.getWidth() > 0);
165 
166         getInstrumentation().runOnMainSync(() -> {
167             childWindowRoot1.getLocationOnScreen(locationAndSize1);
168             locationAndSize1[2] = childWindowRoot1.getWidth();
169             locationAndSize1[3] = childWindowRoot1.getHeight();
170             activity.removeChildWindow();
171 
172             mainWindowRoot.getWindowInsetsController().hide(types);
173 
174             activity.addChildWindow(types, sides, true);
175         });
176 
177         // Make sure the 2nd child window has been laid out.
178         final View childWindowRoot2 = activity.getChildWindowRoot();
179         PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot2.getWidth() > 0);
180 
181         getInstrumentation().runOnMainSync(() -> {
182             childWindowRoot2.getLocationOnScreen(locationAndSize2);
183             locationAndSize2[2] = childWindowRoot2.getWidth();
184             locationAndSize2[3] = childWindowRoot2.getHeight();
185             activity.removeChildWindow();
186         });
187 
188         for (int i = 0; i < 4; i++) {
189             assertEquals(locationAndSize1[i], locationAndSize2[i]);
190         }
191     }
192 
193     public static class TestActivity extends FocusableActivity {
194 
195         private View mChildWindowRoot;
196 
addChildWindow(int types, int sides, boolean ignoreVis)197         void addChildWindow(int types, int sides, boolean ignoreVis) {
198             final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
199             attrs.type = TYPE_APPLICATION_PANEL;
200             attrs.width = MATCH_PARENT;
201             attrs.height = MATCH_PARENT;
202             attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
203             attrs.flags = FLAG_NOT_FOCUSABLE;
204             attrs.setFitInsetsTypes(types);
205             attrs.setFitInsetsSides(sides);
206             attrs.setFitInsetsIgnoringVisibility(ignoreVis);
207             mChildWindowRoot = new View(this);
208             getWindowManager().addView(mChildWindowRoot, attrs);
209         }
210 
removeChildWindow()211         void removeChildWindow() {
212             getWindowManager().removeViewImmediate(mChildWindowRoot);
213         }
214 
getChildWindowRoot()215         View getChildWindowRoot() {
216             return mChildWindowRoot;
217         }
218 
assertMatchDisplay()219         void assertMatchDisplay() {
220             final View rootView = getWindow().getDecorView();
221             final Display display = rootView.getDisplay();
222             final Point size = new Point();
223             display.getRealSize(size);
224             assertEquals(size.x, rootView.getWidth());
225             assertEquals(size.y, rootView.getHeight());
226             final int[] locationOnScreen = new int[2];
227             rootView.getLocationOnScreen(locationOnScreen);
228             assertEquals(0 /* expected x */, locationOnScreen[0]);
229             assertEquals(0 /* expected y */, locationOnScreen[1]);
230         }
231     }
232 }
233