1 /* 2 * Copyright (C) 2023 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.permission.cts 18 19 import android.Manifest 20 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND 21 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE 22 import android.app.Instrumentation 23 import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT 24 import android.companion.virtual.VirtualDeviceManager.VirtualDevice 25 import android.content.Context 26 import android.content.Intent 27 import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME 28 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED 29 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED 30 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET 31 import android.content.pm.PackageManager.PERMISSION_DENIED 32 import android.content.pm.PackageManager.PERMISSION_GRANTED 33 import android.os.Build 34 import android.os.UserHandle 35 import android.permission.PermissionManager 36 import android.permission.flags.Flags 37 import android.platform.test.annotations.AppModeFull 38 import android.platform.test.annotations.RequiresFlagsDisabled 39 import android.platform.test.annotations.RequiresFlagsEnabled 40 import android.platform.test.flag.junit.DeviceFlagsValueProvider 41 import android.virtualdevice.cts.common.VirtualDeviceRule 42 import androidx.test.ext.junit.runners.AndroidJUnit4 43 import androidx.test.filters.SdkSuppress 44 import androidx.test.platform.app.InstrumentationRegistry 45 import com.android.compatibility.common.util.SystemUtil.eventually 46 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow 47 import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts 48 import com.google.common.truth.Truth.assertThat 49 import org.junit.After 50 import org.junit.Before 51 import org.junit.Rule 52 import org.junit.Test 53 import org.junit.runner.RunWith 54 55 @RunWith(AndroidJUnit4::class) 56 @AppModeFull(reason = " cannot be accessed by instant apps") 57 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream") 58 class DevicePermissionsTest { 59 private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() 60 private val defaultDeviceContext = instrumentation.targetContext 61 62 private lateinit var virtualDevice: VirtualDevice 63 private lateinit var virtualDeviceContext: Context 64 private lateinit var persistentDeviceId: String 65 66 private lateinit var permissionManager: PermissionManager 67 68 @get:Rule 69 var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( 70 Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 71 Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, 72 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 73 Manifest.permission.GET_RUNTIME_PERMISSIONS 74 ) 75 76 @Rule @JvmField val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() 77 78 @Before setupnull79 fun setup() { 80 virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() 81 virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) 82 permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! 83 persistentDeviceId = virtualDevice.persistentDeviceId!! 84 runShellCommandOrThrow("pm install -r $TEST_APK") 85 } 86 87 @After cleanupnull88 fun cleanup() { 89 runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") 90 } 91 92 @RequiresFlagsEnabled( 93 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 94 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 95 ) 96 @Test testDeviceAwareRuntimePermissionIsGrantednull97 fun testDeviceAwareRuntimePermissionIsGranted() { 98 grantPermissionAndAssertGranted(Manifest.permission.CAMERA, virtualDeviceContext) 99 } 100 101 @RequiresFlagsDisabled(Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED) 102 @Test testDeviceAwareRuntimePermissionGrantIsInheritednull103 fun testDeviceAwareRuntimePermissionGrantIsInherited() { 104 grantPermissionAndAssertGranted(Manifest.permission.CAMERA, defaultDeviceContext) 105 106 assertPermission(Manifest.permission.CAMERA, PERMISSION_GRANTED, virtualDeviceContext) 107 } 108 109 @Test testNonDeviceAwareRuntimePermissionGrantIsInheritednull110 fun testNonDeviceAwareRuntimePermissionGrantIsInherited() { 111 grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext) 112 113 assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) 114 } 115 116 @RequiresFlagsEnabled( 117 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 118 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 119 ) 120 @Test testDeviceAwareRuntimePermissionIsRevokednull121 fun testDeviceAwareRuntimePermissionIsRevoked() { 122 grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) 123 124 revokePermissionAndAssertDenied(DEVICE_AWARE_PERMISSION, virtualDeviceContext) 125 } 126 127 @Test testNonDeviceAwareRuntimePermissionIsRevokedForDefaultDevicenull128 fun testNonDeviceAwareRuntimePermissionIsRevokedForDefaultDevice() { 129 grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext) 130 assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) 131 // Revoke call from virtualDeviceContext should revoke for default device as well. 132 revokePermissionAndAssertDenied(NON_DEVICE_AWARE_PERMISSION, virtualDeviceContext) 133 assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, defaultDeviceContext) 134 } 135 136 @Test testNormalPermissionGrantIsInheritednull137 fun testNormalPermissionGrantIsInherited() { 138 assertPermission(Manifest.permission.INTERNET, PERMISSION_GRANTED, virtualDeviceContext) 139 } 140 141 @Test testSignaturePermissionGrantIsInheritednull142 fun testSignaturePermissionGrantIsInherited() { 143 assertPermission(CUSTOM_SIGNATURE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) 144 } 145 146 @Test testOneTimePermissionIsRevokednull147 fun testOneTimePermissionIsRevoked() { 148 grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) 149 virtualDeviceContext.packageManager.updatePermissionFlags( 150 DEVICE_AWARE_PERMISSION, 151 TEST_PACKAGE_NAME, 152 FLAG_PERMISSION_ONE_TIME, 153 FLAG_PERMISSION_ONE_TIME, 154 UserHandle.of(virtualDeviceContext.userId) 155 ) 156 157 permissionManager.startOneTimePermissionSession( 158 TEST_PACKAGE_NAME, 159 0, 160 0, 161 IMPORTANCE_FOREGROUND, 162 IMPORTANCE_FOREGROUND_SERVICE 163 ) 164 eventually { 165 assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext) 166 } 167 } 168 169 @RequiresFlagsEnabled( 170 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 171 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 172 ) 173 @Test testRevokeSelfPermissionOnKillnull174 fun testRevokeSelfPermissionOnKill() { 175 grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) 176 177 revokeSelfPermission(DEVICE_AWARE_PERMISSION, virtualDeviceContext) 178 eventually { 179 assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext) 180 } 181 } 182 183 @RequiresFlagsEnabled( 184 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 185 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 186 ) 187 @Test testGrantAndRevokeDeviceAwarePermissionByPersistentDeviceIdnull188 fun testGrantAndRevokeDeviceAwarePermissionByPersistentDeviceId() { 189 val deviceAwarePermission = DEVICE_AWARE_PERMISSION 190 191 permissionManager.grantRuntimePermission( 192 TEST_PACKAGE_NAME, 193 deviceAwarePermission, 194 persistentDeviceId 195 ) 196 197 assertThat( 198 permissionManager.checkPermission( 199 deviceAwarePermission, 200 TEST_PACKAGE_NAME, 201 virtualDevice.persistentDeviceId!! 202 ) 203 ) 204 .isEqualTo(PERMISSION_GRANTED) 205 206 assertThat( 207 permissionManager.checkPermission( 208 deviceAwarePermission, 209 TEST_PACKAGE_NAME, 210 PERSISTENT_DEVICE_ID_DEFAULT 211 ) 212 ) 213 .isEqualTo(PERMISSION_DENIED) 214 215 permissionManager.revokeRuntimePermission( 216 TEST_PACKAGE_NAME, 217 deviceAwarePermission, 218 persistentDeviceId, 219 "test" 220 ) 221 222 assertThat( 223 permissionManager.checkPermission( 224 deviceAwarePermission, 225 TEST_PACKAGE_NAME, 226 virtualDevice.persistentDeviceId!! 227 ) 228 ) 229 .isEqualTo(PERMISSION_DENIED) 230 } 231 232 @RequiresFlagsEnabled( 233 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 234 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 235 ) 236 @Test testUpdateAndGetPermissionFlagsByPersistentDeviceIdnull237 fun testUpdateAndGetPermissionFlagsByPersistentDeviceId() { 238 val deviceAwarePermission = DEVICE_AWARE_PERMISSION 239 val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED 240 val flag = FLAG_PERMISSION_USER_SET 241 242 assertThat( 243 permissionManager.getPermissionFlags( 244 TEST_PACKAGE_NAME, 245 deviceAwarePermission, 246 persistentDeviceId 247 ) 248 ) 249 .isEqualTo(0) 250 251 permissionManager.updatePermissionFlags( 252 TEST_PACKAGE_NAME, 253 deviceAwarePermission, 254 persistentDeviceId, 255 flagMask, 256 flag 257 ) 258 259 assertThat( 260 permissionManager.getPermissionFlags( 261 TEST_PACKAGE_NAME, 262 deviceAwarePermission, 263 persistentDeviceId 264 ) 265 ) 266 .isEqualTo(FLAG_PERMISSION_USER_SET) 267 } 268 269 @RequiresFlagsEnabled( 270 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 271 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 272 ) 273 @Test testAllPermissionStatesApiGrantForVirtualDevicenull274 fun testAllPermissionStatesApiGrantForVirtualDevice() { 275 // Setting a flag explicitly so that the permission consistently stays in the state 276 permissionManager.updatePermissionFlags( 277 TEST_PACKAGE_NAME, 278 DEVICE_AWARE_PERMISSION, 279 PERSISTENT_DEVICE_ID_DEFAULT, 280 FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, 281 FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED 282 ) 283 284 assertThat( 285 permissionManager 286 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId) 287 .isEmpty() 288 ) 289 .isTrue() 290 291 permissionManager.grantRuntimePermission( 292 TEST_PACKAGE_NAME, 293 DEVICE_AWARE_PERMISSION, 294 persistentDeviceId 295 ) 296 297 val permissionStateMap = 298 permissionManager.getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId) 299 assertThat(permissionStateMap.size).isEqualTo(1) 300 assertThat(permissionStateMap[DEVICE_AWARE_PERMISSION]!!.isGranted).isTrue() 301 assertThat(permissionStateMap[DEVICE_AWARE_PERMISSION]!!.flags).isEqualTo(0) 302 303 assertThat( 304 permissionManager 305 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 306 DEVICE_AWARE_PERMISSION]!! 307 .isGranted 308 ) 309 .isFalse() 310 311 permissionManager.revokeRuntimePermission( 312 TEST_PACKAGE_NAME, 313 DEVICE_AWARE_PERMISSION, 314 persistentDeviceId, 315 "test" 316 ) 317 318 assertThat( 319 permissionManager 320 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId) 321 .contains(DEVICE_AWARE_PERMISSION) 322 ) 323 .isFalse() 324 } 325 326 @RequiresFlagsEnabled( 327 Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, 328 Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED 329 ) 330 @Test testAllPermissionStatesApiFlagsForVirtualDevicenull331 fun testAllPermissionStatesApiFlagsForVirtualDevice() { 332 val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED 333 val flag = FLAG_PERMISSION_USER_SET 334 335 assertThat(permissionManager.getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)) 336 .isEmpty() 337 338 permissionManager.updatePermissionFlags( 339 TEST_PACKAGE_NAME, 340 DEVICE_AWARE_PERMISSION, 341 persistentDeviceId, 342 flagMask, 343 flag 344 ) 345 346 assertThat( 347 hasPermission( 348 permissionManager 349 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[ 350 DEVICE_AWARE_PERMISSION]!! 351 .flags, 352 flag 353 ) 354 ) 355 .isTrue() 356 357 assertThat( 358 hasPermission( 359 permissionManager 360 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[ 361 DEVICE_AWARE_PERMISSION]!! 362 .flags, 363 FLAG_PERMISSION_USER_FIXED 364 ) 365 ) 366 .isFalse() 367 } 368 369 @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 370 @Test testAllPermissionStatesApiGrantForDefaultDevicenull371 fun testAllPermissionStatesApiGrantForDefaultDevice() { 372 // Setting a flag explicitly so that the permission consistently stays in the state upon 373 // revoke 374 permissionManager.updatePermissionFlags( 375 TEST_PACKAGE_NAME, 376 DEVICE_AWARE_PERMISSION, 377 PERSISTENT_DEVICE_ID_DEFAULT, 378 FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, 379 FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED 380 ) 381 382 permissionManager.grantRuntimePermission( 383 TEST_PACKAGE_NAME, 384 DEVICE_AWARE_PERMISSION, 385 PERSISTENT_DEVICE_ID_DEFAULT 386 ) 387 388 assertThat( 389 permissionManager 390 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 391 DEVICE_AWARE_PERMISSION]!! 392 .isGranted 393 ) 394 .isTrue() 395 396 assertThat( 397 permissionManager 398 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId) 399 .contains(DEVICE_AWARE_PERMISSION) 400 ) 401 .isFalse() 402 403 permissionManager.revokeRuntimePermission( 404 TEST_PACKAGE_NAME, 405 DEVICE_AWARE_PERMISSION, 406 PERSISTENT_DEVICE_ID_DEFAULT, 407 "test" 408 ) 409 410 assertThat( 411 permissionManager 412 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 413 DEVICE_AWARE_PERMISSION]!! 414 .isGranted 415 ) 416 .isFalse() 417 } 418 419 @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 420 @Test testAllPermissionStatesApiFlagsForDefaultDevicenull421 fun testAllPermissionStatesApiFlagsForDefaultDevice() { 422 val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED 423 val flag = FLAG_PERMISSION_USER_SET 424 425 assertThat( 426 permissionManager 427 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT) 428 .contains(DEVICE_AWARE_PERMISSION) 429 ) 430 .isFalse() 431 432 permissionManager.updatePermissionFlags( 433 TEST_PACKAGE_NAME, 434 DEVICE_AWARE_PERMISSION, 435 PERSISTENT_DEVICE_ID_DEFAULT, 436 flagMask, 437 flag 438 ) 439 440 assertThat( 441 hasPermission( 442 permissionManager 443 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 444 DEVICE_AWARE_PERMISSION]!! 445 .flags, 446 flag 447 ) 448 ) 449 .isTrue() 450 451 assertThat( 452 hasPermission( 453 permissionManager 454 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 455 DEVICE_AWARE_PERMISSION]!! 456 .flags, 457 FLAG_PERMISSION_USER_FIXED 458 ) 459 ) 460 .isFalse() 461 } 462 463 @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 464 @Test testAllPermissionStatesApiThatNonDeviceAwareRuntimePermissionGrantIsNotInheritednull465 fun testAllPermissionStatesApiThatNonDeviceAwareRuntimePermissionGrantIsNotInherited() { 466 permissionManager.grantRuntimePermission( 467 TEST_PACKAGE_NAME, 468 NON_DEVICE_AWARE_PERMISSION, 469 PERSISTENT_DEVICE_ID_DEFAULT 470 ) 471 472 assertThat( 473 permissionManager 474 .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ 475 NON_DEVICE_AWARE_PERMISSION]!! 476 .isGranted 477 ) 478 .isTrue() 479 480 assertThat( 481 permissionManager 482 .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId) 483 .contains(NON_DEVICE_AWARE_PERMISSION) 484 ) 485 .isFalse() 486 } 487 hasPermissionnull488 private fun hasPermission(permissionFlags: Int, permissionBit: Int): Boolean = 489 permissionFlags and permissionBit != 0 490 491 private fun revokeSelfPermission(permissionName: String, context: Context) { 492 val intent = Intent(PERMISSION_SELF_REVOKE_INTENT) 493 intent.setClassName(TEST_PACKAGE_NAME, PERMISSION_SELF_REVOKE_RECEIVER) 494 intent.putExtra("permissionName", permissionName) 495 intent.putExtra("deviceID", context.deviceId) 496 context.sendBroadcast(intent) 497 waitForBroadcasts() 498 } 499 grantPermissionAndAssertGrantednull500 private fun grantPermissionAndAssertGranted(permissionName: String, context: Context) { 501 context.packageManager.grantRuntimePermission( 502 TEST_PACKAGE_NAME, 503 permissionName, 504 UserHandle.of(context.userId) 505 ) 506 assertPermission(permissionName, PERMISSION_GRANTED, context) 507 } 508 revokePermissionAndAssertDeniednull509 private fun revokePermissionAndAssertDenied(permissionName: String, context: Context) { 510 context.packageManager.revokeRuntimePermission( 511 TEST_PACKAGE_NAME, 512 permissionName, 513 UserHandle.of(context.userId) 514 ) 515 assertPermission(permissionName, PERMISSION_DENIED, context) 516 } 517 assertPermissionnull518 private fun assertPermission( 519 permissionName: String, 520 permissionState: Int, 521 context: Context, 522 ) { 523 assertThat(context.packageManager.checkPermission(permissionName, TEST_PACKAGE_NAME)) 524 .isEqualTo(permissionState) 525 } 526 527 companion object { 528 private const val TEST_PACKAGE_NAME = "android.permission.cts.appthatrequestpermission" 529 private const val TEST_APK = 530 "/data/local/tmp/cts-permission/CtsAppThatRequestsDevicePermissions.apk" 531 532 private const val CUSTOM_SIGNATURE_PERMISSION = 533 "android.permission.cts.CUSTOM_SIGNATURE_PERMISSION" 534 535 private const val PERMISSION_SELF_REVOKE_INTENT = 536 "android.permission.cts.appthatrequestpermission.REVOKE_SELF_PERMISSION" 537 private const val PERMISSION_SELF_REVOKE_RECEIVER = 538 "android.permission.cts.appthatrequestpermission.RevokeSelfPermissionReceiver" 539 540 private const val DEVICE_AWARE_PERMISSION = Manifest.permission.RECORD_AUDIO 541 private const val NON_DEVICE_AWARE_PERMISSION = Manifest.permission.READ_CONTACTS 542 } 543 } 544