diff options
13 files changed, 485 insertions, 220 deletions
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java index 41233a23e..00ec67569 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java +++ b/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java @@ -18,7 +18,6 @@ package com.android.role.controller.util; import android.content.Context; import android.os.Build; -import android.os.Flags; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; @@ -91,7 +90,7 @@ public final class UserUtils { * allowed from Android V+ only, so this method will return false on Sdk levels below that. */ public static boolean isPrivateProfile(@NonNull UserHandle user, @NonNull Context context) { - if (!SdkLevel.isAtLeastV() || !Flags.allowPrivateProfile()) { + if (!SdkLevel.isAtLeastV()) { return false; } Context userContext = getUserContext(context, user); diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java index 7573b571d..0dd07ffd0 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java @@ -311,10 +311,8 @@ public class GrantPermissionsActivity extends SettingsActivity PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, ContextCompat.DEVICE_ID_DEFAULT); - if (mTargetDeviceId != ContextCompat.DEVICE_ID_DEFAULT) { - mPackageManager = ContextCompat.createDeviceContext(this, mTargetDeviceId) - .getPackageManager(); - } + mPackageManager = ContextCompat.createDeviceContext(this, mTargetDeviceId) + .getPackageManager(); // When the permission grant dialog is streamed to a virtual device, and when requested // permissions include both device-aware permissions and non-device aware permissions, @@ -337,21 +335,6 @@ public class GrantPermissionsActivity extends SettingsActivity new Intent(this, PermissionDialogStreamingBlockedActivity.class)); return; } - } else if (mTargetDeviceId != ContextCompat.DEVICE_ID_DEFAULT) { - // On the default device, when requested permissions are for a remote device, - // filter out non-device aware permissions. - for (int i = mRequestedPermissions.size() - 1; i >= 0; i--) { - if (!MultiDeviceUtils.isPermissionDeviceAware( - getApplicationContext(), - mTargetDeviceId, - mRequestedPermissions.get(i))) { - Log.e( - LOG_TAG, - "non-device aware permission is requested for a remote device: " - + mRequestedPermissions.get(i)); - mRequestedPermissions.remove(i); - } - } } } @@ -740,7 +723,7 @@ public class GrantPermissionsActivity extends SettingsActivity int dialogDisplayDeviceId = ContextCompat.getDeviceId(this); boolean isMessageDeviceAware = dialogDisplayDeviceId != ContextCompat.DEVICE_ID_DEFAULT - || dialogDisplayDeviceId != mTargetDeviceId; + || dialogDisplayDeviceId != info.getDeviceId(); int messageId = getMessageId(info.getGroupName(), info.getPrompt(), isMessageDeviceAware); CharSequence message = @@ -1132,17 +1115,9 @@ public class GrantPermissionsActivity extends SettingsActivity if ((mDelegated || (mViewModel != null && mViewModel.shouldReturnPermissionState())) && mTargetPackage != null) { - PackageManager defaultDevicePackageManager = SdkLevel.isAtLeastV() - && mTargetDeviceId != ContextCompat.DEVICE_ID_DEFAULT - ? createDeviceContext(ContextCompat.DEVICE_ID_DEFAULT).getPackageManager() - : mPackageManager; - PackageManager targetDevicePackageManager = mPackageManager; for (int i = 0; i < resultPermissions.length; i++) { String permission = resultPermissions[i]; - PackageManager pm = MultiDeviceUtils.isPermissionDeviceAware( - getApplicationContext(), mTargetDeviceId, permission) - ? targetDevicePackageManager : defaultDevicePackageManager; - grantResults[i] = pm.checkPermission(resultPermissions[i], mTargetPackage); + grantResults[i] = mPackageManager.checkPermission(permission, mTargetPackage); } } else { grantResults = new int[0]; diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java index 4d778befb..10e8dd0e1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java +++ b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java @@ -139,7 +139,7 @@ public class UserUtils { */ private static boolean isPrivateProfile(@NonNull UserHandle userHandle, @NonNull Context context) { - if (!SdkLevel.isAtLeastV() || !android.os.Flags.allowPrivateProfile()) { + if (!SdkLevel.isAtLeastV()) { return false; } Context userContext = context.createContextAsUser(userHandle, /* flags= */ 0); diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt index 8d7d96f99..307ef9cf6 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt +++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt @@ -331,9 +331,7 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() { get() = SafetyCenterIds.entryIdFromString(id) private fun isPrivateProfileSupported(): Boolean { - return SdkLevel.isAtLeastV() && - com.android.permission.flags.Flags.privateProfileSupported() && - android.os.Flags.allowPrivateProfile() + return SdkLevel.isAtLeastV() && com.android.permission.flags.Flags.privateProfileSupported() } companion object { diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetySubpageEntryPreference.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetySubpageEntryPreference.kt index b89abde13..551f676f1 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetySubpageEntryPreference.kt +++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetySubpageEntryPreference.kt @@ -49,7 +49,7 @@ class SafetySubpageEntryPreference( context: Context, private val launchTaskId: Int?, private val entry: SafetyCenterEntry, - private val viewModel: SafetyCenterViewModel + private val viewModel: SafetyCenterViewModel, ) : TwoTargetPreference(context), ComparablePreference { init { @@ -108,9 +108,7 @@ class SafetySubpageEntryPreference( } private fun isPrivateProfileSupported(): Boolean { - return SdkLevel.isAtLeastV() && - com.android.permission.flags.Flags.privateProfileSupported() && - android.os.Flags.allowPrivateProfile() + return SdkLevel.isAtLeastV() && com.android.permission.flags.Flags.privateProfileSupported() } override fun onBindViewHolder(holder: PreferenceViewHolder) { @@ -125,7 +123,7 @@ class SafetySubpageEntryPreference( PendingIntentSender.send(iconAction.pendingIntent, launchTaskId) viewModel.interactionLogger.recordForEntry( Action.ENTRY_ICON_ACTION_CLICKED, - entry + entry, ) } catch (ex: Exception) { Log.e(TAG, "Failed to execute icon action intent for $entry", ex) diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java index 87d8744a8..0da8286f6 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java +++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java @@ -98,8 +98,7 @@ public class StaticSafetyEntryPreference extends Preference implements Comparabl private Boolean isPrivateProfileSupported() { return SdkLevel.isAtLeastV() - && com.android.permission.flags.Flags.privateProfileSupported() - && android.os.Flags.allowPrivateProfile(); + && com.android.permission.flags.Flags.privateProfileSupported(); } @Override diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt index 23074a06f..57fdbca03 100644 --- a/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt @@ -205,7 +205,7 @@ fun Chip( color = secondaryTextColor, overflow = TextOverflow.Ellipsis, maxLines = secondaryLabelMaxLines ?: 1, - style = MaterialTheme.typography.caption2, + style = MaterialTheme.typography.caption2.copy(hyphens = Hyphens.Auto), ) } } diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt index 5f1c8dd2c..320e58964 100644 --- a/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt @@ -123,6 +123,7 @@ internal fun WearPermissionButtonInternal( text = secondaryLabel, modifier = Modifier.fillMaxWidth(), maxLines = secondaryLabelMaxLines ?: LocalTextConfiguration.current.maxLines, + style = LocalTextStyle.current.copy(hyphens = Hyphens.Auto), ) } } diff --git a/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/AndroidManifest.xml b/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/AndroidManifest.xml index 211e415bd..c31bfdaf3 100644 --- a/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/AndroidManifest.xml @@ -21,6 +21,7 @@ package="android.permissionmultidevice.cts.accessremotedevicecamera"> <uses-permission android:name="android.permission.CAMERA" /> + <uses-permission android:name="android.permission.READ_CONTACTS" /> <application> <activity android:name=".RequestPermissionActivity" android:exported="true" /> diff --git a/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/src/android/permissionmultidevice/cts/accessremotedevicecamera/RequestPermissionActivity.kt b/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/src/android/permissionmultidevice/cts/accessremotedevicecamera/RequestPermissionActivity.kt index fa1d1f83c..33daa1253 100644 --- a/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/src/android/permissionmultidevice/cts/accessremotedevicecamera/RequestPermissionActivity.kt +++ b/tests/cts/permissionmultidevice/AccessRemoteDeviceCameraApp/src/android/permissionmultidevice/cts/accessremotedevicecamera/RequestPermissionActivity.kt @@ -16,7 +16,6 @@ package android.permissionmultidevice.cts.accessremotedevicecamera -import android.Manifest import android.app.Activity import android.content.Context import android.content.Intent @@ -33,17 +32,24 @@ class RequestPermissionActivity : Activity() { val deviceId = intent.getIntExtra( PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, - Context.DEVICE_ID_DEFAULT + Context.DEVICE_ID_INVALID, ) - requestPermissions(DEVICE_AWARE_PERMISSIONS, 1001, deviceId) + val permissions = + intent.getStringArrayExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES)!! + + if (deviceId != Context.DEVICE_ID_INVALID) { + requestPermissions(permissions, 1001, deviceId) + } else { + requestPermissions(permissions, 1001) + } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray, - deviceId: Int + deviceId: Int, ) { val resultReceiver = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER, RemoteCallback::class.java) @@ -57,8 +63,4 @@ class RequestPermissionActivity : Activity() { resultReceiver?.sendResult(result) finish() } - - companion object { - private val DEVICE_AWARE_PERMISSIONS = arrayOf(Manifest.permission.CAMERA) - } } diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index 907917f6f..76c86df76 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -108,7 +108,7 @@ class AppPermissionsTest { @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionGrantTest() { @@ -123,7 +123,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = true, askChecked = false, - denyChecked = false + denyChecked = false, ) UiAutomatorUtils2.getUiDevice().pressBack() @@ -131,14 +131,14 @@ class AppPermissionsTest { mapOf( "Allowed" to listOf(externalDeviceCameraText), "Ask every time" to emptyList(), - "Not allowed" to listOf("Camera") + "Not allowed" to listOf("Camera", "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) } @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionChangeToAskTest() { @@ -153,7 +153,7 @@ class AppPermissionsTest { @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionChangeToDenyTest() { @@ -168,7 +168,7 @@ class AppPermissionsTest { @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionChangeToAllowTest() { @@ -180,7 +180,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = false, askChecked = true, - denyChecked = false + denyChecked = false, ) clickAllowForegroundButton() @@ -189,7 +189,7 @@ class AppPermissionsTest { @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionNotDisplayedInitiallyTest() { @@ -200,14 +200,14 @@ class AppPermissionsTest { mapOf( "Allowed" to emptyList(), "Ask every time" to emptyList(), - "Not allowed" to listOf("Camera") + "Not allowed" to listOf("Camera", "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) } @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, ) @Test fun externalDevicePermissionStickyOnGrantTest() { @@ -219,7 +219,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = true, askChecked = false, - denyChecked = false + denyChecked = false, ) clickDenyButton() @@ -232,7 +232,7 @@ class AppPermissionsTest { mapOf( "Allowed" to emptyList(), "Ask every time" to emptyList(), - "Not allowed" to listOf("Camera", externalDeviceCameraText) + "Not allowed" to listOf("Camera", externalDeviceCameraText, "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) } @@ -243,7 +243,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = false, askChecked = true, - denyChecked = false + denyChecked = false, ) UiAutomatorUtils2.getUiDevice().pressBack() @@ -252,7 +252,7 @@ class AppPermissionsTest { mapOf( "Allowed" to emptyList(), "Ask every time" to listOf(externalDeviceCameraText), - "Not allowed" to listOf("Camera") + "Not allowed" to listOf("Camera", "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) @@ -270,7 +270,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = false, askChecked = false, - denyChecked = true + denyChecked = true, ) UiAutomatorUtils2.getUiDevice().pressBack() @@ -279,7 +279,7 @@ class AppPermissionsTest { mapOf( "Allowed" to emptyList(), "Ask every time" to emptyList(), - "Not allowed" to listOf("Camera", externalDeviceCameraText) + "Not allowed" to listOf("Camera", externalDeviceCameraText, "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) @@ -297,7 +297,7 @@ class AppPermissionsTest { verifyRadioButtonStates( allowForegroundChecked = true, askChecked = false, - denyChecked = false + denyChecked = false, ) UiAutomatorUtils2.getUiDevice().pressBack() @@ -306,7 +306,7 @@ class AppPermissionsTest { mapOf( "Allowed" to listOf(externalDeviceCameraText), "Ask every time" to emptyList(), - "Not allowed" to listOf("Camera") + "Not allowed" to listOf("Camera", "Contacts"), ) assertEquals(expectedGrantInfoMap, getGrantInfoMap()) @@ -327,7 +327,7 @@ class AppPermissionsTest { mapOf( "Allowed" to mutableListOf<String>(), "Ask every time" to mutableListOf(), - "Not allowed" to mutableListOf() + "Not allowed" to mutableListOf(), ) val outOfScopeTitles = setOf("Unused app settings", "Manage app if unused") @@ -360,21 +360,21 @@ class AppPermissionsTest { private fun verifyRadioButtonStates( allowForegroundChecked: Boolean, askChecked: Boolean, - denyChecked: Boolean + denyChecked: Boolean, ) { eventually { assertEquals( allowForegroundChecked, UiAutomatorUtils2.waitFindObject(By.res(ALLOW_FOREGROUND_ONLY_RADIO_BUTTON)) - .isChecked + .isChecked, ) assertEquals( askChecked, - UiAutomatorUtils2.waitFindObject(By.res(ASK_RADIO_BUTTON)).isChecked + UiAutomatorUtils2.waitFindObject(By.res(ASK_RADIO_BUTTON)).isChecked, ) assertEquals( denyChecked, - UiAutomatorUtils2.waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked + UiAutomatorUtils2.waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked, ) } } @@ -392,7 +392,7 @@ class AppPermissionsTest { ) }, Until.newWindow(), - NEW_WINDOW_TIMEOUT_MILLIS + NEW_WINDOW_TIMEOUT_MILLIS, ) } @@ -418,7 +418,7 @@ class AppPermissionsTest { permissionManager.grantRuntimePermission( APP_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, - persistentDeviceId + persistentDeviceId, ) private fun getPermState(): Map<String, PermissionManager.PermissionState> = diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt index 5c7573a0b..e1068e19a 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt @@ -24,11 +24,11 @@ import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT import android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA import android.content.ComponentName +import android.content.Context import android.content.Intent import android.content.Intent.EXTRA_RESULT_RECEIVER import android.content.pm.PackageManager import android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS -import android.hardware.display.DisplayManager import android.hardware.display.VirtualDisplay import android.os.Build import android.os.Bundle @@ -41,7 +41,6 @@ import android.permissionmultidevice.cts.UiAutomatorUtils.click import android.permissionmultidevice.cts.UiAutomatorUtils.findTextForView import android.permissionmultidevice.cts.UiAutomatorUtils.waitFindObject import android.platform.test.annotations.AppModeFull -import android.platform.test.annotations.RequiresFlagsDisabled import android.platform.test.annotations.RequiresFlagsEnabled import android.provider.Settings import android.view.Display @@ -65,13 +64,19 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream") @AppModeFull(reason = "VirtualDeviceManager cannot be accessed by instant apps") -class DeviceAwarePermissionGrantTest { +@RequiresFlagsEnabled( + Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, + Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES, +) +open class DeviceAwarePermissionGrantTest { private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() private val defaultDeviceContext = instrumentation.targetContext + private lateinit var defaultDeviceName: String private lateinit var virtualDeviceManager: VirtualDeviceManager private lateinit var virtualDevice: VirtualDeviceManager.VirtualDevice private lateinit var virtualDisplay: VirtualDisplay - private lateinit var deviceDisplayName: String + private lateinit var virtualDeviceName: String private val permissionManager = defaultDeviceContext.getSystemService(PermissionManager::class.java)!! @@ -88,194 +93,449 @@ class DeviceAwarePermissionGrantTest { installPackage(APP_APK_PATH_STREAMING) virtualDeviceManager = defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)!! + + defaultDeviceName = + Settings.Global.getString( + defaultDeviceContext.contentResolver, + Settings.Global.DEVICE_NAME, + ) + } + + @After + fun cleanup() { + uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false) + Thread.sleep(2000) + } + + private fun createVirtualDevice(cameraPolicy: Int = DEVICE_POLICY_DEFAULT) { virtualDevice = virtualDeviceRule.createManagedVirtualDevice( VirtualDeviceParams.Builder() - .setDevicePolicy(POLICY_TYPE_CAMERA, DEVICE_POLICY_CUSTOM) + .setDevicePolicy(POLICY_TYPE_CAMERA, cameraPolicy) .build() ) - - val displayConfigBuilder = - VirtualDeviceRule.createDefaultVirtualDisplayConfigBuilder( - DISPLAY_WIDTH, - DISPLAY_HEIGHT, - ) - .setFlags( - DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC or - DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED or - DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY - ) - virtualDisplay = - virtualDeviceRule.createManagedVirtualDisplay(virtualDevice, displayConfigBuilder)!! - deviceDisplayName = + virtualDeviceRule.createManagedVirtualDisplay( + virtualDevice, + VirtualDeviceRule.createTrustedVirtualDisplayConfigBuilder(), + )!! + virtualDeviceName = virtualDeviceManager.getVirtualDevice(virtualDevice.deviceId)!!.displayName.toString() } - @After - fun cleanup() { - uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false) - Thread.sleep(2000) + @Test + fun deviceAwarePermission_onHost_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = false, + ) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, - ) @Test - fun onHostDevice_requestPermissionForHostDevice_shouldGrantPermission() { - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) + fun deviceAwarePermission_onHost_withRemotePermission_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = true, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - testGrantPermissionForDevice( - Display.DEFAULT_DISPLAY, - DEVICE_ID_DEFAULT, - false, - "", + @Test + fun deviceAwarePermission_onHost_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_INVALID, expectPermissionGrantedOnDefaultDevice = true, - expectPermissionGrantedOnRemoteDevice = false, + expectPermissionGrantedOnVirtualDevice = false, ) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, - ) @Test - fun onHostDevice_requestPermissionForRemoteDevice_shouldGrantPermission() { - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) + fun deviceAwarePermission_onHost_withRemotePermission_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = true, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - testGrantPermissionForDevice( - Display.DEFAULT_DISPLAY, - virtualDevice.deviceId, - true, - deviceDisplayName, + @Test + fun deviceAwarePermission_onHost_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = virtualDevice.deviceId, expectPermissionGrantedOnDefaultDevice = false, - expectPermissionGrantedOnRemoteDevice = true, + expectPermissionGrantedOnVirtualDevice = true, ) } @Test - fun onHostDevice_requestPermissionForRemoteDeviceAfterPermissionGrantedToHostDevice() { - instrumentation.uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME, PERMISSION) + fun deviceAwarePermission_onHost_withHostPermission_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = true, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = virtualDevice.deviceId, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, true) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) + @Test + fun deviceAwarePermission_onRemote_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = virtualDevice.deviceId, + expectPermissionGrantedOnDefaultDevice = false, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - testGrantPermissionForDevice( - Display.DEFAULT_DISPLAY, - virtualDevice.deviceId, - true, - deviceDisplayName, + @Test + fun deviceAwarePermission_onRemote_withHostPermission_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = true, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = virtualDevice.deviceId, expectPermissionGrantedOnDefaultDevice = true, - expectPermissionGrantedOnRemoteDevice = true, + expectPermissionGrantedOnVirtualDevice = true, ) } @Test - fun onHostDevice_requestPermissionForHostDeviceAfterPermissionGrantedToRemoteDevice() { - permissionManager.grantRuntimePermission( - APP_PACKAGE_NAME, - PERMISSION, - virtualDevice.persistentDeviceId!!, + fun deviceAwarePermission_onRemote_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = virtualDevice.deviceId, + expectPermissionGrantedOnDefaultDevice = false, + expectPermissionGrantedOnVirtualDevice = true, ) + } - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, true) + @Test + fun deviceAwarePermission_onRemote_withHostPermission_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = true, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = virtualDevice.deviceId, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - testGrantPermissionForDevice( - Display.DEFAULT_DISPLAY, - DEVICE_ID_DEFAULT, - false, - "", + // TODO: Receives PERMISSION_DENIED but it's fine if remote permission is held?? + @Test + fun deviceAwarePermission_onRemote_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_DEFAULT, expectPermissionGrantedOnDefaultDevice = true, - expectPermissionGrantedOnRemoteDevice = true, + expectPermissionGrantedOnVirtualDevice = false, ) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, - ) - @RequiresFlagsDisabled(Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES) @Test - fun onRemoteDevice_requestPermissionForHostDevice_shouldShowWarningDialog() { - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) + fun deviceAwarePermission_onRemote_withRemotePermission_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_CUSTOM) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = true, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - requestPermissionOnDevice(virtualDisplay.display.displayId, DEVICE_ID_DEFAULT) + @Test + fun deviceAwarePermissionWithoutCapability_onHost_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - val displayId = virtualDisplay.display.displayId - waitFindObject(By.displayId(displayId).textContains("Permission request suppressed")) + @Test + fun deviceAwarePermissionWithoutCapability_onHost_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, - Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES, - ) - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @Test - fun onRemoteDevice_requestPermissionForHostDevice_shouldGrantPermission() { - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) - // Create a virtual device with default policy, so that camera permission request will - // correspond to default device camera access. - virtualDevice = - virtualDeviceRule.createManagedVirtualDevice( - VirtualDeviceParams.Builder() - .setDevicePolicy(POLICY_TYPE_CAMERA, DEVICE_POLICY_DEFAULT) - .build() - ) - testGrantPermissionForDevice( - virtualDisplay.display.displayId, - virtualDevice.deviceId, - true, - Settings.Global.getString( - defaultDeviceContext.contentResolver, - Settings.Global.DEVICE_NAME, - ), + fun deviceAwarePermissionWithoutCapability_onHost_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = DEVICE_ID_INVALID, expectPermissionGrantedOnDefaultDevice = true, - expectPermissionGrantedOnRemoteDevice = false, + expectPermissionGrantedOnVirtualDevice = true, ) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, - ) @Test - fun onRemoteDevice_requestPermissionForRemoteDevice_shouldGrantPermission() { - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false) - assertAppHasPermissionForDevice(virtualDevice.deviceId, false) + fun deviceAwarePermissionWithoutCapability_onRemote_requestRemotePermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } - testGrantPermissionForDevice( - virtualDisplay.display.displayId, - virtualDevice.deviceId, - true, - deviceDisplayName, - expectPermissionGrantedOnDefaultDevice = false, - expectPermissionGrantedOnRemoteDevice = true, + @Test + fun deviceAwarePermissionWithoutCapability_onRemote_requestPermissionWithoutDeviceId() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, ) } - private fun testGrantPermissionForDevice( - displayId: Int, - targetDeviceId: Int, - showDeviceName: Boolean, - expectedDeviceNameInDialog: String, + @Test + fun deviceAwarePermissionWithoutCapability_onRemote_requestHostPermission() { + createVirtualDevice(cameraPolicy = DEVICE_POLICY_DEFAULT) + testMultiDevicePermissionGrant( + permission = Manifest.permission.CAMERA, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onHost_requestHostPermission() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onHost_requestPermissionWithoutDeviceId() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onHost_requestRemotePermission() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = DEVICE_ID_DEFAULT, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = DEVICE_ID_INVALID, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onRemote_requestRemotePermission() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = virtualDevice.deviceId, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onRemote_requestPermissionWithoutDeviceId() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_INVALID, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + @Test + fun nonDeviceAwarePermission_onRemote_requestHostPermission() { + createVirtualDevice() + testMultiDevicePermissionGrant( + permission = Manifest.permission.READ_CONTACTS, + initialDefaultDevicePermission = false, + initialVirtualDevicePermission = false, + requestingFromDevice = virtualDevice.deviceId, + requestingForDevice = DEVICE_ID_DEFAULT, + dialogDeviceName = DEVICE_ID_DEFAULT, + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnVirtualDevice = true, + ) + } + + private fun testMultiDevicePermissionGrant( + permission: String, + initialDefaultDevicePermission: Boolean, + initialVirtualDevicePermission: Boolean, + requestingFromDevice: Int, + requestingForDevice: Int, + dialogDeviceName: Int, expectPermissionGrantedOnDefaultDevice: Boolean, - expectPermissionGrantedOnRemoteDevice: Boolean, + expectPermissionGrantedOnVirtualDevice: Boolean, ) { - val future = requestPermissionOnDevice(displayId, targetDeviceId) + if (initialDefaultDevicePermission) { + instrumentation.uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME, permission) + } + if (initialVirtualDevicePermission) { + grantRuntimePermissionOnVirtualDevice(permission) + } + assertAppHasPermissionForDevice( + DEVICE_ID_DEFAULT, + permission, + initialDefaultDevicePermission, + ) + assertAppHasPermissionForDevice( + virtualDevice.deviceId, + permission, + initialVirtualDevicePermission, + ) - if (showDeviceName) { + val displayId = + if (requestingFromDevice == DEVICE_ID_DEFAULT) { + Display.DEFAULT_DISPLAY + } else { + virtualDisplay.display.displayId + } + + val future = requestPermissionOnDevice(displayId, requestingForDevice, permission) + + if (dialogDeviceName != DEVICE_ID_INVALID) { + val expectedDeviceNameInDialog = + if (dialogDeviceName == DEVICE_ID_DEFAULT) { + defaultDeviceName + } else { + virtualDeviceName + } assertPermissionMessageContainsDeviceName(displayId, expectedDeviceNameInDialog) + } else { + assertPermissionMessageDoesNotContainDeviceName(displayId) } // Click the allow button in the dialog to grant permission - SystemUtil.eventually { click(By.displayId(displayId).res(ALLOW_BUTTON)) } + val allowButton = + if (permission == Manifest.permission.CAMERA) ALLOW_BUTTON_FOREGROUND else ALLOW_BUTTON + SystemUtil.eventually { click(By.displayId(displayId).res(allowButton)) } // Validate permission grant result returned from callback val grantPermissionResult = future.get(TIMEOUT, TimeUnit.MILLISECONDS) @@ -284,34 +544,49 @@ class DeviceAwarePermissionGrantTest { TestConstants.PERMISSION_RESULT_KEY_PERMISSIONS ) ) - .isEqualTo(arrayOf(PERMISSION)) + .isEqualTo(arrayOf(permission)) assertThat( grantPermissionResult.getIntArray(TestConstants.PERMISSION_RESULT_KEY_GRANT_RESULTS) ) .isEqualTo(arrayOf(PackageManager.PERMISSION_GRANTED).toIntArray()) + + val expectedPermissionResultDeviceId = + if (requestingForDevice == DEVICE_ID_INVALID) { + requestingFromDevice + } else { + requestingForDevice + } assertThat(grantPermissionResult.getInt(TestConstants.PERMISSION_RESULT_KEY_DEVICE_ID)) - .isEqualTo(targetDeviceId) + .isEqualTo(expectedPermissionResultDeviceId) // Validate whether permission is granted as expected - assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, expectPermissionGrantedOnDefaultDevice) + assertAppHasPermissionForDevice( + DEVICE_ID_DEFAULT, + permission, + expectPermissionGrantedOnDefaultDevice, + ) assertAppHasPermissionForDevice( virtualDevice.deviceId, - expectPermissionGrantedOnRemoteDevice, + permission, + expectPermissionGrantedOnVirtualDevice, ) } private fun requestPermissionOnDevice( displayId: Int, targetDeviceId: Int, + permission: String, ): CompletableFuture<Bundle> { val future = CompletableFuture<Bundle>() val callback = RemoteCallback { result: Bundle? -> future.complete(result) } + val permissions = mutableListOf(permission).toTypedArray() val intent = Intent() .setComponent( ComponentName(APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.RequestPermissionActivity") ) .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, targetDeviceId) + .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, permissions) .putExtra(EXTRA_RESULT_RECEIVER, callback) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) @@ -327,12 +602,23 @@ class DeviceAwarePermissionGrantTest { assertThat(text).contains(deviceName) } - private fun assertAppHasPermissionForDevice(deviceId: Int, expectPermissionGranted: Boolean) { + private fun assertPermissionMessageDoesNotContainDeviceName(displayId: Int) { + waitFindObject(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) + val text = findTextForView(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) + assertThat(text).doesNotContain(virtualDeviceName) + assertThat(text).doesNotContain(defaultDeviceName) + } + + private fun assertAppHasPermissionForDevice( + deviceId: Int, + permission: String, + expectPermissionGranted: Boolean, + ) { val checkPermissionResult = defaultDeviceContext .createDeviceContext(deviceId) .packageManager - .checkPermission(PERMISSION, APP_PACKAGE_NAME) + .checkPermission(permission, APP_PACKAGE_NAME) if (expectPermissionGranted) { Assert.assertEquals(PackageManager.PERMISSION_GRANTED, checkPermissionResult) @@ -347,18 +633,25 @@ class DeviceAwarePermissionGrantTest { return intent.resolveActivity(defaultDeviceContext.packageManager) } + private fun grantRuntimePermissionOnVirtualDevice(permission: String) { + permissionManager.grantRuntimePermission( + APP_PACKAGE_NAME, + permission, + virtualDevice.persistentDeviceId!!, + ) + } + companion object { const val APK_DIRECTORY = "/data/local/tmp/cts-permissionmultidevice" const val APP_APK_PATH_STREAMING = "${APK_DIRECTORY}/CtsAccessRemoteDeviceCamera.apk" const val APP_PACKAGE_NAME = "android.permissionmultidevice.cts.accessremotedevicecamera" const val PERMISSION_MESSAGE_ID = "com.android.permissioncontroller:id/permission_message" - const val ALLOW_BUTTON = + const val ALLOW_BUTTON_FOREGROUND = "com.android.permissioncontroller:id/permission_allow_foreground_only_button" - const val DEVICE_ID_DEFAULT = 0 + const val ALLOW_BUTTON = "com.android.permissioncontroller:id/permission_allow_button" + const val DEVICE_ID_DEFAULT = Context.DEVICE_ID_DEFAULT + const val DEVICE_ID_INVALID = Context.DEVICE_ID_INVALID const val PERSISTENT_DEVICE_ID_DEFAULT = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT - const val PERMISSION = Manifest.permission.CAMERA const val TIMEOUT = 5000L - private const val DISPLAY_HEIGHT = 1920 - private const val DISPLAY_WIDTH = 1080 } } diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java index 3bc3ff12b..e15614be2 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -878,7 +878,6 @@ public class RoleManagerTest { } @Test - @RequiresFlagsEnabled(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE) @EnsureHasPrivateProfile(installInstrumentedApp = OptionalBoolean.TRUE) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream") |