1 /* <lambda>null2 * 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.permissionmultidevice.cts 18 19 import android.Manifest 20 import android.app.Instrumentation 21 import android.companion.virtual.VirtualDeviceManager 22 import android.companion.virtual.VirtualDeviceParams 23 import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM 24 import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT 25 import android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA 26 import android.content.ComponentName 27 import android.content.Context 28 import android.content.Intent 29 import android.content.Intent.EXTRA_RESULT_RECEIVER 30 import android.content.pm.PackageManager 31 import android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS 32 import android.hardware.display.VirtualDisplay 33 import android.os.Build 34 import android.os.Bundle 35 import android.os.RemoteCallback 36 import android.permission.PermissionManager 37 import android.permission.flags.Flags 38 import android.permissionmultidevice.cts.PackageManagementUtils.installPackage 39 import android.permissionmultidevice.cts.PackageManagementUtils.uninstallPackage 40 import android.permissionmultidevice.cts.UiAutomatorUtils.click 41 import android.permissionmultidevice.cts.UiAutomatorUtils.findTextForView 42 import android.permissionmultidevice.cts.UiAutomatorUtils.waitFindObject 43 import android.platform.test.annotations.AppModeFull 44 import android.platform.test.annotations.RequiresFlagsEnabled 45 import android.provider.Settings 46 import android.view.Display 47 import android.virtualdevice.cts.common.VirtualDeviceRule 48 import androidx.test.ext.junit.runners.AndroidJUnit4 49 import androidx.test.filters.SdkSuppress 50 import androidx.test.platform.app.InstrumentationRegistry 51 import androidx.test.uiautomator.By 52 import com.android.compatibility.common.util.SystemUtil 53 import com.google.common.truth.Truth.assertThat 54 import java.util.concurrent.CompletableFuture 55 import java.util.concurrent.TimeUnit 56 import org.junit.After 57 import org.junit.Assert 58 import org.junit.Assume.assumeFalse 59 import org.junit.Before 60 import org.junit.Rule 61 import org.junit.Test 62 import org.junit.runner.RunWith 63 64 @RunWith(AndroidJUnit4::class) 65 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") 66 @AppModeFull(reason = "VirtualDeviceManager cannot be accessed by instant apps") 67 open class DeviceAwarePermissionGrantTest { 68 private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() 69 private val defaultDeviceContext = instrumentation.targetContext 70 private lateinit var defaultDeviceName: String 71 private lateinit var virtualDeviceManager: VirtualDeviceManager 72 private lateinit var virtualDevice: VirtualDeviceManager.VirtualDevice 73 private lateinit var virtualDisplay: VirtualDisplay 74 private lateinit var virtualDeviceName: String 75 private val permissionManager = 76 defaultDeviceContext.getSystemService(PermissionManager::class.java)!! 77 78 @get:Rule 79 var virtualDeviceRule: VirtualDeviceRule = 80 VirtualDeviceRule.withAdditionalPermissions(Manifest.permission.GRANT_RUNTIME_PERMISSIONS) 81 82 @Before 83 fun setup() { 84 assumeFalse(PermissionUtils.isAutomotive(defaultDeviceContext)) 85 assumeFalse(PermissionUtils.isTv(defaultDeviceContext)) 86 assumeFalse(PermissionUtils.isWatch(defaultDeviceContext)) 87 88 installPackage(APP_APK_PATH_STREAMING) 89 virtualDeviceManager = 90 defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)!! 91 92 defaultDeviceName = 93 Settings.Global.getString( 94 defaultDeviceContext.contentResolver, 95 Settings.Global.DEVICE_NAME, 96 ) 97 } 98 99 @After 100 fun cleanup() { 101 uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false) 102 Thread.sleep(2000) 103 } 104 105 private fun createVirtualDevice(cameraPolicy: Int = DEVICE_POLICY_DEFAULT) { 106 virtualDevice = 107 virtualDeviceRule.createManagedVirtualDevice( 108 VirtualDeviceParams.Builder() 109 .setDevicePolicy(POLICY_TYPE_CAMERA, cameraPolicy) 110 .build() 111 ) 112 virtualDisplay = 113 virtualDeviceRule.createManagedVirtualDisplay( 114 virtualDevice, 115 VirtualDeviceRule.createTrustedVirtualDisplayConfigBuilder(), 116 )!! 117 virtualDeviceName = 118 virtualDeviceManager.getVirtualDevice(virtualDevice.deviceId)!!.displayName.toString() 119 } 120 121 @Test 122 fun deviceAwarePermission_onHost_requestHostPermission() { 123 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 124 testMultiDevicePermissionGrant( 125 permission = Manifest.permission.CAMERA, 126 initialDefaultDevicePermission = false, 127 initialVirtualDevicePermission = false, 128 requestingFromDevice = DEVICE_ID_DEFAULT, 129 requestingForDevice = DEVICE_ID_DEFAULT, 130 dialogDeviceName = DEVICE_ID_INVALID, 131 expectPermissionGrantedOnDefaultDevice = true, 132 expectPermissionGrantedOnVirtualDevice = false, 133 ) 134 } 135 136 @Test 137 fun deviceAwarePermission_onHost_withRemotePermission_requestHostPermission() { 138 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 139 testMultiDevicePermissionGrant( 140 permission = Manifest.permission.CAMERA, 141 initialDefaultDevicePermission = false, 142 initialVirtualDevicePermission = true, 143 requestingFromDevice = DEVICE_ID_DEFAULT, 144 requestingForDevice = DEVICE_ID_DEFAULT, 145 dialogDeviceName = DEVICE_ID_INVALID, 146 expectPermissionGrantedOnDefaultDevice = true, 147 expectPermissionGrantedOnVirtualDevice = true, 148 ) 149 } 150 151 @Test 152 fun deviceAwarePermission_onHost_requestPermissionWithoutDeviceId() { 153 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 154 testMultiDevicePermissionGrant( 155 permission = Manifest.permission.CAMERA, 156 initialDefaultDevicePermission = false, 157 initialVirtualDevicePermission = false, 158 requestingFromDevice = DEVICE_ID_DEFAULT, 159 requestingForDevice = DEVICE_ID_INVALID, 160 dialogDeviceName = DEVICE_ID_INVALID, 161 expectPermissionGrantedOnDefaultDevice = true, 162 expectPermissionGrantedOnVirtualDevice = false, 163 ) 164 } 165 166 @Test 167 fun deviceAwarePermission_onHost_withRemotePermission_requestPermissionWithoutDeviceId() { 168 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 169 testMultiDevicePermissionGrant( 170 permission = Manifest.permission.CAMERA, 171 initialDefaultDevicePermission = false, 172 initialVirtualDevicePermission = true, 173 requestingFromDevice = DEVICE_ID_DEFAULT, 174 requestingForDevice = DEVICE_ID_INVALID, 175 dialogDeviceName = DEVICE_ID_INVALID, 176 expectPermissionGrantedOnDefaultDevice = true, 177 expectPermissionGrantedOnVirtualDevice = true, 178 ) 179 } 180 181 @Test 182 fun deviceAwarePermission_onHost_requestRemotePermission() { 183 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 184 testMultiDevicePermissionGrant( 185 permission = Manifest.permission.CAMERA, 186 initialDefaultDevicePermission = false, 187 initialVirtualDevicePermission = false, 188 requestingFromDevice = DEVICE_ID_DEFAULT, 189 requestingForDevice = virtualDevice.deviceId, 190 dialogDeviceName = virtualDevice.deviceId, 191 expectPermissionGrantedOnDefaultDevice = false, 192 expectPermissionGrantedOnVirtualDevice = true, 193 ) 194 } 195 196 @Test 197 fun deviceAwarePermission_onHost_withHostPermission_requestRemotePermission() { 198 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 199 testMultiDevicePermissionGrant( 200 permission = Manifest.permission.CAMERA, 201 initialDefaultDevicePermission = true, 202 initialVirtualDevicePermission = false, 203 requestingFromDevice = DEVICE_ID_DEFAULT, 204 requestingForDevice = virtualDevice.deviceId, 205 dialogDeviceName = virtualDevice.deviceId, 206 expectPermissionGrantedOnDefaultDevice = true, 207 expectPermissionGrantedOnVirtualDevice = true, 208 ) 209 } 210 211 @Test 212 fun deviceAwarePermission_onRemote_requestRemotePermission() { 213 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 214 testMultiDevicePermissionGrant( 215 permission = Manifest.permission.CAMERA, 216 initialDefaultDevicePermission = false, 217 initialVirtualDevicePermission = false, 218 requestingFromDevice = virtualDevice.deviceId, 219 requestingForDevice = virtualDevice.deviceId, 220 dialogDeviceName = virtualDevice.deviceId, 221 expectPermissionGrantedOnDefaultDevice = false, 222 expectPermissionGrantedOnVirtualDevice = true, 223 ) 224 } 225 226 @Test 227 fun deviceAwarePermission_onRemote_withHostPermission_requestRemotePermission() { 228 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 229 testMultiDevicePermissionGrant( 230 permission = Manifest.permission.CAMERA, 231 initialDefaultDevicePermission = true, 232 initialVirtualDevicePermission = false, 233 requestingFromDevice = virtualDevice.deviceId, 234 requestingForDevice = virtualDevice.deviceId, 235 dialogDeviceName = virtualDevice.deviceId, 236 expectPermissionGrantedOnDefaultDevice = true, 237 expectPermissionGrantedOnVirtualDevice = true, 238 ) 239 } 240 241 @Test 242 fun deviceAwarePermission_onRemote_requestPermissionWithoutDeviceId() { 243 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 244 testMultiDevicePermissionGrant( 245 permission = Manifest.permission.CAMERA, 246 initialDefaultDevicePermission = false, 247 initialVirtualDevicePermission = false, 248 requestingFromDevice = virtualDevice.deviceId, 249 requestingForDevice = DEVICE_ID_INVALID, 250 dialogDeviceName = virtualDevice.deviceId, 251 expectPermissionGrantedOnDefaultDevice = false, 252 expectPermissionGrantedOnVirtualDevice = true, 253 ) 254 } 255 256 @Test 257 fun deviceAwarePermission_onRemote_withHostPermission_requestPermissionWithoutDeviceId() { 258 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 259 testMultiDevicePermissionGrant( 260 permission = Manifest.permission.CAMERA, 261 initialDefaultDevicePermission = true, 262 initialVirtualDevicePermission = false, 263 requestingFromDevice = virtualDevice.deviceId, 264 requestingForDevice = DEVICE_ID_INVALID, 265 dialogDeviceName = virtualDevice.deviceId, 266 expectPermissionGrantedOnDefaultDevice = true, 267 expectPermissionGrantedOnVirtualDevice = true, 268 ) 269 } 270 271 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 272 @Test 273 fun deviceAwarePermission_onRemote_requestHostPermission() { 274 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 275 testMultiDevicePermissionGrant( 276 permission = Manifest.permission.CAMERA, 277 initialDefaultDevicePermission = false, 278 initialVirtualDevicePermission = false, 279 requestingFromDevice = virtualDevice.deviceId, 280 requestingForDevice = DEVICE_ID_DEFAULT, 281 dialogDeviceName = DEVICE_ID_DEFAULT, 282 expectPermissionGrantedOnDefaultDevice = true, 283 expectPermissionGrantedOnVirtualDevice = false, 284 ) 285 } 286 287 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 288 @Test 289 fun deviceAwarePermission_onRemote_withRemotePermission_requestHostPermission() { 290 createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) 291 testMultiDevicePermissionGrant( 292 permission = Manifest.permission.CAMERA, 293 initialDefaultDevicePermission = false, 294 initialVirtualDevicePermission = true, 295 requestingFromDevice = virtualDevice.deviceId, 296 requestingForDevice = DEVICE_ID_DEFAULT, 297 dialogDeviceName = DEVICE_ID_DEFAULT, 298 expectPermissionGrantedOnDefaultDevice = true, 299 expectPermissionGrantedOnVirtualDevice = true, 300 ) 301 } 302 303 @Test 304 fun deviceAwarePermissionWithoutCapability_onHost_requestHostPermission() { 305 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 306 testMultiDevicePermissionGrant( 307 permission = Manifest.permission.CAMERA, 308 initialDefaultDevicePermission = false, 309 initialVirtualDevicePermission = false, 310 requestingFromDevice = DEVICE_ID_DEFAULT, 311 requestingForDevice = DEVICE_ID_DEFAULT, 312 dialogDeviceName = DEVICE_ID_INVALID, 313 expectPermissionGrantedOnDefaultDevice = true, 314 expectPermissionGrantedOnVirtualDevice = true, 315 ) 316 } 317 318 @Test 319 fun deviceAwarePermissionWithoutCapability_onHost_requestPermissionWithoutDeviceId() { 320 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 321 testMultiDevicePermissionGrant( 322 permission = Manifest.permission.CAMERA, 323 initialDefaultDevicePermission = false, 324 initialVirtualDevicePermission = false, 325 requestingFromDevice = DEVICE_ID_DEFAULT, 326 requestingForDevice = DEVICE_ID_INVALID, 327 dialogDeviceName = DEVICE_ID_INVALID, 328 expectPermissionGrantedOnDefaultDevice = true, 329 expectPermissionGrantedOnVirtualDevice = true, 330 ) 331 } 332 333 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 334 @Test 335 fun deviceAwarePermissionWithoutCapability_onHost_requestRemotePermission() { 336 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 337 testMultiDevicePermissionGrant( 338 permission = Manifest.permission.CAMERA, 339 initialDefaultDevicePermission = false, 340 initialVirtualDevicePermission = false, 341 requestingFromDevice = DEVICE_ID_DEFAULT, 342 requestingForDevice = virtualDevice.deviceId, 343 dialogDeviceName = DEVICE_ID_INVALID, 344 expectPermissionGrantedOnDefaultDevice = true, 345 expectPermissionGrantedOnVirtualDevice = true, 346 ) 347 } 348 349 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 350 @Test 351 fun deviceAwarePermissionWithoutCapability_onRemote_requestRemotePermission() { 352 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 353 testMultiDevicePermissionGrant( 354 permission = Manifest.permission.CAMERA, 355 initialDefaultDevicePermission = false, 356 initialVirtualDevicePermission = false, 357 requestingFromDevice = virtualDevice.deviceId, 358 requestingForDevice = virtualDevice.deviceId, 359 dialogDeviceName = DEVICE_ID_DEFAULT, 360 expectPermissionGrantedOnDefaultDevice = true, 361 expectPermissionGrantedOnVirtualDevice = true, 362 ) 363 } 364 365 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 366 @Test 367 fun deviceAwarePermissionWithoutCapability_onRemote_requestPermissionWithoutDeviceId() { 368 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 369 testMultiDevicePermissionGrant( 370 permission = Manifest.permission.CAMERA, 371 initialDefaultDevicePermission = false, 372 initialVirtualDevicePermission = false, 373 requestingFromDevice = virtualDevice.deviceId, 374 requestingForDevice = DEVICE_ID_INVALID, 375 dialogDeviceName = DEVICE_ID_DEFAULT, 376 expectPermissionGrantedOnDefaultDevice = true, 377 expectPermissionGrantedOnVirtualDevice = true, 378 ) 379 } 380 381 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 382 @Test 383 fun deviceAwarePermissionWithoutCapability_onRemote_requestHostPermission() { 384 createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) 385 testMultiDevicePermissionGrant( 386 permission = Manifest.permission.CAMERA, 387 initialDefaultDevicePermission = false, 388 initialVirtualDevicePermission = false, 389 requestingFromDevice = virtualDevice.deviceId, 390 requestingForDevice = DEVICE_ID_DEFAULT, 391 dialogDeviceName = DEVICE_ID_DEFAULT, 392 expectPermissionGrantedOnDefaultDevice = true, 393 expectPermissionGrantedOnVirtualDevice = true, 394 ) 395 } 396 397 @Test 398 fun nonDeviceAwarePermission_onHost_requestHostPermission() { 399 createVirtualDevice() 400 testMultiDevicePermissionGrant( 401 permission = Manifest.permission.READ_CONTACTS, 402 initialDefaultDevicePermission = false, 403 initialVirtualDevicePermission = false, 404 requestingFromDevice = DEVICE_ID_DEFAULT, 405 requestingForDevice = DEVICE_ID_DEFAULT, 406 dialogDeviceName = DEVICE_ID_INVALID, 407 expectPermissionGrantedOnDefaultDevice = true, 408 expectPermissionGrantedOnVirtualDevice = true, 409 ) 410 } 411 412 @Test 413 fun nonDeviceAwarePermission_onHost_requestPermissionWithoutDeviceId() { 414 createVirtualDevice() 415 testMultiDevicePermissionGrant( 416 permission = Manifest.permission.READ_CONTACTS, 417 initialDefaultDevicePermission = false, 418 initialVirtualDevicePermission = false, 419 requestingFromDevice = DEVICE_ID_DEFAULT, 420 requestingForDevice = DEVICE_ID_INVALID, 421 dialogDeviceName = DEVICE_ID_INVALID, 422 expectPermissionGrantedOnDefaultDevice = true, 423 expectPermissionGrantedOnVirtualDevice = true, 424 ) 425 } 426 427 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 428 @Test 429 fun nonDeviceAwarePermission_onHost_requestRemotePermission() { 430 createVirtualDevice() 431 testMultiDevicePermissionGrant( 432 permission = Manifest.permission.READ_CONTACTS, 433 initialDefaultDevicePermission = false, 434 initialVirtualDevicePermission = false, 435 requestingFromDevice = DEVICE_ID_DEFAULT, 436 requestingForDevice = virtualDevice.deviceId, 437 dialogDeviceName = DEVICE_ID_INVALID, 438 expectPermissionGrantedOnDefaultDevice = true, 439 expectPermissionGrantedOnVirtualDevice = true, 440 ) 441 } 442 443 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 444 @Test 445 fun nonDeviceAwarePermission_onRemote_requestRemotePermission() { 446 createVirtualDevice() 447 testMultiDevicePermissionGrant( 448 permission = Manifest.permission.READ_CONTACTS, 449 initialDefaultDevicePermission = false, 450 initialVirtualDevicePermission = false, 451 requestingFromDevice = virtualDevice.deviceId, 452 requestingForDevice = virtualDevice.deviceId, 453 dialogDeviceName = DEVICE_ID_DEFAULT, 454 expectPermissionGrantedOnDefaultDevice = true, 455 expectPermissionGrantedOnVirtualDevice = true, 456 ) 457 } 458 459 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 460 @Test 461 fun nonDeviceAwarePermission_onRemote_requestPermissionWithoutDeviceId() { 462 createVirtualDevice() 463 testMultiDevicePermissionGrant( 464 permission = Manifest.permission.READ_CONTACTS, 465 initialDefaultDevicePermission = false, 466 initialVirtualDevicePermission = false, 467 requestingFromDevice = virtualDevice.deviceId, 468 requestingForDevice = DEVICE_ID_INVALID, 469 dialogDeviceName = DEVICE_ID_DEFAULT, 470 expectPermissionGrantedOnDefaultDevice = true, 471 expectPermissionGrantedOnVirtualDevice = true, 472 ) 473 } 474 475 @RequiresFlagsEnabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) 476 @Test 477 fun nonDeviceAwarePermission_onRemote_requestHostPermission() { 478 createVirtualDevice() 479 testMultiDevicePermissionGrant( 480 permission = Manifest.permission.READ_CONTACTS, 481 initialDefaultDevicePermission = false, 482 initialVirtualDevicePermission = false, 483 requestingFromDevice = virtualDevice.deviceId, 484 requestingForDevice = DEVICE_ID_DEFAULT, 485 dialogDeviceName = DEVICE_ID_DEFAULT, 486 expectPermissionGrantedOnDefaultDevice = true, 487 expectPermissionGrantedOnVirtualDevice = true, 488 ) 489 } 490 491 private fun testMultiDevicePermissionGrant( 492 permission: String, 493 initialDefaultDevicePermission: Boolean, 494 initialVirtualDevicePermission: Boolean, 495 requestingFromDevice: Int, 496 requestingForDevice: Int, 497 dialogDeviceName: Int, 498 expectPermissionGrantedOnDefaultDevice: Boolean, 499 expectPermissionGrantedOnVirtualDevice: Boolean, 500 ) { 501 if (initialDefaultDevicePermission) { 502 instrumentation.uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME, permission) 503 } 504 if (initialVirtualDevicePermission) { 505 grantRuntimePermissionOnVirtualDevice(permission) 506 } 507 assertAppHasPermissionForDevice( 508 DEVICE_ID_DEFAULT, 509 permission, 510 initialDefaultDevicePermission, 511 ) 512 assertAppHasPermissionForDevice( 513 virtualDevice.deviceId, 514 permission, 515 initialVirtualDevicePermission, 516 ) 517 518 val displayId = 519 if (requestingFromDevice == DEVICE_ID_DEFAULT) { 520 Display.DEFAULT_DISPLAY 521 } else { 522 virtualDisplay.display.displayId 523 } 524 525 val future = requestPermissionOnDevice(displayId, requestingForDevice, permission) 526 527 if (dialogDeviceName != DEVICE_ID_INVALID) { 528 val expectedDeviceNameInDialog = 529 if (dialogDeviceName == DEVICE_ID_DEFAULT) { 530 defaultDeviceName 531 } else { 532 virtualDeviceName 533 } 534 assertPermissionMessageContainsDeviceName(displayId, expectedDeviceNameInDialog) 535 } else { 536 assertPermissionMessageDoesNotContainDeviceName(displayId) 537 } 538 539 // Click the allow button in the dialog to grant permission 540 val allowButton = 541 if (permission == Manifest.permission.CAMERA) ALLOW_BUTTON_FOREGROUND else ALLOW_BUTTON 542 SystemUtil.eventually { click(By.displayId(displayId).res(allowButton)) } 543 544 // Validate permission grant result returned from callback 545 val grantPermissionResult = future.get(TIMEOUT, TimeUnit.MILLISECONDS) 546 assertThat( 547 grantPermissionResult.getStringArray( 548 TestConstants.PERMISSION_RESULT_KEY_PERMISSIONS 549 ) 550 ) 551 .isEqualTo(arrayOf(permission)) 552 assertThat( 553 grantPermissionResult.getIntArray(TestConstants.PERMISSION_RESULT_KEY_GRANT_RESULTS) 554 ) 555 .isEqualTo(arrayOf(PackageManager.PERMISSION_GRANTED).toIntArray()) 556 557 val expectedPermissionResultDeviceId = 558 if (requestingForDevice == DEVICE_ID_INVALID) { 559 requestingFromDevice 560 } else { 561 requestingForDevice 562 } 563 assertThat(grantPermissionResult.getInt(TestConstants.PERMISSION_RESULT_KEY_DEVICE_ID)) 564 .isEqualTo(expectedPermissionResultDeviceId) 565 566 // Validate whether permission is granted as expected 567 assertAppHasPermissionForDevice( 568 DEVICE_ID_DEFAULT, 569 permission, 570 expectPermissionGrantedOnDefaultDevice, 571 ) 572 assertAppHasPermissionForDevice( 573 virtualDevice.deviceId, 574 permission, 575 expectPermissionGrantedOnVirtualDevice, 576 ) 577 } 578 579 private fun requestPermissionOnDevice( 580 displayId: Int, 581 targetDeviceId: Int, 582 permission: String, 583 ): CompletableFuture<Bundle> { 584 val future = CompletableFuture<Bundle>() 585 val callback = RemoteCallback { result: Bundle? -> future.complete(result) } 586 val permissions = mutableListOf(permission).toTypedArray() 587 val intent = 588 Intent() 589 .setComponent( 590 ComponentName(APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.RequestPermissionActivity") 591 ) 592 .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, targetDeviceId) 593 .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, permissions) 594 .putExtra(EXTRA_RESULT_RECEIVER, callback) 595 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) 596 597 virtualDeviceRule.sendIntentToDisplay(intent, displayId) 598 virtualDeviceRule.waitAndAssertActivityResumed(getPermissionDialogComponentName()) 599 600 return future 601 } 602 603 private fun assertPermissionMessageContainsDeviceName(displayId: Int, deviceName: String) { 604 waitFindObject(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) 605 val text = findTextForView(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) 606 assertThat(text).contains(deviceName) 607 } 608 609 private fun assertPermissionMessageDoesNotContainDeviceName(displayId: Int) { 610 waitFindObject(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) 611 val text = findTextForView(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) 612 assertThat(text).doesNotContain(virtualDeviceName) 613 assertThat(text).doesNotContain(defaultDeviceName) 614 } 615 616 private fun assertAppHasPermissionForDevice( 617 deviceId: Int, 618 permission: String, 619 expectPermissionGranted: Boolean, 620 ) { 621 val checkPermissionResult = 622 defaultDeviceContext 623 .createDeviceContext(deviceId) 624 .packageManager 625 .checkPermission(permission, APP_PACKAGE_NAME) 626 627 if (expectPermissionGranted) { 628 Assert.assertEquals(PackageManager.PERMISSION_GRANTED, checkPermissionResult) 629 } else { 630 Assert.assertEquals(PackageManager.PERMISSION_DENIED, checkPermissionResult) 631 } 632 } 633 634 private fun getPermissionDialogComponentName(): ComponentName { 635 val intent = Intent(ACTION_REQUEST_PERMISSIONS) 636 intent.setPackage(defaultDeviceContext.packageManager.getPermissionControllerPackageName()) 637 return intent.resolveActivity(defaultDeviceContext.packageManager) 638 } 639 640 private fun grantRuntimePermissionOnVirtualDevice(permission: String) { 641 permissionManager.grantRuntimePermission( 642 APP_PACKAGE_NAME, 643 permission, 644 virtualDevice.persistentDeviceId!!, 645 ) 646 } 647 648 companion object { 649 const val APK_DIRECTORY = "/data/local/tmp/cts-permissionmultidevice" 650 const val APP_APK_PATH_STREAMING = "${APK_DIRECTORY}/CtsAccessRemoteDeviceCamera.apk" 651 const val APP_PACKAGE_NAME = "android.permissionmultidevice.cts.accessremotedevicecamera" 652 const val PERMISSION_MESSAGE_ID = "com.android.permissioncontroller:id/permission_message" 653 const val ALLOW_BUTTON_FOREGROUND = 654 "com.android.permissioncontroller:id/permission_allow_foreground_only_button" 655 const val ALLOW_BUTTON = "com.android.permissioncontroller:id/permission_allow_button" 656 const val DEVICE_ID_DEFAULT = Context.DEVICE_ID_DEFAULT 657 const val DEVICE_ID_INVALID = Context.DEVICE_ID_INVALID 658 const val PERSISTENT_DEVICE_ID_DEFAULT = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT 659 const val TIMEOUT = 5000L 660 } 661 } 662