1 /*
2  * Copyright (C) 2018 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.OPSTR_SYSTEM_ALERT_WINDOW;
21 
22 import static androidx.test.InstrumentationRegistry.getInstrumentation;
23 
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.ArgumentMatchers.isNull;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.reset;
33 import static org.mockito.Mockito.timeout;
34 import static org.mockito.Mockito.verify;
35 
36 import android.app.AppOpsManager;
37 import android.os.Process;
38 import android.platform.test.annotations.Presubmit;
39 
40 import androidx.test.rule.ActivityTestRule;
41 
42 import com.android.compatibility.common.util.AppOpsUtils;
43 
44 import org.junit.AfterClass;
45 import org.junit.BeforeClass;
46 import org.junit.Rule;
47 import org.junit.Test;
48 
49 import java.io.IOException;
50 import java.util.concurrent.TimeUnit;
51 
52 /**
53  * Test whether system alert window properly interacts with app ops.
54  *
55  * Build/Install/Run:
56  *     atest CtsWindowManagerDeviceTestCases:AlertWindowsAppOpsTests
57  */
58 @Presubmit
59 public class AlertWindowsAppOpsTests {
60     private static final long APP_OP_CHANGE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(2);
61 
62     private static int sPreviousSawAppOp;
63 
64     @Rule
65     public final ActivityTestRule<AlertWindowsAppOpsTestsActivity> mActivityRule =
66             new ActivityTestRule<>(AlertWindowsAppOpsTestsActivity.class);
67 
68     @BeforeClass
grantSystemAlertWindowAccess()69     public static void grantSystemAlertWindowAccess() throws IOException {
70         String packageName = getInstrumentation().getContext().getPackageName();
71         sPreviousSawAppOp = AppOpsUtils.getOpMode(packageName, OPSTR_SYSTEM_ALERT_WINDOW);
72         AppOpsUtils.setOpMode(packageName, OPSTR_SYSTEM_ALERT_WINDOW, MODE_ALLOWED);
73     }
74 
75     @AfterClass
revokeSystemAlertWindowAccess()76     public static void revokeSystemAlertWindowAccess() throws IOException {
77         AppOpsUtils.setOpMode(getInstrumentation().getContext().getPackageName(),
78                 OPSTR_SYSTEM_ALERT_WINDOW, sPreviousSawAppOp);
79     }
80 
81     @Test
testSystemAlertWindowAppOpsInitiallyAllowed()82     public void testSystemAlertWindowAppOpsInitiallyAllowed() {
83         final String packageName = getInstrumentation().getContext().getPackageName();
84         final int uid = Process.myUid();
85 
86         final AppOpsManager appOpsManager = getInstrumentation().getContext()
87                 .getSystemService(AppOpsManager.class);
88         final AppOpsManager.OnOpActiveChangedListener listener = mock(
89                 AppOpsManager.OnOpActiveChangedListener.class);
90 
91         // Launch our activity.
92         final AlertWindowsAppOpsTestsActivity activity = mActivityRule.getActivity();
93 
94         // Start watching for app op
95         appOpsManager.startWatchingActive(new String[] { OPSTR_SYSTEM_ALERT_WINDOW },
96                 getInstrumentation().getContext().getMainExecutor(), listener);
97 
98         // Assert the app op is not started
99         assertFalse(appOpsManager.isOpActive(OPSTR_SYSTEM_ALERT_WINDOW, uid, packageName));
100 
101 
102         // Show a system alert window.
103         getInstrumentation().runOnMainSync(activity::showSystemAlertWindow);
104 
105         // The app op should start
106         verify(listener, timeout(APP_OP_CHANGE_TIMEOUT_MILLIS)
107                 .only()).onOpActiveChanged(eq(OPSTR_SYSTEM_ALERT_WINDOW),
108                 eq(uid), eq(packageName), isNull(), eq(true), anyInt(), anyInt());
109 
110         // The app op should be reported as started
111         assertTrue(appOpsManager.isOpActive(OPSTR_SYSTEM_ALERT_WINDOW,
112                 uid, packageName));
113 
114 
115         // Start with a clean slate
116         reset(listener);
117 
118         // Hide a system alert window.
119         getInstrumentation().runOnMainSync(activity::hideSystemAlertWindow);
120 
121         // The app op should finish
122         verify(listener, timeout(APP_OP_CHANGE_TIMEOUT_MILLIS)
123                 .only()).onOpActiveChanged(eq(OPSTR_SYSTEM_ALERT_WINDOW),
124                 eq(uid), eq(packageName), isNull(), eq(false), anyInt(), anyInt());
125 
126         // The app op should be reported as finished
127         assertFalse(appOpsManager.isOpActive(OPSTR_SYSTEM_ALERT_WINDOW, uid, packageName));
128 
129 
130         // Start with a clean slate
131         reset(listener);
132 
133         // Stop watching for app op
134         appOpsManager.stopWatchingActive(listener);
135 
136         // Show a system alert window
137         getInstrumentation().runOnMainSync(activity::showSystemAlertWindow);
138 
139         // No other callbacks expected
140         verify(listener, timeout(APP_OP_CHANGE_TIMEOUT_MILLIS).times(0))
141                 .onOpActiveChanged(eq(OPSTR_SYSTEM_ALERT_WINDOW),
142                         anyInt(), anyString(), anyBoolean());
143 
144         // The app op should be reported as started
145         assertTrue(appOpsManager.isOpActive(OPSTR_SYSTEM_ALERT_WINDOW, uid, packageName));
146     }
147 }
148