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