• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.server.wm;
18 
19 import static android.app.AppOpsManager.MODE_ALLOWED;
20 import static android.app.AppOpsManager.MODE_ERRORED;
21 import static android.app.AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW;
22 import static android.server.wm.ShellCommandHelper.executeShellCommand;
23 import static android.server.wm.alertwindowapp.Components.ALERT_WINDOW_TEST_ACTIVITY;
24 import static android.server.wm.alertwindowappsdk25.Components.SDK25_ALERT_WINDOW_TEST_ACTIVITY;
25 
26 import static org.hamcrest.MatcherAssert.assertThat;
27 import static org.hamcrest.Matchers.empty;
28 import static org.hamcrest.Matchers.greaterThan;
29 import static org.hamcrest.Matchers.hasSize;
30 import static org.hamcrest.Matchers.lessThan;
31 import static org.junit.Assert.assertEquals;
32 import static org.junit.Assert.assertNotNull;
33 import static org.junit.Assert.assertTrue;
34 
35 import android.content.ComponentName;
36 import android.platform.test.annotations.AppModeFull;
37 import android.platform.test.annotations.Presubmit;
38 
39 import com.android.compatibility.common.util.AppOpsUtils;
40 
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 
45 import java.util.List;
46 
47 /**
48  * Build/Install/Run:
49  *     atest CtsWindowManagerDeviceTestCases:AlertWindowsTests
50  */
51 @Presubmit
52 @AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_TASKS")
53 public class AlertWindowsTests extends ActivityManagerTestBase {
54 
55     // From WindowManager.java
56     private static final int TYPE_BASE_APPLICATION      = 1;
57     private static final int FIRST_SYSTEM_WINDOW        = 2000;
58 
59     private static final int TYPE_PHONE                 = FIRST_SYSTEM_WINDOW + 2;
60     private static final int TYPE_SYSTEM_ALERT          = FIRST_SYSTEM_WINDOW + 3;
61     private static final int TYPE_SYSTEM_OVERLAY        = FIRST_SYSTEM_WINDOW + 6;
62     private static final int TYPE_PRIORITY_PHONE        = FIRST_SYSTEM_WINDOW + 7;
63     private static final int TYPE_SYSTEM_ERROR          = FIRST_SYSTEM_WINDOW + 10;
64     private static final int TYPE_APPLICATION_OVERLAY   = FIRST_SYSTEM_WINDOW + 38;
65 
66     private static final int TYPE_STATUS_BAR            = FIRST_SYSTEM_WINDOW;
67     private static final int TYPE_INPUT_METHOD          = FIRST_SYSTEM_WINDOW + 11;
68     private static final int TYPE_NAVIGATION_BAR        = FIRST_SYSTEM_WINDOW + 19;
69 
70     private static final int[] ALERT_WINDOW_TYPES = {
71             TYPE_PHONE,
72             TYPE_PRIORITY_PHONE,
73             TYPE_SYSTEM_ALERT,
74             TYPE_SYSTEM_ERROR,
75             TYPE_SYSTEM_OVERLAY,
76             TYPE_APPLICATION_OVERLAY
77     };
78     private static final int[] SYSTEM_WINDOW_TYPES = {
79             TYPE_STATUS_BAR,
80             TYPE_INPUT_METHOD,
81             TYPE_NAVIGATION_BAR
82     };
83 
84     @Before
85     @Override
setUp()86     public void setUp() throws Exception {
87         super.setUp();
88         resetPermissionState(ALERT_WINDOW_TEST_ACTIVITY);
89         resetPermissionState(SDK25_ALERT_WINDOW_TEST_ACTIVITY);
90     }
91 
92     @After
tearDown()93     public void tearDown() throws Exception {
94         resetPermissionState(ALERT_WINDOW_TEST_ACTIVITY);
95         resetPermissionState(SDK25_ALERT_WINDOW_TEST_ACTIVITY);
96         stopTestPackage(ALERT_WINDOW_TEST_ACTIVITY.getPackageName());
97         stopTestPackage(SDK25_ALERT_WINDOW_TEST_ACTIVITY.getPackageName());
98     }
99 
100     @Test
testAlertWindowAllowed()101     public void testAlertWindowAllowed() throws Exception {
102         runAlertWindowTest(ALERT_WINDOW_TEST_ACTIVITY, true /* hasAlertWindowPermission */,
103                 true /* atLeastO */);
104     }
105 
106     @Test
testAlertWindowDisallowed()107     public void testAlertWindowDisallowed() throws Exception {
108         runAlertWindowTest(ALERT_WINDOW_TEST_ACTIVITY, false /* hasAlertWindowPermission */,
109                 true /* atLeastO */);
110     }
111 
112     @Test
testAlertWindowAllowedSdk25()113     public void testAlertWindowAllowedSdk25() throws Exception {
114         runAlertWindowTest(SDK25_ALERT_WINDOW_TEST_ACTIVITY, true /* hasAlertWindowPermission */,
115                 false /* atLeastO */);
116     }
117 
118     @Test
testAlertWindowDisallowedSdk25()119     public void testAlertWindowDisallowedSdk25() throws Exception {
120         runAlertWindowTest(SDK25_ALERT_WINDOW_TEST_ACTIVITY, false /* hasAlertWindowPermission */,
121                 false /* atLeastO */);
122     }
123 
runAlertWindowTest(final ComponentName activityName, final boolean hasAlertWindowPermission, final boolean atLeastO)124     private void runAlertWindowTest(final ComponentName activityName,
125             final boolean hasAlertWindowPermission, final boolean atLeastO) throws Exception {
126         setAlertWindowPermission(activityName, hasAlertWindowPermission);
127 
128         executeShellCommand(getAmStartCmd(activityName));
129         mWmState.computeState(new WaitForValidActivityState(activityName));
130         mWmState.assertVisibility(activityName, true);
131 
132         assertAlertWindows(activityName, hasAlertWindowPermission, atLeastO);
133     }
134 
allWindowsHidden(List<WindowManagerState.WindowState> windows)135     private boolean allWindowsHidden(List<WindowManagerState.WindowState> windows) {
136         for (WindowManagerState.WindowState ws : windows) {
137             if (ws.isSurfaceShown()) {
138                 return false;
139             }
140         }
141         return true;
142     }
143 
assertAlertWindows(final ComponentName activityName, final boolean hasAlertWindowPermission, final boolean atLeastO)144     private void assertAlertWindows(final ComponentName activityName,
145             final boolean hasAlertWindowPermission, final boolean atLeastO) throws Exception {
146         final String packageName = activityName.getPackageName();
147         final WindowManagerState wmState = mWmState;
148 
149         final List<WindowManagerState.WindowState> alertWindows =
150                 wmState.getWindowsByPackageName(packageName, ALERT_WINDOW_TYPES);
151 
152         if (!hasAlertWindowPermission) {
153             // When running in VR Mode, an App Op restriction is
154             // in place for SYSTEM_ALERT_WINDOW, which allows the window
155             // to be created, but will be hidden instead.
156             if (isUiModeLockedToVrHeadset()) {
157                 assertThat("Should not be empty alertWindows",
158                         alertWindows, hasSize(greaterThan(0)));
159                 assertTrue("All alert windows should be hidden",
160                         allWindowsHidden(alertWindows));
161             } else {
162                 assertThat("Should be empty alertWindows", alertWindows, empty());
163                 assertTrue(AppOpsUtils.rejectedOperationLogged(packageName,
164                         OPSTR_SYSTEM_ALERT_WINDOW));
165                 return;
166             }
167         }
168 
169         if (atLeastO) {
170             // Assert that only TYPE_APPLICATION_OVERLAY was created.
171             for (WindowManagerState.WindowState win : alertWindows) {
172                 assertEquals("Can't create win=" + win + " on SDK O or greater",
173                         win.getType(), TYPE_APPLICATION_OVERLAY);
174             }
175         }
176 
177         final WindowManagerState.WindowState mainAppWindow =
178                 wmState.getWindowByPackageName(packageName, TYPE_BASE_APPLICATION);
179 
180         assertNotNull(mainAppWindow);
181 
182         final WindowManagerState.WindowState lowestAlertWindow = alertWindows.get(0);
183         final WindowManagerState.WindowState highestAlertWindow =
184                 alertWindows.get(alertWindows.size() - 1);
185 
186         // Assert that the alert windows have higher z-order than the main app window
187         assertThat("lowestAlertWindow has higher z-order than mainAppWindow",
188                 wmState.getZOrder(lowestAlertWindow),
189                 greaterThan(wmState.getZOrder(mainAppWindow)));
190 
191         // Assert that legacy alert windows have a lower z-order than the new alert window layer.
192         final WindowManagerState.WindowState appOverlayWindow =
193                 wmState.getWindowByPackageName(packageName, TYPE_APPLICATION_OVERLAY);
194         if (appOverlayWindow != null && highestAlertWindow != appOverlayWindow) {
195             assertThat("highestAlertWindow has lower z-order than appOverlayWindow",
196                     wmState.getZOrder(highestAlertWindow),
197                     lessThan(wmState.getZOrder(appOverlayWindow)));
198         }
199 
200         // Assert that alert windows are below key system windows.
201         final List<WindowManagerState.WindowState> systemWindows =
202                 wmState.getWindowsByPackageName(packageName, SYSTEM_WINDOW_TYPES);
203         if (!systemWindows.isEmpty()) {
204             final WindowManagerState.WindowState lowestSystemWindow = alertWindows.get(0);
205             assertThat("highestAlertWindow has lower z-order than lowestSystemWindow",
206                     wmState.getZOrder(highestAlertWindow),
207                     lessThan(wmState.getZOrder(lowestSystemWindow)));
208         }
209         assertTrue(AppOpsUtils.allowedOperationLogged(packageName, OPSTR_SYSTEM_ALERT_WINDOW));
210     }
211 
212     // Resets the permission states for a package to the system defaults.
213     // Also clears the app operation logs for this package, required to test that displaying
214     // the alert window gets logged.
resetPermissionState(ComponentName activityName)215     private void resetPermissionState(ComponentName activityName) throws Exception {
216         AppOpsUtils.reset(activityName.getPackageName());
217     }
218 
setAlertWindowPermission(final ComponentName activityName, final boolean allow)219     private void setAlertWindowPermission(final ComponentName activityName, final boolean allow)
220             throws Exception {
221         int mode = allow ? MODE_ALLOWED : MODE_ERRORED;
222         AppOpsUtils.setOpMode(activityName.getPackageName(), OPSTR_SYSTEM_ALERT_WINDOW, mode);
223     }
224 }
225