diff options
9 files changed, 285 insertions, 163 deletions
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml index 5dc571f45..f5a997674 100644 --- a/PermissionController/res/values/strings.xml +++ b/PermissionController/res/values/strings.xml @@ -2029,17 +2029,15 @@ <!--Title for dialog displayed to tell user that settings are blocked due to the phone state (such as being in a call with an unknown number) [CHAR LIMIT=50] --> <string name="enhanced_confirmation_phone_state_dialog_title">Can\u2019t complete action during call</string> <!--Content for dialog displayed to tell user that settings are blocked due to the phone state (such as being in a call with an unknown number) [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_desc"><xliff:g id="setting_description" example="allowing apps to install other apps">%1$s</xliff:g>\n\n - This setting is blocked to protect your device and data</string> + <string name="enhanced_confirmation_phone_state_dialog_desc">This setting is blocked to protect your device and data.<xliff:g id="scam_use_setting_description" example="scammers may ask you to allow apps to install other apps">%1$s</xliff:g></string> <!--Content explaining that the "install other apps" setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix">Scammers may try to install harmful apps by asking you to install unknown apps from a new source.</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc"><xliff:g id="empty_line">\n\n</xliff:g>Scammers may try to install harmful apps by asking you to install unknown apps from a new source.</string> <!--Content explaining that the "enable accessibility service" setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix">Scammers may try to take control of your device by asking you to allow accessibility access for an app.</string> - - <!--Content explaining that a generic setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix">Scammers may attempt to harm your device with this setting.</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc"><xliff:g id="empty_line">\n\n</xliff:g>Scammers may try to take control of your device by asking you to allow accessibility access for an app.</string> + <!--Content explaining that a generic setting is blocked due to the phone state in a dialog displayed to the user. currently empty [CHAR LIMIT=NONE] --> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc" /> <!--Title for dialog displayed to tell user that permissions are blocked by setting restrictions [CHAR LIMIT=50] --> <string name="enhanced_confirmation_dialog_title_permission">App was denied access to <xliff:g id="permission_name" example="contacts">%1$s</xliff:g></string> diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java index 6a7251563..0f79b19c0 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java +++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java @@ -992,7 +992,14 @@ public class Role { */ public void onHolderAddedAsUser(@NonNull String packageName, @NonNull UserHandle user, @NonNull Context context) { - RoleManagerCompat.setRoleFallbackEnabledAsUser(this, true, user, context); + if (RoleFlags.isProfileGroupExclusivityAvailable() + && com.android.permission.flags.Flags.crossUserRoleUxBugfixEnabled() + && getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { + UserHandle profileParent = UserUtils.getProfileParentOrSelf(user, context); + RoleManagerCompat.setRoleFallbackEnabledAsUser(this, true, profileParent, context); + } else { + RoleManagerCompat.setRoleFallbackEnabledAsUser(this, true, user, context); + } } /** diff --git a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt index d3c7e3a0b..c5191938e 100644 --- a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt +++ b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt @@ -153,8 +153,8 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() { var message: CharSequence? if (settingType == SettingType.BLOCKED_DUE_TO_PHONE_STATE) { title = settingType.titleRes?.let { context.getString(it) } - val messagePrefix = getPhoneStateMessagePrefix(context, settingIdentifier) - message = settingType.messageRes?.let { context.getString(it, messagePrefix) } + val settingMessage = getPhoneStateSettingMessage(context, settingIdentifier) + message = settingType.messageRes?.let { context.getString(it, settingMessage) } } else { val url = context.getString(R.string.help_url_action_disabled_by_restricted_settings) @@ -165,18 +165,17 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() { return Setting(title, message) } - private fun getPhoneStateMessagePrefix( + private fun getPhoneStateSettingMessage( context: Context, settingsIdentifier: String, ): String { return context.getString( when (settingsIdentifier) { AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE -> - R.string.enhanced_confirmation_phone_state_dialog_a11y_desc_prefix + R.string.enhanced_confirmation_phone_state_dialog_a11y_desc AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES -> - R.string.enhanced_confirmation_phone_state_dialog_install_desc_prefix - else -> - R.string.enhanced_confirmation_phone_state_dialog_generic_desc_prefix + R.string.enhanced_confirmation_phone_state_dialog_install_desc + else -> R.string.enhanced_confirmation_phone_state_dialog_generic_desc } ) } @@ -278,7 +277,7 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() { return AlertDialog.Builder(dialogActivity) .setView(createDialogView(dialogActivity, title, message)) - .setPositiveButton(R.string.enhanced_confirmation_dialog_ok) { _, _ -> + .setPositiveButton(R.string.dialog_close) { _, _ -> dialogActivity.onDialogResult(DialogResult.Okay) } .create() diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index ff333c6a0..145936382 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -22,6 +22,10 @@ import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_S import android.app.Instrumentation import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice +import android.companion.virtual.VirtualDeviceParams +import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM +import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT +import android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -33,10 +37,7 @@ import android.content.pm.PackageManager.PERMISSION_GRANTED import android.os.Build import android.os.UserHandle import android.permission.PermissionManager -import android.permission.flags.Flags import android.platform.test.annotations.AppModeFull -import android.platform.test.annotations.RequiresFlagsDisabled -import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.virtualdevice.cts.common.VirtualDeviceRule import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -66,18 +67,25 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager @get:Rule - var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( + var mVirtualDeviceRule = + VirtualDeviceRule.withAdditionalPermissions( Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, - Manifest.permission.GET_RUNTIME_PERMISSIONS + Manifest.permission.GET_RUNTIME_PERMISSIONS, ) @Rule @JvmField val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() @Before fun setup() { - virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() + virtualDevice = + mVirtualDeviceRule.createManagedVirtualDevice( + // Without custom audio policy, the RECORD_AUDIO permission won't be device aware. + VirtualDeviceParams.Builder() + .setDevicePolicy(POLICY_TYPE_AUDIO, DEVICE_POLICY_CUSTOM) + .build() + ) virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -89,43 +97,47 @@ class DevicePermissionsTest { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testDeviceAwareRuntimePermissionIsGranted() { - grantPermissionAndAssertGranted(Manifest.permission.CAMERA, virtualDeviceContext) + fun virtualDeviceDefaultPolicy_deviceAwarePermissionFallsBackToDefaultDevice() { + virtualDevice = + mVirtualDeviceRule.createManagedVirtualDevice( + // With default audio policy, the RECORD_AUDIO permission won't be device aware. + VirtualDeviceParams.Builder() + .setDevicePolicy(POLICY_TYPE_AUDIO, DEVICE_POLICY_DEFAULT) + .build() + ) + virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) + + grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, defaultDeviceContext) + assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) } - @RequiresFlagsDisabled(Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED) @Test - fun testDeviceAwareRuntimePermissionGrantIsInherited() { - grantPermissionAndAssertGranted(Manifest.permission.CAMERA, defaultDeviceContext) + fun virtualDeviceCustomPolicy_deviceAwarePermissionGrantedOnVirtualDevice() { + // When a device aware permission is granted on the default device, it's not automatically + // granted on the virtual device. + grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, defaultDeviceContext) + assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext) - assertPermission(Manifest.permission.CAMERA, PERMISSION_GRANTED, virtualDeviceContext) + grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) } @Test - fun testNonDeviceAwareRuntimePermissionGrantIsInherited() { + fun normalPermissionGrantedOnDefaultDevice_isGrantedOnVirtualDevice() { grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext) assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testDeviceAwareRuntimePermissionIsRevoked() { + fun virtualDeviceCustomPolicy_deviceAwarePermissionIsRevoked() { grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) revokePermissionAndAssertDenied(DEVICE_AWARE_PERMISSION, virtualDeviceContext) } @Test - fun testNonDeviceAwareRuntimePermissionIsRevokedForDefaultDevice() { + fun normalPermissionRevokedFromVirtualDevice_isAlsoRevokedOnDefaultDevice() { grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext) assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) // Revoke call from virtualDeviceContext should revoke for default device as well. @@ -134,24 +146,24 @@ class DevicePermissionsTest { } @Test - fun testNormalPermissionGrantIsInherited() { + fun normalPermission_isInheritedOnVirtualDevice() { assertPermission(Manifest.permission.INTERNET, PERMISSION_GRANTED, virtualDeviceContext) } @Test - fun testSignaturePermissionGrantIsInherited() { + fun signaturePermission_isInheritedOnVirtualDevice() { assertPermission(CUSTOM_SIGNATURE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext) } @Test - fun testOneTimePermissionIsRevoked() { + fun virtualDeviceCustomPolicy_oneTimePermissionIsRevoked() { grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) virtualDeviceContext.packageManager.updatePermissionFlags( DEVICE_AWARE_PERMISSION, TEST_PACKAGE_NAME, FLAG_PERMISSION_ONE_TIME, FLAG_PERMISSION_ONE_TIME, - UserHandle.of(virtualDeviceContext.userId) + UserHandle.of(virtualDeviceContext.userId), ) permissionManager.startOneTimePermissionSession( @@ -159,19 +171,15 @@ class DevicePermissionsTest { 0, 0, IMPORTANCE_FOREGROUND, - IMPORTANCE_FOREGROUND_SERVICE + IMPORTANCE_FOREGROUND_SERVICE, ) eventually { assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext) } } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testRevokeSelfPermissionOnKill() { + fun virtualDeviceCustomPolicy_revokeSelfPermissionOnKill_permissionIsRevoked() { grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext) revokeSelfPermission(DEVICE_AWARE_PERMISSION, virtualDeviceContext) @@ -180,105 +188,90 @@ class DevicePermissionsTest { } } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testGrantAndRevokeDeviceAwarePermissionByPersistentDeviceId() { - val deviceAwarePermission = DEVICE_AWARE_PERMISSION - + fun usePersistentDeviceIdToRevokeDeviceAwarePermission_permissionIsRevoked() { permissionManager.grantRuntimePermission( TEST_PACKAGE_NAME, - deviceAwarePermission, - persistentDeviceId + DEVICE_AWARE_PERMISSION, + persistentDeviceId, ) assertThat( permissionManager.checkPermission( - deviceAwarePermission, + DEVICE_AWARE_PERMISSION, TEST_PACKAGE_NAME, - virtualDevice.persistentDeviceId!! + virtualDevice.persistentDeviceId!!, ) ) .isEqualTo(PERMISSION_GRANTED) assertThat( permissionManager.checkPermission( - deviceAwarePermission, + DEVICE_AWARE_PERMISSION, TEST_PACKAGE_NAME, - PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT, ) ) .isEqualTo(PERMISSION_DENIED) permissionManager.revokeRuntimePermission( TEST_PACKAGE_NAME, - deviceAwarePermission, + DEVICE_AWARE_PERMISSION, persistentDeviceId, - "test" + "test", ) assertThat( permissionManager.checkPermission( - deviceAwarePermission, + DEVICE_AWARE_PERMISSION, TEST_PACKAGE_NAME, - virtualDevice.persistentDeviceId!! + virtualDevice.persistentDeviceId!!, ) ) .isEqualTo(PERMISSION_DENIED) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testUpdateAndGetPermissionFlagsByPersistentDeviceId() { - val deviceAwarePermission = DEVICE_AWARE_PERMISSION + fun updateAndGetPermissionFlagsByPersistentDeviceId() { val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED val flag = FLAG_PERMISSION_USER_SET assertThat( permissionManager.getPermissionFlags( TEST_PACKAGE_NAME, - deviceAwarePermission, - persistentDeviceId + DEVICE_AWARE_PERMISSION, + persistentDeviceId, ) ) .isEqualTo(0) permissionManager.updatePermissionFlags( TEST_PACKAGE_NAME, - deviceAwarePermission, + DEVICE_AWARE_PERMISSION, persistentDeviceId, flagMask, - flag + flag, ) assertThat( permissionManager.getPermissionFlags( TEST_PACKAGE_NAME, - deviceAwarePermission, - persistentDeviceId + DEVICE_AWARE_PERMISSION, + persistentDeviceId, ) ) .isEqualTo(FLAG_PERMISSION_USER_SET) } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testAllPermissionStatesApiGrantForVirtualDevice() { + fun permissionGrantedOnVirtualDevice_reflectedInGetAllPermissionStatesApi() { // Setting a flag explicitly so that the permission consistently stays in the state permissionManager.updatePermissionFlags( TEST_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, PERSISTENT_DEVICE_ID_DEFAULT, FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, - FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED + FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, ) assertThat( @@ -291,7 +284,7 @@ class DevicePermissionsTest { permissionManager.grantRuntimePermission( TEST_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, - persistentDeviceId + persistentDeviceId, ) val permissionStateMap = @@ -312,7 +305,7 @@ class DevicePermissionsTest { TEST_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, persistentDeviceId, - "test" + "test", ) assertThat( @@ -323,12 +316,8 @@ class DevicePermissionsTest { .isFalse() } - @RequiresFlagsEnabled( - Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, - Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED - ) @Test - fun testAllPermissionStatesApiFlagsForVirtualDevice() { + fun setPermissionFlagOnVirtualDevice_reflectedInGetAllPermissionStatesApi() { val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED val flag = FLAG_PERMISSION_USER_SET @@ -340,7 +329,7 @@ class DevicePermissionsTest { DEVICE_AWARE_PERMISSION, persistentDeviceId, flagMask, - flag + flag, ) assertThat( @@ -349,7 +338,7 @@ class DevicePermissionsTest { .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[ DEVICE_AWARE_PERMISSION]!! .flags, - flag + flag, ) ) .isTrue() @@ -360,15 +349,14 @@ class DevicePermissionsTest { .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[ DEVICE_AWARE_PERMISSION]!! .flags, - FLAG_PERMISSION_USER_FIXED + FLAG_PERMISSION_USER_FIXED, ) ) .isFalse() } - @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) @Test - fun testAllPermissionStatesApiGrantForDefaultDevice() { + fun permissionGrantedOnDefaultDevice_reflectedInGetAllPermissionStatesApi() { // Setting a flag explicitly so that the permission consistently stays in the state upon // revoke permissionManager.updatePermissionFlags( @@ -376,13 +364,13 @@ class DevicePermissionsTest { DEVICE_AWARE_PERMISSION, PERSISTENT_DEVICE_ID_DEFAULT, FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, - FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED + FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, ) permissionManager.grantRuntimePermission( TEST_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, - PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT, ) assertThat( @@ -404,7 +392,7 @@ class DevicePermissionsTest { TEST_PACKAGE_NAME, DEVICE_AWARE_PERMISSION, PERSISTENT_DEVICE_ID_DEFAULT, - "test" + "test", ) assertThat( @@ -416,9 +404,8 @@ class DevicePermissionsTest { .isFalse() } - @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) @Test - fun testAllPermissionStatesApiFlagsForDefaultDevice() { + fun setPermissionFlagOnDefaultDevice_reflectedInGetAllPermissionStatesApi() { val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED val flag = FLAG_PERMISSION_USER_SET @@ -434,7 +421,7 @@ class DevicePermissionsTest { DEVICE_AWARE_PERMISSION, PERSISTENT_DEVICE_ID_DEFAULT, flagMask, - flag + flag, ) assertThat( @@ -443,7 +430,7 @@ class DevicePermissionsTest { .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ DEVICE_AWARE_PERMISSION]!! .flags, - flag + flag, ) ) .isTrue() @@ -454,19 +441,18 @@ class DevicePermissionsTest { .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[ DEVICE_AWARE_PERMISSION]!! .flags, - FLAG_PERMISSION_USER_FIXED + FLAG_PERMISSION_USER_FIXED, ) ) .isFalse() } - @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) @Test - fun testAllPermissionStatesApiThatNonDeviceAwareRuntimePermissionGrantIsNotInherited() { + fun getAllPermissionStates_normalPermissionIsNotInherited() { permissionManager.grantRuntimePermission( TEST_PACKAGE_NAME, NON_DEVICE_AWARE_PERMISSION, - PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT, ) assertThat( @@ -501,7 +487,7 @@ class DevicePermissionsTest { context.packageManager.grantRuntimePermission( TEST_PACKAGE_NAME, permissionName, - UserHandle.of(context.userId) + UserHandle.of(context.userId), ) assertPermission(permissionName, PERMISSION_GRANTED, context) } @@ -510,18 +496,14 @@ class DevicePermissionsTest { context.packageManager.revokeRuntimePermission( TEST_PACKAGE_NAME, permissionName, - UserHandle.of(context.userId) + UserHandle.of(context.userId), ) assertPermission(permissionName, PERMISSION_DENIED, context) } - private fun assertPermission( - permissionName: String, - permissionState: Int, - context: Context, - ) { - assertThat(context.packageManager.checkPermission(permissionName, TEST_PACKAGE_NAME)) - .isEqualTo(permissionState) + private fun assertPermission(permissionName: String, permissionState: Int, context: Context) { + val uid = defaultDeviceContext.packageManager.getApplicationInfo(TEST_PACKAGE_NAME, 0).uid + assertThat(context.checkPermission(permissionName, -1, uid)).isEqualTo(permissionState) } companion object { diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index ceefe3dfd..2547b9786 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8995,13 +8995,13 @@ <!-- @SystemApi @FlaggedApi("android.permission.flags.text_classifier_choice_api_enabled") - This permission is required to access the specific text classifier you need from the + This permission is required to access the specific text classifier from the TextClassificationManager. - <p>Protection level: signature|role + <p>Protection level: signature|role|privileged @hide --> <permission android:name="android.permission.ACCESS_TEXT_CLASSIFIER_BY_TYPE" - android:protectionLevel="signature|role" + android:protectionLevel="signature|role|privileged" android:featureFlag="android.permission.flags.text_classifier_choice_api_enabled"/> <!-- Attribution for Geofencing service. --> diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt index ccc5a0a5e..f52e32344 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt @@ -38,6 +38,7 @@ import android.provider.DeviceConfig import android.provider.Settings import android.text.Spanned import android.text.style.ClickableSpan +import android.util.Log import android.view.View import android.view.accessibility.AccessibilityNodeInfo import androidx.test.uiautomator.By @@ -51,6 +52,7 @@ import com.android.compatibility.common.util.SystemUtil import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity +import com.android.compatibility.common.util.UiDumpUtils import com.android.modules.utils.build.SdkLevel import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit @@ -64,6 +66,7 @@ import org.junit.Before abstract class BaseUsePermissionTest : BasePermissionTest() { companion object { + const val LOG_TAG = "BaseUsePermissionTest" const val APP_APK_NAME_31 = "CtsUsePermissionApp31.apk" const val APP_APK_NAME_31_WITH_ASL = "CtsUsePermissionApp31WithAsl.apk" const val APP_APK_NAME_LATEST = "CtsUsePermissionAppLatest.apk" @@ -791,6 +794,9 @@ abstract class BaseUsePermissionTest : BasePermissionTest() { ) if (timeoutOccurred) { + val uiDump = StringBuilder() + UiDumpUtils.dumpNodes(uiDump) + Log.w(LOG_TAG, "Timed out waiting for window transition, UI dump: $uiDump") throw RuntimeException("Timed out waiting for window transition.") } } diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt index ae6e33b2a..e4ee52186 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt @@ -53,7 +53,8 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { openPermissionDecisions() waitFindObject( By.hasChild( - By.text("You gave $APP_PACKAGE_NAME access to location").displayId(displayId)) + By.text("You gave $APP_PACKAGE_NAME access to location").displayId(displayId) + ) .hasChild(By.text("Today").displayId(displayId)) .displayId(displayId) ) @@ -69,7 +70,8 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { openPermissionDecisions() waitFindObject( By.hasChild( - By.text("You denied $APP_PACKAGE_NAME access to location").displayId(displayId)) + By.text("You denied $APP_PACKAGE_NAME access to location").displayId(displayId) + ) .hasChild(By.text("Today").displayId(displayId)) .displayId(displayId) ) @@ -86,11 +88,13 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { openPermissionDecisions() assertNull( waitFindObjectOrNull( - By.hasChild(By.text("You denied $APP_PACKAGE_NAME access to location") - .displayId(displayId)) + By.hasChild( + By.text("You denied $APP_PACKAGE_NAME access to location") + .displayId(displayId) + ) .hasChild(By.text("Today").displayId(displayId)) .displayId(displayId), - ASSERT_ABSENT_SELECTOR_TIMEOUT_MS + ASSERT_ABSENT_SELECTOR_TIMEOUT_MS, ) ) } @@ -105,8 +109,10 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { openPermissionDecisions() waitFindObject( - By.hasChild(By.text("You gave $APP_PACKAGE_NAME access to location") - .displayId(displayId)) + By.hasChild( + By.text("You gave $APP_PACKAGE_NAME access to location") + .displayId(displayId) + ) .hasChild(By.text("Today").displayId(displayId)) .displayId(displayId) ) @@ -121,7 +127,8 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { pressBack() waitFindObject( By.hasChild( - By.text("You denied $APP_PACKAGE_NAME access to location").displayId(displayId)) + By.text("You denied $APP_PACKAGE_NAME access to location").displayId(displayId) + ) .hasChild(By.text("Today").displayId(displayId)) .displayId(displayId) ) @@ -132,7 +139,7 @@ class PermissionDecisionsTest : BaseUsePermissionTest() { SystemUtil.runWithShellPermissionIdentity { context.startActivity( Intent(PermissionManager.ACTION_REVIEW_PERMISSION_DECISIONS).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) } ) } diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt index c2b5447dd..17cef0e31 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt @@ -16,6 +16,7 @@ package android.permissionui.cts +import android.content.pm.PackageManager import android.health.connect.HealthPermissions import android.os.Build import android.permission.flags.Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED @@ -25,6 +26,7 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.test.filters.FlakyTest import androidx.test.filters.SdkSuppress import org.junit.Assume.assumeFalse +import org.junit.Assume.assumeTrue import org.junit.Before import org.junit.Rule import org.junit.Test @@ -33,6 +35,12 @@ import org.junit.Test @FlakyTest class PermissionSplitTest : BaseUsePermissionTest() { + companion object { + @JvmStatic + private val supportHeartrate = + packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE) + } + @Rule @JvmField val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() @Before @@ -146,6 +154,7 @@ class PermissionSplitTest : BaseUsePermissionTest() { @RequiresFlagsEnabled(FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) @Test fun testBodySensorSplitOnBaklava_splitToReadHeartRate() { + assumeTrue(supportHeartrate) installPackage(APP_APK_PATH_30_WITH_BACKGROUND) assertAppHasPermission(android.Manifest.permission.BODY_SENSORS, false) assertAppHasPermission(HealthPermissions.READ_HEART_RATE, false) @@ -195,6 +204,7 @@ class PermissionSplitTest : BaseUsePermissionTest() { } private fun testBodySensorPermissionSplitToBodySensorsBackground(expectSplit: Boolean) { + assumeTrue(supportHeartrate) assertAppHasPermission(android.Manifest.permission.BODY_SENSORS, false) assertAppHasPermission(android.Manifest.permission.BODY_SENSORS_BACKGROUND, false) diff --git a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt index f070fa9aa..3e24d5025 100644 --- a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt +++ b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt @@ -27,6 +27,7 @@ import android.os.Process import android.os.UserHandle import android.os.UserManager.DISALLOW_CONFIG_DEFAULT_APPS import android.provider.Settings +import android.util.Log import android.util.Pair import androidx.test.filters.SdkSuppress import androidx.test.rule.ActivityTestRule @@ -95,16 +96,24 @@ class RoleManagerMultiUserTest { ActivityTestRule(WaitForResultActivity::class.java) @Before - @Throws(java.lang.Exception::class) fun setUp() { assumeTrue(RoleManagerUtil.isCddCompliantScreenSize()) installAppForAllUsers() + + // If "none" selected in test, ensure we re-enable fallback for other test runs + permissions().withPermission(MANAGE_ROLE_HOLDERS, INTERACT_ACROSS_USERS_FULL).use { + setRoleFallbackEnabledForAllUsers() + } } @After - @Throws(java.lang.Exception::class) fun tearDown() { uninstallAppForAllUsers() + + // If "none" selected in test, ensure we re-enable fallback for other test runs + permissions().withPermission(MANAGE_ROLE_HOLDERS, INTERACT_ACROSS_USERS_FULL).use { + setRoleFallbackEnabledForAllUsers() + } } @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @@ -379,7 +388,7 @@ class RoleManagerMultiUserTest { val initialUser = deviceState.workProfile().userHandle() // setActiveUserForRole and getActiveUserForRole is used to ensure initial active users // state and requires INTERACT_ACROSS_USERS_FULL - permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(initialUser) @@ -407,7 +416,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole is used to ensure addRoleHolderAsUser didn't set active user, and // requires INTERACT_ACROSS_USERS_FULL - permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(initialUser) } @@ -472,6 +481,47 @@ class RoleManagerMultiUserTest { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) } + @RequireFlagsEnabled( + com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED, + com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_UX_BUGFIX_ENABLED, + ) + @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) + @EnsureHasWorkProfile + @RequireRunOnPrimaryUser + @Test + @Throws(java.lang.Exception::class) + fun addRoleHolderAsUserReenablesFallbackOnProfileParent() { + // Set other user as active + val initialUserReference = deviceState.initialUser() + val initialUser = initialUserReference.userHandle() + roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(initialUser) + + val profileParentRoleManager = getRoleManagerForUser(initialUserReference) + profileParentRoleManager.setRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, false) + assertThat( + profileParentRoleManager.isRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) + ) + .isFalse() + + val targetActiveUser = deviceState.workProfile().userHandle() + val future = CallbackFuture() + roleManager.addRoleHolderAsUser( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + targetActiveUser, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat( + profileParentRoleManager.isRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) + ) + .isTrue() + } + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @EnsureHasPermission(MANAGE_DEFAULT_APPLICATIONS) @EnsureDoesNotHavePermission(INTERACT_ACROSS_USERS_FULL) @@ -484,7 +534,7 @@ class RoleManagerMultiUserTest { val initialUser = deviceState.workProfile().userHandle() // setActiveUserForRole and getActiveUserForRole is used to ensure initial active users // state and requires INTERACT_ACROSS_USERS_FULL - permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(initialUser) @@ -504,7 +554,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole is used to ensure setDefaultApplication didn't set active user, // and requires INTERACT_ACROSS_USERS_FULL - permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(initialUser) } @@ -566,6 +616,50 @@ class RoleManagerMultiUserTest { eventually { assertExpectedProfileHasRoleUsingGetDefaultApplication(targetActiveUser) } } + @RequireFlagsEnabled( + com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED, + com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_UX_BUGFIX_ENABLED, + ) + @EnsureHasPermission( + INTERACT_ACROSS_USERS_FULL, + MANAGE_DEFAULT_APPLICATIONS, + MANAGE_ROLE_HOLDERS, + ) + @EnsureHasWorkProfile + @RequireRunOnPrimaryUser + @Test + @Throws(java.lang.Exception::class) + fun setDefaultApplicationReenablesFallbackOnProfileParent() { + // Set other user as active + val initialUserReference = deviceState.initialUser() + val initialUser = initialUserReference.userHandle() + roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(initialUser) + + val profileParentRoleManager = getRoleManagerForUser(initialUserReference) + profileParentRoleManager.setRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, false) + assertThat( + profileParentRoleManager.isRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) + ) + .isFalse() + + val future = CallbackFuture() + getRoleManagerForUser(deviceState.workProfile()) + .setDefaultApplication( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat( + profileParentRoleManager.isRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) + ) + .isTrue() + } + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) @EnsureCanAddUser @@ -1281,7 +1375,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1308,7 +1402,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(targetActiveUser) assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) @@ -1317,7 +1411,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1334,7 +1428,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1361,7 +1455,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(targetActiveUser) assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) @@ -1370,7 +1464,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1387,7 +1481,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1412,7 +1506,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(deviceState.initialUser().userHandle()) assertNoRoleHoldersUsingGetRoleHoldersAsUser() @@ -1421,7 +1515,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1438,7 +1532,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1465,7 +1559,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(targetActiveUser) assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) @@ -1474,7 +1568,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1491,7 +1585,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1518,7 +1612,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(targetActiveUser) assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) @@ -1527,7 +1621,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1544,7 +1638,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1569,7 +1663,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(deviceState.initialUser().userHandle()) assertNoRoleHoldersUsingGetRoleHoldersAsUser() @@ -1578,7 +1672,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -1950,7 +2044,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -1977,7 +2071,7 @@ class RoleManagerMultiUserTest { // getActiveUserForRole and getRoleHoldersAsUser require INTERACT_ACROSS_USERS_FULL and // MANAGE_ROLE_HOLDERS permissions to validate cross user role active user and role // holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) .isEqualTo(targetActiveUser) assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) @@ -1986,7 +2080,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -2007,7 +2101,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -2032,7 +2126,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -2053,7 +2147,7 @@ class RoleManagerMultiUserTest { // setDefaultHoldersForTestForAllUsers and setRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { // Set test default role holder. Ensures fallbacks to a default holder setDefaultHoldersForTestForAllUsers() setRoleVisibleForTestForAllUsers() @@ -2078,7 +2172,7 @@ class RoleManagerMultiUserTest { // clearDefaultHoldersForTestForAllUsers and clearRoleVisibleForTestForAllUsers require // INTERACT_ACROSS_USERS_FULL and MANAGE_ROLE_HOLDERS permissions to validate cross user // role active user and role holder states - permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { _ -> + permissions().withPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS).use { clearDefaultHoldersForTestForAllUsers() clearRoleVisibleForTestForAllUsers() } @@ -2215,7 +2309,7 @@ class RoleManagerMultiUserTest { private fun setDefaultHoldersForTestForAllUsers() { // Set test default role holder. Ensures fallbacks to a default holder for (userRoleManager in - users().profileGroup(deviceState.initialUser()).map { getRoleManagerForUser(it) }) { + users().profileGroup(users().current()).map { getRoleManagerForUser(it) }) { userRoleManager.setDefaultHoldersForTest( PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, listOf(APP_PACKAGE_NAME), @@ -2226,7 +2320,7 @@ class RoleManagerMultiUserTest { private fun clearDefaultHoldersForTestForAllUsers() { // Set test default role holder. Ensures fallbacks to a default holder for (userRoleManager in - users().profileGroup(deviceState.initialUser()).map { getRoleManagerForUser(it) }) { + users().profileGroup(users().current()).map { getRoleManagerForUser(it) }) { userRoleManager.setDefaultHoldersForTest( PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, emptyList(), @@ -2237,7 +2331,7 @@ class RoleManagerMultiUserTest { private fun setRoleVisibleForTestForAllUsers() { // Set test default role holder. Ensures fallbacks to a default holder for (userRoleManager in - users().profileGroup(deviceState.initialUser()).map { getRoleManagerForUser(it) }) { + users().profileGroup(users().current()).map { getRoleManagerForUser(it) }) { userRoleManager.setRoleVisibleForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, true) } } @@ -2245,11 +2339,28 @@ class RoleManagerMultiUserTest { private fun clearRoleVisibleForTestForAllUsers() { // Set test default role holder. Ensures fallbacks to a default holder for (userRoleManager in - users().profileGroup(deviceState.initialUser()).map { getRoleManagerForUser(it) }) { + users().profileGroup(users().current()).map { getRoleManagerForUser(it) }) { userRoleManager.setRoleVisibleForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, false) } } + private fun setRoleFallbackEnabledForAllUsers() { + for (userReference in users().profileGroup(users().current())) { + try { + val userRoleManager = getRoleManagerForUser(userReference) + userRoleManager.setRoleFallbackEnabled(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, true) + } catch (e: Exception) { + Log.w( + LOG_TAG, + "Encountered error setting fallback enabled for" + + " $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME@" + + "${userReference.userHandle().identifier}", + e, + ) + } + } + } + private fun getRoleManagerForUser(user: UserReference): RoleManager { val userContext = context().androidContextAsUser(user) return userContext.getSystemService(RoleManager::class.java) @@ -2262,6 +2373,8 @@ class RoleManagerMultiUserTest { } companion object { + private val LOG_TAG = RoleManagerMultiUserTest::class.java.simpleName + private const val TIMEOUT_MILLIS: Long = (15 * 1000).toLong() private const val IDLE_TIMEOUT_MILLIS: Long = (2 * 1000).toLong() private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME = |