1 /*
2  * Copyright (C) 2015 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.permission3.cts
18 
19 import androidx.test.filters.FlakyTest
20 import com.android.modules.utils.build.SdkLevel
21 import org.junit.Assume
22 import org.junit.Before
23 import org.junit.Test
24 
25 /**
26  * Runtime permission behavior tests for apps targeting API 23.
27  */
28 class PermissionTest23 : BaseUsePermissionTest() {
29     companion object {
30         private const val NON_EXISTENT_PERMISSION = "permission.does.not.exist"
31         private const val INVALID_PERMISSION = "$APP_PACKAGE_NAME.abadname"
32     }
33 
34     @Before
installApp23null35     fun installApp23() {
36         installPackage(APP_APK_PATH_23)
37     }
38 
39     @Test
testDefaultnull40     fun testDefault() {
41         // New permission model is denied by default
42         assertAppHasAllOrNoPermissions(false)
43     }
44 
45     @Test
testGrantednull46     fun testGranted() {
47         grantAppPermissions(android.Manifest.permission.READ_CALENDAR)
48 
49         // Read/write access should be allowed
50         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
51         assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
52         assertAppHasCalendarAccess(true)
53     }
54 
55     @Test
testInteractiveGrantnull56     fun testInteractiveGrant() {
57         // Start out without permission
58         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
59         assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
60         assertAppHasCalendarAccess(false)
61 
62         // Go through normal grant flow
63         requestAppPermissionsAndAssertResult(
64             android.Manifest.permission.READ_CALENDAR to true,
65             android.Manifest.permission.WRITE_CALENDAR to true
66         ) {
67             clickPermissionRequestAllowButton()
68         }
69 
70         // We should have permission now!
71         assertAppHasCalendarAccess(true)
72     }
73 
74     @Test
testRuntimeGroupGrantSpecificitynull75     fun testRuntimeGroupGrantSpecificity() {
76         // Start out without permission
77         assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
78         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
79 
80         // Request only one permission from the 'contacts' permission group
81         // Expect the permission is granted
82         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to true) {
83             clickPermissionRequestAllowButton()
84         }
85 
86         // Make sure no undeclared as used permissions are granted
87         assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
88     }
89 
90     @Test
testCancelledPermissionRequestnull91     fun testCancelledPermissionRequest() {
92         // Make sure we don't have the permission
93         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
94 
95         // Request the permission and cancel the request
96         // Expect the permission is not granted
97         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to false) {
98             clickPermissionRequestDenyButton()
99         }
100     }
101 
102     @Test
testRequestGrantedPermissionnull103     fun testRequestGrantedPermission() {
104         // Make sure we don't have the permission
105         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
106 
107         // Request the permission and allow it
108         // Expect the permission is granted
109         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to true) {
110             clickPermissionRequestAllowButton()
111         }
112 
113         // Request the permission and do nothing
114         // Expect the permission is granted
115         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to true) {}
116     }
117 
118     @Test
testDenialWithPrejudicenull119     fun testDenialWithPrejudice() {
120         // Make sure we don't have the permission
121         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
122 
123         // Request the permission and deny it
124         // Expect the permission is not granted
125         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to false) {
126             clickPermissionRequestDenyButton()
127         }
128 
129         // Request the permission and choose don't ask again
130         // Expect the permission is not granted
131         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to false) {
132             denyPermissionRequestWithPrejudice()
133         }
134 
135         // Request the permission and do nothing
136         // Expect the permission is not granted
137         requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to false) {}
138     }
139 
140     @FlakyTest
141     @Test
testRevokeAffectsWholeGroupnull142     fun testRevokeAffectsWholeGroup() {
143         // Grant the group
144         grantAppPermissions(android.Manifest.permission.READ_CALENDAR)
145 
146         // Make sure we have the permissions
147         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
148         assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
149 
150         // Revoke the group
151         revokeAppPermissions(android.Manifest.permission.READ_CALENDAR)
152 
153         // Make sure we don't have the permissions
154         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
155         assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
156     }
157 
158     @Test
testGrantPreviouslyRevokedWithPrejudiceShowsPromptnull159     fun testGrantPreviouslyRevokedWithPrejudiceShowsPrompt() {
160         // Make sure we don't have the permission
161         assertAppHasPermission(android.Manifest.permission.CAMERA, false)
162 
163         // Request the permission and deny it
164         // Expect the permission is not granted
165         requestAppPermissionsAndAssertResult(android.Manifest.permission.CAMERA to false) {
166             clickPermissionRequestDenyButton()
167         }
168 
169         // Request the permission and choose don't ask again
170         // Expect the permission is not granted
171         requestAppPermissionsAndAssertResult(android.Manifest.permission.CAMERA to false) {
172             denyPermissionRequestWithPrejudice()
173         }
174 
175         // Clear the denial with prejudice
176         grantAppPermissions(android.Manifest.permission.CAMERA)
177         revokeAppPermissions(android.Manifest.permission.CAMERA)
178 
179         // Make sure we don't have the permission
180         assertAppHasPermission(android.Manifest.permission.CAMERA, false)
181 
182         // Request the permission and allow it
183         // Make sure the permission is granted
184         requestAppPermissionsAndAssertResult(android.Manifest.permission.CAMERA to true) {
185             if (SdkLevel.isAtLeastS()) {
186                 clickPermissionRequestAllowForegroundButton()
187             } else {
188                 clickPermissionRequestAllowButton()
189             }
190         }
191     }
192 
193     @Test
testRequestNonRuntimePermissionnull194     fun testRequestNonRuntimePermission() {
195         // Make sure we don't have the permission
196         assertAppHasPermission(android.Manifest.permission.BIND_PRINT_SERVICE, false)
197 
198         // Request the permission and do nothing
199         // Expect the permission is not granted
200         requestAppPermissionsAndAssertResult(
201             android.Manifest.permission.BIND_PRINT_SERVICE to false
202         ) {}
203     }
204 
205     @Test
testRequestNonExistentPermissionnull206     fun testRequestNonExistentPermission() {
207         // Make sure we don't have the permission
208         assertAppHasPermission(NON_EXISTENT_PERMISSION, false)
209 
210         // Request the permission and do nothing
211         // Expect the permission is not granted
212         requestAppPermissionsAndAssertResult(NON_EXISTENT_PERMISSION to false) {}
213     }
214 
215     @Test
testRequestPermissionFromTwoGroupsnull216     fun testRequestPermissionFromTwoGroups() {
217         // Make sure we don't have the permissions
218         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
219         assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
220         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
221 
222         // Request the permission and allow it
223         // Expect the permission are granted
224         val result = requestAppPermissionsAndAssertResult(
225             android.Manifest.permission.WRITE_CONTACTS to true,
226             android.Manifest.permission.WRITE_CALENDAR to true
227         ) {
228             clickPermissionRequestAllowButton()
229             clickPermissionRequestAllowButton()
230         }
231 
232         // In API < N_MR1 all permissions of a group are granted. I.e. the grant was "expanded"
233         assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
234         // Even the contacts group was expanded, the read-calendar permission is not in the
235         // manifest, hence not granted.
236         assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
237     }
238 
239     @Test(timeout = 120000)
240     @FlakyTest
testNoResidualPermissionsOnUninstallnull241     fun testNoResidualPermissionsOnUninstall() {
242         Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
243 
244         // Grant all permissions
245         grantAppPermissions(
246             android.Manifest.permission.WRITE_CALENDAR,
247             android.Manifest.permission.WRITE_CONTACTS,
248             android.Manifest.permission.READ_SMS,
249             android.Manifest.permission.CALL_PHONE,
250             android.Manifest.permission.RECORD_AUDIO,
251             android.Manifest.permission.BODY_SENSORS,
252             android.Manifest.permission.CAMERA,
253             android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23
254         )
255         // Don't use UI for granting location permission as this shows another dialog
256         uiAutomation.grantRuntimePermission(
257             APP_PACKAGE_NAME, android.Manifest.permission.ACCESS_FINE_LOCATION
258         )
259         uiAutomation.grantRuntimePermission(
260             APP_PACKAGE_NAME, android.Manifest.permission.ACCESS_COARSE_LOCATION
261         )
262         uiAutomation.grantRuntimePermission(
263             APP_PACKAGE_NAME, android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
264         )
265 
266         uninstallPackage(APP_PACKAGE_NAME)
267         installPackage(APP_APK_PATH_23)
268 
269         // Make no permissions are granted after uninstalling and installing the app
270         assertAppHasAllOrNoPermissions(false)
271     }
272 
273     @Test
testNullPermissionRequestnull274     fun testNullPermissionRequest() {
275         // Go through normal grant flow
276         requestAppPermissionsAndAssertResult(null to false) {}
277     }
278 
279     @Test
testNullAndRealPermissionnull280     fun testNullAndRealPermission() {
281         // Make sure we don't have the permissions
282         assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
283         assertAppHasPermission(android.Manifest.permission.RECORD_AUDIO, false)
284 
285         // Request the permission and allow it
286         // Expect the permission are granted
287         requestAppPermissionsAndAssertResult(
288             null to false,
289             android.Manifest.permission.WRITE_CONTACTS to true,
290             null to false,
291             android.Manifest.permission.RECORD_AUDIO to true
292         ) {
293             if (SdkLevel.isAtLeastS()) {
294                 clickPermissionRequestAllowForegroundButton()
295             } else {
296                 clickPermissionRequestAllowButton()
297             }
298             clickPermissionRequestAllowButton()
299         }
300     }
301 
302     @Test
testInvalidPermissionnull303     fun testInvalidPermission() {
304         // Request the permission and allow it
305         // Expect the permission is not granted
306         requestAppPermissionsAndAssertResult(INVALID_PERMISSION to false) {}
307     }
308 
denyPermissionRequestWithPrejudicenull309     private fun denyPermissionRequestWithPrejudice() {
310         if (isTv || isWatch) {
311             clickPermissionRequestDontAskAgainButton()
312         } else {
313             clickPermissionRequestDenyAndDontAskAgainButton()
314         }
315     }
316 
assertAppHasAllOrNoPermissionsnull317     private fun assertAppHasAllOrNoPermissions(expectPermissions: Boolean) {
318         arrayOf(
319             android.Manifest.permission.SEND_SMS,
320             android.Manifest.permission.RECEIVE_SMS,
321             android.Manifest.permission.RECEIVE_WAP_PUSH,
322             android.Manifest.permission.RECEIVE_MMS,
323             android.Manifest.permission.READ_CALENDAR,
324             android.Manifest.permission.WRITE_CALENDAR,
325             android.Manifest.permission.WRITE_CONTACTS,
326             android.Manifest.permission.READ_SMS,
327             android.Manifest.permission.READ_PHONE_STATE,
328             android.Manifest.permission.READ_CALL_LOG,
329             android.Manifest.permission.WRITE_CALL_LOG,
330             android.Manifest.permission.ADD_VOICEMAIL,
331             android.Manifest.permission.CALL_PHONE,
332             android.Manifest.permission.USE_SIP,
333             android.Manifest.permission.PROCESS_OUTGOING_CALLS,
334             android.Manifest.permission.RECORD_AUDIO,
335             android.Manifest.permission.ACCESS_FINE_LOCATION,
336             android.Manifest.permission.ACCESS_COARSE_LOCATION,
337             android.Manifest.permission.CAMERA,
338             android.Manifest.permission.BODY_SENSORS,
339             android.Manifest.permission.READ_CELL_BROADCASTS,
340             // Split permissions
341             android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
342             // Storage permissions
343             android.Manifest.permission.READ_EXTERNAL_STORAGE,
344             android.Manifest.permission.WRITE_EXTERNAL_STORAGE
345         ).forEach {
346             assertAppHasPermission(it, expectPermissions)
347         }
348     }
349 }
350