From db39e27bcadc77b642e37827998b9a0c274c3266 Mon Sep 17 00:00:00 2001 From: Piotr Karzelek Date: Tue, 24 Sep 2024 13:54:35 +0000 Subject: move multi-user annotations to bedstead-multiuser module Test: atest bedstead-multiuser-test Bug: 334025286 Flag: TEST_ONLY Relnote: N/A LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I6effd0422c0250b3d45a78b13e4a03d01e2391bb --- tests/cts/role/src/android/app/role/cts/RoleManagerTest.java | 2 +- .../functional/multiusers/SafetyCenterMultiUsersTest.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tests') 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 b64de5665..a3bb0afb6 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -66,7 +66,7 @@ import androidx.test.uiautomator.Until; import com.android.bedstead.harrier.BedsteadJUnit4; import com.android.bedstead.harrier.DeviceState; -import com.android.bedstead.harrier.annotations.EnsureHasPrivateProfile; +import com.android.bedstead.multiuser.annotations.EnsureHasPrivateProfile; import com.android.bedstead.nene.types.OptionalBoolean; import com.android.compatibility.common.util.DisableAnimationRule; import com.android.compatibility.common.util.FreezeRotationRule; diff --git a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt index ff5dcc1f6..7c2062e8d 100644 --- a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt +++ b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt @@ -43,11 +43,11 @@ import androidx.test.core.app.ApplicationProvider import androidx.test.filters.LargeTest import com.android.bedstead.harrier.BedsteadJUnit4 import com.android.bedstead.harrier.DeviceState -import com.android.bedstead.harrier.annotations.EnsureHasAdditionalUser -import com.android.bedstead.harrier.annotations.EnsureHasCloneProfile +import com.android.bedstead.multiuser.annotations.EnsureHasAdditionalUser +import com.android.bedstead.multiuser.annotations.EnsureHasCloneProfile import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile -import com.android.bedstead.harrier.annotations.EnsureHasPrivateProfile -import com.android.bedstead.harrier.annotations.EnsureHasNoPrivateProfile +import com.android.bedstead.multiuser.annotations.EnsureHasPrivateProfile +import com.android.bedstead.multiuser.annotations.EnsureHasNoPrivateProfile import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile import com.android.bedstead.enterprise.annotations.EnsureHasDeviceOwner import com.android.bedstead.enterprise.annotations.EnsureHasNoDeviceOwner -- cgit v1.2.3-59-g8ed1b From bcd36031ea1a5c460294fb7c5efea387b5d0f6ca Mon Sep 17 00:00:00 2001 From: Piotr Karzelek Date: Fri, 27 Sep 2024 15:52:47 +0000 Subject: move multi-user and enterprise annotations to the modules Test: atest bedstead-multiuser-test Test: atest bedstead-enterprise-test Bug: 334025286 Bug: 336991736 Flag: TEST_ONLY Relnote: N/A LOW_COVERAGE_REASON=TEST_ONLY Change-Id: Ib1b16ffd8b706499fd7680a8b87fcdaa43899ab7 --- tests/cts/permissionmultiuser/AndroidTest.xml | 4 ++-- .../src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionmultiuser/AndroidTest.xml b/tests/cts/permissionmultiuser/AndroidTest.xml index 10fd4e7a5..f6834036b 100644 --- a/tests/cts/permissionmultiuser/AndroidTest.xml +++ b/tests/cts/permissionmultiuser/AndroidTest.xml @@ -63,8 +63,8 @@ diff --git a/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt index 2169f0f72..2067dec51 100644 --- a/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt +++ b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt @@ -50,15 +50,15 @@ import android.support.test.uiautomator.UiObject2 import android.util.Log import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry +import com.android.bedstead.enterprise.annotations.RequireRunOnWorkProfile import com.android.bedstead.harrier.BedsteadJUnit4 import com.android.bedstead.harrier.DeviceState import com.android.bedstead.permissions.annotations.EnsureHasPermission import com.android.bedstead.harrier.annotations.EnsureSecureSettingSet import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature import com.android.bedstead.harrier.annotations.RequireNotWatch -import com.android.bedstead.harrier.annotations.RequireRunOnAdditionalUser -import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile import com.android.bedstead.harrier.annotations.RequireSdkVersion +import com.android.bedstead.multiuser.annotations.RequireRunOnAdditionalUser import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS import com.android.compatibility.common.util.ApiTest import com.android.compatibility.common.util.DeviceConfigStateChangerRule -- cgit v1.2.3-59-g8ed1b From 5152677aecbe1054b8276bdef7e9ff193388bd27 Mon Sep 17 00:00:00 2001 From: Scarlett Song Date: Fri, 13 Sep 2024 01:56:40 +0000 Subject: Add BackgroundPermission cts test for health permissions After backgroundPermission attr is open to apk-in-apex apps, Health&Fitness can use this attr to link READ_HEART_RATE to bg permission, see other two CLs in this topic. This CL adds CTS test for this flow, to prove: 1. HealthConnect(which is an apk-in-apex package) can use backgroundPermission attr 2. READ_HEALTH_DATA_IN_BACKGROUND bg permission behaves like any other bg permissions Flag: android.permission.flags.replace_body_sensor_permission_enabled Test: atest BackgroundPermissionsTest Relnote: Add BackgroundPermission cts test for health permissions Bug: 364638912 Bug: 364643245 Change-Id: I5fc464a8e8fa1445bfce8e8a70ff1062633d4aff LOW_COVERAGE_REASON=TEST_ONLY --- .../permission/cts/BackgroundPermissionsTest.java | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java index f3f47631c..6c08f75ff 100644 --- a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java +++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java @@ -24,6 +24,7 @@ import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_INTERNAL; +import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP; import static android.permission.cts.PermissionUtils.getAppOp; import static android.permission.cts.PermissionUtils.grantPermission; import static android.permission.cts.PermissionUtils.install; @@ -31,8 +32,10 @@ import static android.permission.cts.PermissionUtils.uninstallApp; import static com.android.compatibility.common.util.SystemUtil.eventually; +import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -42,8 +45,13 @@ import android.app.UiAutomation; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; +import android.permission.flags.Flags; import android.platform.test.annotations.AppModeFull; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.ArrayMap; import android.util.Log; @@ -51,6 +59,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.After; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -72,6 +81,9 @@ public class BackgroundPermissionsTest { private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @After public void uninstallTestApp() { uninstallApp(APP_PKG); @@ -79,9 +91,23 @@ public class BackgroundPermissionsTest { @Test @AppModeFull(reason = "Instant apps cannot read properties of other packages") - public void verifybackgroundPermissionsProperties() throws Exception { + public void verifyBackgroundPropertiesForPlatformPermissions() throws Exception { + verifyBackgroundPermissionsProperties("android"); + } + + @RequiresFlagsEnabled({Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED}) + @Test + @AppModeFull(reason = "Instant apps cannot read properties of other packages") + public void verifyBackgroundPropertiesForHealthPermissions() throws Exception { + String healthPackageName = sContext.getPackageManager().getPermissionGroupInfo( + HEALTH_PERMISSION_GROUP, /* flags= */ 0).packageName; + verifyBackgroundPermissionsProperties(healthPackageName); + } + + private void verifyBackgroundPermissionsProperties(String packageName) + throws Exception { PackageInfo pkg = sContext.getPackageManager().getPackageInfo( - "android", PackageManager.GET_PERMISSIONS); + packageName, PackageManager.GET_PERMISSIONS); ArrayMap potentialBackgroundPermissionsToGroup = new ArrayMap<>(); int numPermissions = pkg.permissions.length; @@ -97,11 +123,13 @@ public class BackgroundPermissionsTest { } } + int backgroundPermissionCount = 0; for (int i = 0; i < numPermissions; i++) { PermissionInfo permission = pkg.permissions[i]; String backgroundPermissionName = permission.backgroundPermission; if (backgroundPermissionName != null) { + backgroundPermissionCount += 1; Log.i(LOG_TAG, permission.name + "->" + backgroundPermissionName); // foreground permissions must be dangerous @@ -115,6 +143,8 @@ public class BackgroundPermissionsTest { .containsKey(backgroundPermissionName)); } } + // Tested packages must have at least one permission linked with a background permission. + assertThat(backgroundPermissionCount).isGreaterThan(0); } /** -- cgit v1.2.3-59-g8ed1b From 5fd9eb6c4f28368e257d91da4248044ae7fcabaa Mon Sep 17 00:00:00 2001 From: Scarlett Song Date: Tue, 1 Oct 2024 21:18:31 +0000 Subject: Revert "Add BackgroundPermission cts test for health permissions" This reverts commit 5152677aecbe1054b8276bdef7e9ff193388bd27. Reason for revert: b/370579400 test failure on Android U based image. Change-Id: I5f2083a995aface34541b29f2a9a71be60c70ff2 LOW_COVERAGE_REASON=TEST_ONLY Bug: 364638912 Bug: 364643245 Bug: 370579400 --- .../permission/cts/BackgroundPermissionsTest.java | 34 ++-------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'tests') diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java index 6c08f75ff..f3f47631c 100644 --- a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java +++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java @@ -24,7 +24,6 @@ import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_INTERNAL; -import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP; import static android.permission.cts.PermissionUtils.getAppOp; import static android.permission.cts.PermissionUtils.grantPermission; import static android.permission.cts.PermissionUtils.install; @@ -32,10 +31,8 @@ import static android.permission.cts.PermissionUtils.uninstallApp; import static com.android.compatibility.common.util.SystemUtil.eventually; -import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -45,13 +42,8 @@ import android.app.UiAutomation; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; -import android.permission.flags.Flags; import android.platform.test.annotations.AppModeFull; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.ArrayMap; import android.util.Log; @@ -59,7 +51,6 @@ import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.After; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -81,9 +72,6 @@ public class BackgroundPermissionsTest { private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - @After public void uninstallTestApp() { uninstallApp(APP_PKG); @@ -91,23 +79,9 @@ public class BackgroundPermissionsTest { @Test @AppModeFull(reason = "Instant apps cannot read properties of other packages") - public void verifyBackgroundPropertiesForPlatformPermissions() throws Exception { - verifyBackgroundPermissionsProperties("android"); - } - - @RequiresFlagsEnabled({Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED}) - @Test - @AppModeFull(reason = "Instant apps cannot read properties of other packages") - public void verifyBackgroundPropertiesForHealthPermissions() throws Exception { - String healthPackageName = sContext.getPackageManager().getPermissionGroupInfo( - HEALTH_PERMISSION_GROUP, /* flags= */ 0).packageName; - verifyBackgroundPermissionsProperties(healthPackageName); - } - - private void verifyBackgroundPermissionsProperties(String packageName) - throws Exception { + public void verifybackgroundPermissionsProperties() throws Exception { PackageInfo pkg = sContext.getPackageManager().getPackageInfo( - packageName, PackageManager.GET_PERMISSIONS); + "android", PackageManager.GET_PERMISSIONS); ArrayMap potentialBackgroundPermissionsToGroup = new ArrayMap<>(); int numPermissions = pkg.permissions.length; @@ -123,13 +97,11 @@ public class BackgroundPermissionsTest { } } - int backgroundPermissionCount = 0; for (int i = 0; i < numPermissions; i++) { PermissionInfo permission = pkg.permissions[i]; String backgroundPermissionName = permission.backgroundPermission; if (backgroundPermissionName != null) { - backgroundPermissionCount += 1; Log.i(LOG_TAG, permission.name + "->" + backgroundPermissionName); // foreground permissions must be dangerous @@ -143,8 +115,6 @@ public class BackgroundPermissionsTest { .containsKey(backgroundPermissionName)); } } - // Tested packages must have at least one permission linked with a background permission. - assertThat(backgroundPermissionCount).isGreaterThan(0); } /** -- cgit v1.2.3-59-g8ed1b From 32ec3b253dad00cde669b4b2320517add9775c66 Mon Sep 17 00:00:00 2001 From: Song Chun Fan Date: Mon, 16 Sep 2024 20:34:58 +0000 Subject: [PermissionPolicyTest] add VERIFICATION_AGENT permission Change-Id: Icab0539e74a9ad4086b4d693fa0e16dfb50330da BUG: 360129103 FLAG: android.content.pm.verification_service Test: atest android.permissionpolicy.cts.PermissionPolicyTest#platformPermissionPolicyIsUnaltered Relnote: add VERIFICATION_AGENT permission LOW_COVERAGE_REASON=NON_CODE_ONLY --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index af96c9a20..13423ffc5 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8264,6 +8264,17 @@ + + + + -- cgit v1.2.3-59-g8ed1b From d3ced8a1b5ec08ef08f72f2d1bd387b116cf9d95 Mon Sep 17 00:00:00 2001 From: Vladimir Komsiyski Date: Tue, 24 Sep 2024 09:30:05 +0200 Subject: Drop VDM permissions from Shell role. Replace FakeAssociationRule with VirtualDeviceRule Bug: 370657093 Bug: 318641591 Test: presubmit Test: atest CtsPermissionTestCases Flag: EXEMPT test improvement LOW_COVERAGE_REASON=TEST_ONLY Relnote: N/A Change-Id: I6c1d6429e82aa653d8f6e89901b8e8a3a3455eb7 --- PermissionController/res/xml/roles.xml | 3 -- tests/cts/permission/AndroidManifest.xml | 3 ++ .../permission/cts/DevicePermissionsTest.kt | 27 +++-------------- .../cts/PermissionUpdateListenerTest.java | 35 ++++------------------ .../cts/permissionmultidevice/AndroidManifest.xml | 2 ++ .../cts/AppPermissionsTest.kt | 1 - 6 files changed, 15 insertions(+), 56 deletions(-) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 1d01f8208..fafe0f553 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -625,7 +625,6 @@ visible="false"> - @@ -642,8 +641,6 @@ minSdkVersion="33" /> - - + + + diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index dbda1f5e1..ff333c6a0 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -20,10 +20,8 @@ import android.Manifest import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE import android.app.Instrumentation -import android.companion.virtual.VirtualDeviceManager import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice -import android.companion.virtual.VirtualDeviceParams import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -40,17 +38,15 @@ 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.FakeAssociationRule +import android.virtualdevice.cts.common.VirtualDeviceRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry -import com.android.compatibility.common.util.AdoptShellPermissionsRule import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts import com.google.common.truth.Truth.assertThat import org.junit.After -import org.junit.Assume.assumeNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -69,13 +65,8 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager - @get:Rule var mFakeAssociationRule = FakeAssociationRule() - @get:Rule - val mAdoptShellPermissionsRule = - AdoptShellPermissionsRule( - instrumentation.uiAutomation, - Manifest.permission.CREATE_VIRTUAL_DEVICE, + var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, @@ -86,14 +77,7 @@ class DevicePermissionsTest { @Before fun setup() { - val virtualDeviceManager = - defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java) - assumeNotNull(virtualDeviceManager) - virtualDevice = - virtualDeviceManager!!.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - VirtualDeviceParams.Builder().build() - ) + virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -103,9 +87,6 @@ class DevicePermissionsTest { @After fun cleanup() { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") - if (this::virtualDevice.isInitialized) { - virtualDevice.close() - } } @RequiresFlagsEnabled( @@ -226,7 +207,7 @@ class DevicePermissionsTest { permissionManager.checkPermission( deviceAwarePermission, TEST_PACKAGE_NAME, - VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT ) ) .isEqualTo(PERMISSION_DENIED) diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java index e9e71af20..4325ace79 100644 --- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java +++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java @@ -22,10 +22,8 @@ import static com.android.compatibility.common.util.SystemUtil.runWithShellPermi import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assume.assumeNotNull; - import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.VirtualDeviceParams; +import android.companion.virtual.VirtualDeviceManager.VirtualDevice; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.OnPermissionsChangedListener; @@ -34,12 +32,11 @@ import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.virtualdevice.cts.common.FakeAssociationRule; +import android.virtualdevice.cts.common.VirtualDeviceRule; import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; @@ -71,15 +68,8 @@ public class PermissionUpdateListenerTest { private int mTestAppUid; - private VirtualDeviceManager mVirtualDeviceManager; - - @Rule - public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); - @Rule - public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( - InstrumentationRegistry.getInstrumentation().getUiAutomation(), - android.Manifest.permission.CREATE_VIRTUAL_DEVICE); + public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -92,7 +82,6 @@ public class PermissionUpdateListenerTest { SystemUtil.waitForBroadcasts(); Thread.sleep(1000); mTestAppUid = mPackageManager.getPackageUid(PACKAGE_NAME, 0); - mVirtualDeviceManager = mDefaultContext.getSystemService(VirtualDeviceManager.class); } @After @@ -127,11 +116,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testGrantPermissionNotifyListener(deviceContext, virtualDevice.getPersistentDeviceId()); } @@ -172,11 +157,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testRevokePermissionNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); @@ -213,11 +194,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testUpdatePermissionFlagsNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); diff --git a/tests/cts/permissionmultidevice/AndroidManifest.xml b/tests/cts/permissionmultidevice/AndroidManifest.xml index 9bad85813..7d04d140e 100644 --- a/tests/cts/permissionmultidevice/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AndroidManifest.xml @@ -24,6 +24,8 @@ + + diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index 4d166939a..ac5564e37 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -62,7 +62,6 @@ class AppPermissionsTest { Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, - Manifest.permission.CREATE_VIRTUAL_DEVICE ) private lateinit var persistentDeviceId: String -- cgit v1.2.3-59-g8ed1b From 93d445a8b687d86d1b79c5744d9a8006cde36e63 Mon Sep 17 00:00:00 2001 From: Song Chun Fan Date: Thu, 3 Oct 2024 16:07:01 +0000 Subject: Add missing permission declaration to fix PermissionPolicyTest The new permission was added in ag/29450003 Change-Id: Ibd04d74c94945456cbf29468fb6652d0b85d2f81 BUG: 371089266 Test: atest PermissionPolicyTest FLAG: android.content.pm.verification_service Relnote: add BIND_VERIFICATION_AGENT permission LOW_COVERAGE_REASON=NON_CODE_ONLY --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 13423ffc5..f548119b6 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8274,6 +8274,18 @@ android:protectionLevel="signature|privileged" android:featureFlag="android.content.pm.verification_service"/> + + -- cgit v1.2.3-59-g8ed1b From cff790e6f7cd364f90d1b68ff3b195920ea44af0 Mon Sep 17 00:00:00 2001 From: "Priyanka Advani (xWF)" Date: Mon, 7 Oct 2024 21:22:13 +0000 Subject: Revert "Drop VDM permissions from Shell role." Revert submission 29561525-no-vdm-shell Reason for revert: Droidmonitor created revert due to b/372058363. Will be verifying through ABTD before submission. Reverted changes: /q/submissionid:29561525-no-vdm-shell Change-Id: I164251563e9c71e87dfe3281d1719c35480860da --- PermissionController/res/xml/roles.xml | 3 ++ tests/cts/permission/AndroidManifest.xml | 3 -- .../permission/cts/DevicePermissionsTest.kt | 27 ++++++++++++++--- .../cts/PermissionUpdateListenerTest.java | 35 ++++++++++++++++++---- .../cts/permissionmultidevice/AndroidManifest.xml | 2 -- .../cts/AppPermissionsTest.kt | 1 + 6 files changed, 56 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index fafe0f553..1d01f8208 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -625,6 +625,7 @@ visible="false"> + @@ -641,6 +642,8 @@ minSdkVersion="33" /> + + - - - diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index ff333c6a0..dbda1f5e1 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -20,8 +20,10 @@ import android.Manifest import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE import android.app.Instrumentation +import android.companion.virtual.VirtualDeviceManager import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice +import android.companion.virtual.VirtualDeviceParams import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -38,15 +40,17 @@ 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 android.virtualdevice.cts.common.FakeAssociationRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry +import com.android.compatibility.common.util.AdoptShellPermissionsRule import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts import com.google.common.truth.Truth.assertThat import org.junit.After +import org.junit.Assume.assumeNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -65,8 +69,13 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager + @get:Rule var mFakeAssociationRule = FakeAssociationRule() + @get:Rule - var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( + val mAdoptShellPermissionsRule = + AdoptShellPermissionsRule( + instrumentation.uiAutomation, + Manifest.permission.CREATE_VIRTUAL_DEVICE, Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, @@ -77,7 +86,14 @@ class DevicePermissionsTest { @Before fun setup() { - virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() + val virtualDeviceManager = + defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java) + assumeNotNull(virtualDeviceManager) + virtualDevice = + virtualDeviceManager!!.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + VirtualDeviceParams.Builder().build() + ) virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -87,6 +103,9 @@ class DevicePermissionsTest { @After fun cleanup() { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") + if (this::virtualDevice.isInitialized) { + virtualDevice.close() + } } @RequiresFlagsEnabled( @@ -207,7 +226,7 @@ class DevicePermissionsTest { permissionManager.checkPermission( deviceAwarePermission, TEST_PACKAGE_NAME, - PERSISTENT_DEVICE_ID_DEFAULT + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT ) ) .isEqualTo(PERMISSION_DENIED) diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java index 4325ace79..e9e71af20 100644 --- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java +++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java @@ -22,8 +22,10 @@ import static com.android.compatibility.common.util.SystemUtil.runWithShellPermi import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeNotNull; + import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.VirtualDeviceManager.VirtualDevice; +import android.companion.virtual.VirtualDeviceParams; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.OnPermissionsChangedListener; @@ -32,11 +34,12 @@ import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.virtualdevice.cts.common.VirtualDeviceRule; +import android.virtualdevice.cts.common.FakeAssociationRule; import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; @@ -68,8 +71,15 @@ public class PermissionUpdateListenerTest { private int mTestAppUid; + private VirtualDeviceManager mVirtualDeviceManager; + + @Rule + public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); + @Rule - public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault(); + public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( + InstrumentationRegistry.getInstrumentation().getUiAutomation(), + android.Manifest.permission.CREATE_VIRTUAL_DEVICE); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -82,6 +92,7 @@ public class PermissionUpdateListenerTest { SystemUtil.waitForBroadcasts(); Thread.sleep(1000); mTestAppUid = mPackageManager.getPackageUid(PACKAGE_NAME, 0); + mVirtualDeviceManager = mDefaultContext.getSystemService(VirtualDeviceManager.class); } @After @@ -116,7 +127,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testGrantPermissionNotifyListener(deviceContext, virtualDevice.getPersistentDeviceId()); } @@ -157,7 +172,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testRevokePermissionNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); @@ -194,7 +213,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testUpdatePermissionFlagsNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); diff --git a/tests/cts/permissionmultidevice/AndroidManifest.xml b/tests/cts/permissionmultidevice/AndroidManifest.xml index 7d04d140e..9bad85813 100644 --- a/tests/cts/permissionmultidevice/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AndroidManifest.xml @@ -24,8 +24,6 @@ - - diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index ac5564e37..4d166939a 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -62,6 +62,7 @@ class AppPermissionsTest { Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, + Manifest.permission.CREATE_VIRTUAL_DEVICE ) private lateinit var persistentDeviceId: String -- cgit v1.2.3-59-g8ed1b From 899eec59a38981a538ae0be7342c4fefb0ed9848 Mon Sep 17 00:00:00 2001 From: Vladimir Komsiyski Date: Tue, 8 Oct 2024 06:31:40 +0000 Subject: Revert^2 "Drop VDM permissions from Shell role." cff790e6f7cd364f90d1b68ff3b195920ea44af0 LOW_COVERAGE_REASON=TEST_ONLY Change-Id: If70c15eed038fb55110b06448e06056e92e3a5c0 --- PermissionController/res/xml/roles.xml | 3 -- tests/cts/permission/AndroidManifest.xml | 3 ++ .../permission/cts/DevicePermissionsTest.kt | 27 +++-------------- .../cts/PermissionUpdateListenerTest.java | 35 ++++------------------ .../cts/permissionmultidevice/AndroidManifest.xml | 2 ++ .../cts/AppPermissionsTest.kt | 1 - 6 files changed, 15 insertions(+), 56 deletions(-) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 1d01f8208..fafe0f553 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -625,7 +625,6 @@ visible="false"> - @@ -642,8 +641,6 @@ minSdkVersion="33" /> - - + + + diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index dbda1f5e1..ff333c6a0 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -20,10 +20,8 @@ import android.Manifest import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE import android.app.Instrumentation -import android.companion.virtual.VirtualDeviceManager import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice -import android.companion.virtual.VirtualDeviceParams import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -40,17 +38,15 @@ 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.FakeAssociationRule +import android.virtualdevice.cts.common.VirtualDeviceRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry -import com.android.compatibility.common.util.AdoptShellPermissionsRule import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts import com.google.common.truth.Truth.assertThat import org.junit.After -import org.junit.Assume.assumeNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -69,13 +65,8 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager - @get:Rule var mFakeAssociationRule = FakeAssociationRule() - @get:Rule - val mAdoptShellPermissionsRule = - AdoptShellPermissionsRule( - instrumentation.uiAutomation, - Manifest.permission.CREATE_VIRTUAL_DEVICE, + var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, @@ -86,14 +77,7 @@ class DevicePermissionsTest { @Before fun setup() { - val virtualDeviceManager = - defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java) - assumeNotNull(virtualDeviceManager) - virtualDevice = - virtualDeviceManager!!.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - VirtualDeviceParams.Builder().build() - ) + virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -103,9 +87,6 @@ class DevicePermissionsTest { @After fun cleanup() { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") - if (this::virtualDevice.isInitialized) { - virtualDevice.close() - } } @RequiresFlagsEnabled( @@ -226,7 +207,7 @@ class DevicePermissionsTest { permissionManager.checkPermission( deviceAwarePermission, TEST_PACKAGE_NAME, - VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT ) ) .isEqualTo(PERMISSION_DENIED) diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java index e9e71af20..4325ace79 100644 --- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java +++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java @@ -22,10 +22,8 @@ import static com.android.compatibility.common.util.SystemUtil.runWithShellPermi import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assume.assumeNotNull; - import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.VirtualDeviceParams; +import android.companion.virtual.VirtualDeviceManager.VirtualDevice; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.OnPermissionsChangedListener; @@ -34,12 +32,11 @@ import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.virtualdevice.cts.common.FakeAssociationRule; +import android.virtualdevice.cts.common.VirtualDeviceRule; import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; @@ -71,15 +68,8 @@ public class PermissionUpdateListenerTest { private int mTestAppUid; - private VirtualDeviceManager mVirtualDeviceManager; - - @Rule - public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); - @Rule - public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( - InstrumentationRegistry.getInstrumentation().getUiAutomation(), - android.Manifest.permission.CREATE_VIRTUAL_DEVICE); + public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -92,7 +82,6 @@ public class PermissionUpdateListenerTest { SystemUtil.waitForBroadcasts(); Thread.sleep(1000); mTestAppUid = mPackageManager.getPackageUid(PACKAGE_NAME, 0); - mVirtualDeviceManager = mDefaultContext.getSystemService(VirtualDeviceManager.class); } @After @@ -127,11 +116,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testGrantPermissionNotifyListener(deviceContext, virtualDevice.getPersistentDeviceId()); } @@ -172,11 +157,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testRevokePermissionNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); @@ -213,11 +194,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testUpdatePermissionFlagsNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); diff --git a/tests/cts/permissionmultidevice/AndroidManifest.xml b/tests/cts/permissionmultidevice/AndroidManifest.xml index 9bad85813..7d04d140e 100644 --- a/tests/cts/permissionmultidevice/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AndroidManifest.xml @@ -24,6 +24,8 @@ + + diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index 4d166939a..ac5564e37 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -62,7 +62,6 @@ class AppPermissionsTest { Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, - Manifest.permission.CREATE_VIRTUAL_DEVICE ) private lateinit var persistentDeviceId: String -- cgit v1.2.3-59-g8ed1b From 0f45c1a6fe27a17495b0632c3835e75c30071ac6 Mon Sep 17 00:00:00 2001 From: "Priyanka Advani (xWF)" Date: Tue, 8 Oct 2024 20:41:10 +0000 Subject: Revert^3 "Drop VDM permissions from Shell role." 899eec59a38981a538ae0be7342c4fefb0ed9848 Change-Id: I0f4f1bfef84a035617dc11518d7b9fa437b152ef --- PermissionController/res/xml/roles.xml | 3 ++ tests/cts/permission/AndroidManifest.xml | 3 -- .../permission/cts/DevicePermissionsTest.kt | 27 ++++++++++++++--- .../cts/PermissionUpdateListenerTest.java | 35 ++++++++++++++++++---- .../cts/permissionmultidevice/AndroidManifest.xml | 2 -- .../cts/AppPermissionsTest.kt | 1 + 6 files changed, 56 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index fafe0f553..1d01f8208 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -625,6 +625,7 @@ visible="false"> + @@ -641,6 +642,8 @@ minSdkVersion="33" /> + + - - - diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index ff333c6a0..dbda1f5e1 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -20,8 +20,10 @@ import android.Manifest import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE import android.app.Instrumentation +import android.companion.virtual.VirtualDeviceManager import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice +import android.companion.virtual.VirtualDeviceParams import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -38,15 +40,17 @@ 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 android.virtualdevice.cts.common.FakeAssociationRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry +import com.android.compatibility.common.util.AdoptShellPermissionsRule import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts import com.google.common.truth.Truth.assertThat import org.junit.After +import org.junit.Assume.assumeNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -65,8 +69,13 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager + @get:Rule var mFakeAssociationRule = FakeAssociationRule() + @get:Rule - var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( + val mAdoptShellPermissionsRule = + AdoptShellPermissionsRule( + instrumentation.uiAutomation, + Manifest.permission.CREATE_VIRTUAL_DEVICE, Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, @@ -77,7 +86,14 @@ class DevicePermissionsTest { @Before fun setup() { - virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() + val virtualDeviceManager = + defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java) + assumeNotNull(virtualDeviceManager) + virtualDevice = + virtualDeviceManager!!.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + VirtualDeviceParams.Builder().build() + ) virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -87,6 +103,9 @@ class DevicePermissionsTest { @After fun cleanup() { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") + if (this::virtualDevice.isInitialized) { + virtualDevice.close() + } } @RequiresFlagsEnabled( @@ -207,7 +226,7 @@ class DevicePermissionsTest { permissionManager.checkPermission( deviceAwarePermission, TEST_PACKAGE_NAME, - PERSISTENT_DEVICE_ID_DEFAULT + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT ) ) .isEqualTo(PERMISSION_DENIED) diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java index 4325ace79..e9e71af20 100644 --- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java +++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java @@ -22,8 +22,10 @@ import static com.android.compatibility.common.util.SystemUtil.runWithShellPermi import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeNotNull; + import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.VirtualDeviceManager.VirtualDevice; +import android.companion.virtual.VirtualDeviceParams; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.OnPermissionsChangedListener; @@ -32,11 +34,12 @@ import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.virtualdevice.cts.common.VirtualDeviceRule; +import android.virtualdevice.cts.common.FakeAssociationRule; import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; @@ -68,8 +71,15 @@ public class PermissionUpdateListenerTest { private int mTestAppUid; + private VirtualDeviceManager mVirtualDeviceManager; + + @Rule + public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); + @Rule - public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault(); + public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( + InstrumentationRegistry.getInstrumentation().getUiAutomation(), + android.Manifest.permission.CREATE_VIRTUAL_DEVICE); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -82,6 +92,7 @@ public class PermissionUpdateListenerTest { SystemUtil.waitForBroadcasts(); Thread.sleep(1000); mTestAppUid = mPackageManager.getPackageUid(PACKAGE_NAME, 0); + mVirtualDeviceManager = mDefaultContext.getSystemService(VirtualDeviceManager.class); } @After @@ -116,7 +127,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testGrantPermissionNotifyListener(deviceContext, virtualDevice.getPersistentDeviceId()); } @@ -157,7 +172,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testRevokePermissionNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); @@ -194,7 +213,11 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException { - VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); + assumeNotNull(mVirtualDeviceManager); + VirtualDeviceManager.VirtualDevice virtualDevice = + mVirtualDeviceManager.createVirtualDevice( + mFakeAssociationRule.getAssociationInfo().getId(), + new VirtualDeviceParams.Builder().build()); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testUpdatePermissionFlagsNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); diff --git a/tests/cts/permissionmultidevice/AndroidManifest.xml b/tests/cts/permissionmultidevice/AndroidManifest.xml index 7d04d140e..9bad85813 100644 --- a/tests/cts/permissionmultidevice/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AndroidManifest.xml @@ -24,8 +24,6 @@ - - diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index ac5564e37..4d166939a 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -62,6 +62,7 @@ class AppPermissionsTest { Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, + Manifest.permission.CREATE_VIRTUAL_DEVICE ) private lateinit var persistentDeviceId: String -- cgit v1.2.3-59-g8ed1b From 5b7968bf1f1acf5291a606e700e3d804003549cf Mon Sep 17 00:00:00 2001 From: Vladimir Komsiyski Date: Wed, 9 Oct 2024 06:27:15 +0000 Subject: Revert^4 "Drop VDM permissions from Shell role." 0f45c1a6fe27a17495b0632c3835e75c30071ac6 LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I09790de752e933efa424cbab66c282c67a86ee4e --- PermissionController/res/xml/roles.xml | 3 -- tests/cts/permission/AndroidManifest.xml | 3 ++ .../permission/cts/DevicePermissionsTest.kt | 27 +++-------------- .../cts/PermissionUpdateListenerTest.java | 35 ++++------------------ .../cts/permissionmultidevice/AndroidManifest.xml | 2 ++ .../cts/AppPermissionsTest.kt | 1 - 6 files changed, 15 insertions(+), 56 deletions(-) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 1d01f8208..fafe0f553 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -625,7 +625,6 @@ visible="false"> - @@ -642,8 +641,6 @@ minSdkVersion="33" /> - - + + + diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt index dbda1f5e1..ff333c6a0 100644 --- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt +++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt @@ -20,10 +20,8 @@ import android.Manifest import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE import android.app.Instrumentation -import android.companion.virtual.VirtualDeviceManager import android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT import android.companion.virtual.VirtualDeviceManager.VirtualDevice -import android.companion.virtual.VirtualDeviceParams import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME @@ -40,17 +38,15 @@ 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.FakeAssociationRule +import android.virtualdevice.cts.common.VirtualDeviceRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry -import com.android.compatibility.common.util.AdoptShellPermissionsRule import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts import com.google.common.truth.Truth.assertThat import org.junit.After -import org.junit.Assume.assumeNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -69,13 +65,8 @@ class DevicePermissionsTest { private lateinit var permissionManager: PermissionManager - @get:Rule var mFakeAssociationRule = FakeAssociationRule() - @get:Rule - val mAdoptShellPermissionsRule = - AdoptShellPermissionsRule( - instrumentation.uiAutomation, - Manifest.permission.CREATE_VIRTUAL_DEVICE, + var mVirtualDeviceRule = VirtualDeviceRule.withAdditionalPermissions( Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, @@ -86,14 +77,7 @@ class DevicePermissionsTest { @Before fun setup() { - val virtualDeviceManager = - defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java) - assumeNotNull(virtualDeviceManager) - virtualDevice = - virtualDeviceManager!!.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - VirtualDeviceParams.Builder().build() - ) + virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice() virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId) permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!! persistentDeviceId = virtualDevice.persistentDeviceId!! @@ -103,9 +87,6 @@ class DevicePermissionsTest { @After fun cleanup() { runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME") - if (this::virtualDevice.isInitialized) { - virtualDevice.close() - } } @RequiresFlagsEnabled( @@ -226,7 +207,7 @@ class DevicePermissionsTest { permissionManager.checkPermission( deviceAwarePermission, TEST_PACKAGE_NAME, - VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + PERSISTENT_DEVICE_ID_DEFAULT ) ) .isEqualTo(PERMISSION_DENIED) diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java index e9e71af20..4325ace79 100644 --- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java +++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java @@ -22,10 +22,8 @@ import static com.android.compatibility.common.util.SystemUtil.runWithShellPermi import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assume.assumeNotNull; - import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.VirtualDeviceParams; +import android.companion.virtual.VirtualDeviceManager.VirtualDevice; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.OnPermissionsChangedListener; @@ -34,12 +32,11 @@ import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.virtualdevice.cts.common.FakeAssociationRule; +import android.virtualdevice.cts.common.VirtualDeviceRule; import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; @@ -71,15 +68,8 @@ public class PermissionUpdateListenerTest { private int mTestAppUid; - private VirtualDeviceManager mVirtualDeviceManager; - - @Rule - public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); - @Rule - public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( - InstrumentationRegistry.getInstrumentation().getUiAutomation(), - android.Manifest.permission.CREATE_VIRTUAL_DEVICE); + public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -92,7 +82,6 @@ public class PermissionUpdateListenerTest { SystemUtil.waitForBroadcasts(); Thread.sleep(1000); mTestAppUid = mPackageManager.getPackageUid(PACKAGE_NAME, 0); - mVirtualDeviceManager = mDefaultContext.getSystemService(VirtualDeviceManager.class); } @After @@ -127,11 +116,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testGrantPermissionNotifyListener(deviceContext, virtualDevice.getPersistentDeviceId()); } @@ -172,11 +157,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testRevokePermissionNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); @@ -213,11 +194,7 @@ public class PermissionUpdateListenerTest { @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED}) public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException { - assumeNotNull(mVirtualDeviceManager); - VirtualDeviceManager.VirtualDevice virtualDevice = - mVirtualDeviceManager.createVirtualDevice( - mFakeAssociationRule.getAssociationInfo().getId(), - new VirtualDeviceParams.Builder().build()); + VirtualDevice virtualDevice = mVirtualDeviceRule.createManagedVirtualDevice(); Context deviceContext = mDefaultContext.createDeviceContext(virtualDevice.getDeviceId()); testUpdatePermissionFlagsNotifyListener( deviceContext, virtualDevice.getPersistentDeviceId()); diff --git a/tests/cts/permissionmultidevice/AndroidManifest.xml b/tests/cts/permissionmultidevice/AndroidManifest.xml index 9bad85813..7d04d140e 100644 --- a/tests/cts/permissionmultidevice/AndroidManifest.xml +++ b/tests/cts/permissionmultidevice/AndroidManifest.xml @@ -24,6 +24,8 @@ + + diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt index 4d166939a..ac5564e37 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt @@ -62,7 +62,6 @@ class AppPermissionsTest { Manifest.permission.GRANT_RUNTIME_PERMISSIONS, Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, - Manifest.permission.CREATE_VIRTUAL_DEVICE ) private lateinit var persistentDeviceId: String -- cgit v1.2.3-59-g8ed1b From 15315a5b118a461eac8c65201ef38ac7aca49790 Mon Sep 17 00:00:00 2001 From: Scarlett Song Date: Fri, 13 Sep 2024 01:56:40 +0000 Subject: Add BackgroundPermission cts test for health permissions After backgroundPermission attr is open to apk-in-apex apps, Health&Fitness can use this attr to link READ_HEART_RATE to bg permission, see other two CLs in this topic. This CL adds CTS test for this flow, to prove: 1. HealthConnect(which is an apk-in-apex package) can use backgroundPermission attr 2. READ_HEALTH_DATA_IN_BACKGROUND bg permission behaves like any other bg permissions LOW_COVERAGE_REASON=TEST_ONLY Flag: android.permission.flags.replace_body_sensor_permission_enabled Test: atest BackgroundPermissionsTest Relnote: Add BackgroundPermission cts test for health permissions Bug: 364638912 Bug: 364643245 Fixes: 370579400 Change-Id: If9c34e64b9903740cbe195af23169b8ff9113366 --- .../permission/cts/BackgroundPermissionsTest.java | 36 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java index f3f47631c..fcdccd87a 100644 --- a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java +++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java @@ -24,6 +24,7 @@ import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_INTERNAL; +import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP; import static android.permission.cts.PermissionUtils.getAppOp; import static android.permission.cts.PermissionUtils.grantPermission; import static android.permission.cts.PermissionUtils.install; @@ -31,6 +32,7 @@ import static android.permission.cts.PermissionUtils.uninstallApp; import static com.android.compatibility.common.util.SystemUtil.eventually; +import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertNotEquals; @@ -43,14 +45,21 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; +import android.os.Build; +import android.permission.flags.Flags; import android.platform.test.annotations.AppModeFull; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.ArrayMap; import android.util.Log; +import androidx.test.filters.SdkSuppress; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.After; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -72,6 +81,9 @@ public class BackgroundPermissionsTest { private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @After public void uninstallTestApp() { uninstallApp(APP_PKG); @@ -79,9 +91,25 @@ public class BackgroundPermissionsTest { @Test @AppModeFull(reason = "Instant apps cannot read properties of other packages") - public void verifybackgroundPermissionsProperties() throws Exception { + public void verifyBackgroundPropertiesForPlatformPermissions() throws Exception { + verifyBackgroundPermissionsProperties("android"); + } + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, + codeName = "VanillaIceCream") + @RequiresFlagsEnabled({Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED}) + @Test + @AppModeFull(reason = "Instant apps cannot read properties of other packages") + public void verifyBackgroundPropertiesForHealthPermissions() throws Exception { + String healthPackageName = sContext.getPackageManager().getPermissionGroupInfo( + HEALTH_PERMISSION_GROUP, /* flags= */ 0).packageName; + verifyBackgroundPermissionsProperties(healthPackageName); + } + + private void verifyBackgroundPermissionsProperties(String packageName) + throws Exception { PackageInfo pkg = sContext.getPackageManager().getPackageInfo( - "android", PackageManager.GET_PERMISSIONS); + packageName, PackageManager.GET_PERMISSIONS); ArrayMap potentialBackgroundPermissionsToGroup = new ArrayMap<>(); int numPermissions = pkg.permissions.length; @@ -97,11 +125,13 @@ public class BackgroundPermissionsTest { } } + int backgroundPermissionCount = 0; for (int i = 0; i < numPermissions; i++) { PermissionInfo permission = pkg.permissions[i]; String backgroundPermissionName = permission.backgroundPermission; if (backgroundPermissionName != null) { + backgroundPermissionCount += 1; Log.i(LOG_TAG, permission.name + "->" + backgroundPermissionName); // foreground permissions must be dangerous @@ -115,6 +145,8 @@ public class BackgroundPermissionsTest { .containsKey(backgroundPermissionName)); } } + // Tested packages must have at least one permission linked with a background permission. + assertThat(backgroundPermissionCount).isGreaterThan(0); } /** -- cgit v1.2.3-59-g8ed1b From 089480bb75c4e5313d4c2cb2d90f05bd1ccdcb54 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Mon, 14 Oct 2024 15:21:21 -0700 Subject: Disable A11y services before running ReviewAccessibilityServicesTest This ensures that any preexisting enabled services do not affect the test (which restores them afterwards) Bug: 372626091 Test: atest ReviewAccessibilityServicesTest Flag: EXEMPT test only Relnote: test fix LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I091b66808ed66ae84f959083fdf8d40e281ba297 --- .../cts/ReviewAccessibilityServicesTest.kt | 56 +++++++++++++++------- 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt index 03151c9fe..55f028e17 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt @@ -23,6 +23,7 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.platform.test.annotations.AppModeFull +import android.provider.Settings import androidx.test.filters.FlakyTest import androidx.test.platform.app.InstrumentationRegistry import androidx.test.runner.AndroidJUnit4 @@ -36,9 +37,11 @@ import com.android.compatibility.common.util.SystemUtil import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull import java.util.regex.Pattern import org.junit.After +import org.junit.AfterClass import org.junit.Assert.assertEquals import org.junit.Assume import org.junit.Before +import org.junit.BeforeClass import org.junit.Ignore import org.junit.Rule import org.junit.Test @@ -49,15 +52,41 @@ import org.junit.runner.RunWith @FlakyTest class ReviewAccessibilityServicesTest { - private val context: Context = InstrumentationRegistry.getInstrumentation().context private val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private val testService1String = context.getString(R.string.test_accessibility_service) private val testService2String = context.getString(R.string.test_accessibility_service_2) private val packageName = context.packageManager.permissionControllerPackageName companion object { + private val context: Context = InstrumentationRegistry.getInstrumentation().context + private var enabledA11yServices: String? = null private const val EXPECTED_TIMEOUT_MS = 500L private const val NEW_WINDOW_TIMEOUT_MILLIS: Long = 20_000 + + @BeforeClass + @JvmStatic + fun disableServices() { + enabledA11yServices = + Settings.Secure.getString( + context.contentResolver, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + ) + if (enabledA11yServices != null) { + InstrumentedAccessibilityService.disableAllServices() + } + } + + @AfterClass + @JvmStatic + fun reenableServices() { + if (enabledA11yServices != null) { + SystemUtil.runShellCommand( + "settings put secure ${Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES} " + + enabledA11yServices + ) + enabledA11yServices = null + } + } } @get:Rule @@ -161,7 +190,7 @@ class ReviewAccessibilityServicesTest { !uiDevice.performActionAndWait( { block() }, Until.newWindow(), - NEW_WINDOW_TIMEOUT_MILLIS + NEW_WINDOW_TIMEOUT_MILLIS, ) if (timeoutOccurred) { @@ -183,17 +212,11 @@ class ReviewAccessibilityServicesTest { private fun waitForSettingsButtonToDisappear() { SystemUtil.eventually { - findPCObjectByClassAndText(false, - "android.widget.Button", - "Settings" - ) + findPCObjectByClassAndText(false, "android.widget.Button", "Settings") } } - private fun findObjectByTextWithoutRetry( - shouldBePresent: Boolean, - text: String, - ): UiObject2? { + private fun findObjectByTextWithoutRetry(shouldBePresent: Boolean, text: String): UiObject2? { val containsWithoutCaseSelector = By.text(Pattern.compile(".*$text.*", Pattern.CASE_INSENSITIVE)) val view = @@ -206,7 +229,7 @@ class ReviewAccessibilityServicesTest { assertEquals( "Expected to find view with text $text: $shouldBePresent", shouldBePresent, - view != null + view != null, ) return view } @@ -222,15 +245,16 @@ class ReviewAccessibilityServicesTest { private fun findPCObjectByClassAndText( shouldBePresent: Boolean, className: String, - text: String + text: String, ): UiObject2? { - val selector = By.pkg(packageName) - .clazz(className) - .text(text) + val selector = By.pkg(packageName).clazz(className).text(text) val view = waitFindObjectOrNull(selector) assertEquals( "Expected to find view with packageName '$packageName' className '$className' " + - "text '$text' : $shouldBePresent", shouldBePresent, view != null) + "text '$text' : $shouldBePresent", + shouldBePresent, + view != null, + ) return view } } -- cgit v1.2.3-59-g8ed1b From 68952b942052c0f4661866fb3c2be51f52b652c6 Mon Sep 17 00:00:00 2001 From: Piotr Karzelek Date: Wed, 16 Oct 2024 13:19:15 +0000 Subject: remove multi-user and enterprise deprecated functions from DeviceState Test: atest HarrierTest:com.android.bedstead.harrier.MainAnnotationExecutorTest Test: atest CtsDevicePolicyTestCases:android.devicepolicy.cts.UserTest Flag: TEST_ONLY Bug: 334025286 Bug: 336991736 Relnote: N/A LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I3ac40f911559749f047974fa083c87251ee2207c --- tests/cts/permissionmultiuser/Android.bp | 1 + .../src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt | 1 + tests/cts/role/Android.bp | 1 + tests/cts/role/src/android/app/role/cts/RoleManagerTest.java | 3 ++- tests/functional/safetycenter/multiusers/Android.bp | 1 + .../safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt | 4 ++++ 6 files changed, 10 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/cts/permissionmultiuser/Android.bp b/tests/cts/permissionmultiuser/Android.bp index b86b02205..23aafb7e0 100644 --- a/tests/cts/permissionmultiuser/Android.bp +++ b/tests/cts/permissionmultiuser/Android.bp @@ -33,6 +33,7 @@ android_test { "compatibility-device-util-axt", "ctstestrunner-axt", "Harrier", + "bedstead-multiuser", "modules-utils-build_system", "Nene", ], diff --git a/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt index 2067dec51..f3309bd3c 100644 --- a/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt +++ b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt @@ -58,6 +58,7 @@ import com.android.bedstead.harrier.annotations.EnsureSecureSettingSet import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature import com.android.bedstead.harrier.annotations.RequireNotWatch import com.android.bedstead.harrier.annotations.RequireSdkVersion +import com.android.bedstead.multiuser.additionalUser import com.android.bedstead.multiuser.annotations.RequireRunOnAdditionalUser import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS import com.android.compatibility.common.util.ApiTest diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp index f0095b7dd..5751aaada 100644 --- a/tests/cts/role/Android.bp +++ b/tests/cts/role/Android.bp @@ -33,6 +33,7 @@ android_test { "compatibility-device-util-axt", "ctstestrunner-axt", "Harrier", + "bedstead-multiuser", "platform-test-annotations", "truth", ], 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 4ba8b33e7..2116f59b4 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -16,6 +16,7 @@ package android.app.role.cts; +import static com.android.bedstead.multiuser.MultiUserDeviceStateExtensionsKt.privateProfile; import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity; import static com.android.compatibility.common.util.SystemUtil.runShellCommand; import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow; @@ -864,7 +865,7 @@ public class RoleManagerTest { return; } - UserHandle privateProfile = sDeviceState.privateProfile().userHandle(); + UserHandle privateProfile = privateProfile(sDeviceState).userHandle(); assertThat(privateProfile).isNotNull(); installPackage(APP_APK_PATH, privateProfile); installPackage(APP_CLONE_APK_PATH, privateProfile); diff --git a/tests/functional/safetycenter/multiusers/Android.bp b/tests/functional/safetycenter/multiusers/Android.bp index 30024221b..745e763f0 100644 --- a/tests/functional/safetycenter/multiusers/Android.bp +++ b/tests/functional/safetycenter/multiusers/Android.bp @@ -36,6 +36,7 @@ android_test { "Harrier", "Nene", "TestApp", + "bedstead-enterprise", "com.android.permission.flags-aconfig-java-export", ], test_suites: [ diff --git a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt index 7c2062e8d..82ca0365c 100644 --- a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt +++ b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt @@ -51,6 +51,10 @@ import com.android.bedstead.multiuser.annotations.EnsureHasNoPrivateProfile import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile import com.android.bedstead.enterprise.annotations.EnsureHasDeviceOwner import com.android.bedstead.enterprise.annotations.EnsureHasNoDeviceOwner +import com.android.bedstead.enterprise.workProfile +import com.android.bedstead.multiuser.additionalUser +import com.android.bedstead.multiuser.cloneProfile +import com.android.bedstead.multiuser.privateProfile import com.android.bedstead.nene.TestApis import com.android.bedstead.nene.types.OptionalBoolean.TRUE import com.android.compatibility.common.util.DisableAnimationRule -- cgit v1.2.3-59-g8ed1b From d04df17f09693b367ae0ee21115d54dd422b3699 Mon Sep 17 00:00:00 2001 From: Kiran Ramachandra Date: Wed, 16 Oct 2024 20:22:33 +0000 Subject: Implemented a screen size check to prevent failures on small screens. Cuttlefish instances that run for kernal build test have the screensize 360x640, which is smaller than the CDD compliant size. This change adds precondition to skip the test on the smaller screens. Fixes: 356958319 Test: atest CtsRoleTestCases:android.app.role.cts.RoleManagerTest Flag: EXEMPT bugfix Relnote: N/A LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I69208cc2450716eb3940eaa2ac4ec40ec76bb80f --- .../src/android/app/role/cts/RoleManagerTest.java | 1 + .../src/android/app/role/cts/RoleManagerUtil.kt | 62 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/cts/role/src/android/app/role/cts/RoleManagerUtil.kt (limited to 'tests') 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 4ba8b33e7..9d7e5647a 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -184,6 +184,7 @@ public class RoleManagerTest { @Before public void setUp() throws Exception { + assumeTrue(RoleManagerUtil.INSTANCE.isCddCompliantScreenSize()); saveRoleHolder(); installApp(); wakeUpScreen(); diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerUtil.kt b/tests/cts/role/src/android/app/role/cts/RoleManagerUtil.kt new file mode 100644 index 000000000..10a3834a2 --- /dev/null +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerUtil.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.role.cts + +import android.content.res.Configuration +import android.content.res.Resources +import android.util.Log + +object RoleManagerUtil { + private val TAG = RoleManagerUtil::class.java.getSimpleName() + + /** + * This method checks for the minimum screen size described in CDD {@see + * https://source.android.com/docs/compatibility/14/android-14-cdd#7111_screen_size_and_shape} + */ + fun isCddCompliantScreenSize(): Boolean { + if ( + Resources.getSystem().configuration.uiMode and Configuration.UI_MODE_TYPE_MASK == + Configuration.UI_MODE_TYPE_WATCH + ) { + Log.d(TAG, "UI mode is UI_MODE_TYPE_WATCH, skipping the min dp check") + return true + } + + val screenSize = + Resources.getSystem().configuration.screenLayout and + Configuration.SCREENLAYOUT_SIZE_MASK + return when (screenSize) { + Configuration.SCREENLAYOUT_SIZE_SMALL -> hasMinScreenSize(426, 320) + Configuration.SCREENLAYOUT_SIZE_NORMAL -> hasMinScreenSize(480, 320) + Configuration.SCREENLAYOUT_SIZE_LARGE -> hasMinScreenSize(640, 480) + Configuration.SCREENLAYOUT_SIZE_XLARGE -> hasMinScreenSize(960, 720) + else -> { + Log.e(TAG, "Unknown screen size: $screenSize") + true + } + } + } + + private fun hasMinScreenSize(minWidthDp: Int, minHeightDp: Int): Boolean { + val dpi = Resources.getSystem().displayMetrics.densityDpi + val widthDp = (160f / dpi) * Resources.getSystem().displayMetrics.widthPixels + val heightDp = (160f / dpi) * Resources.getSystem().displayMetrics.heightPixels + + // CDD does seem to follow width & height convention correctly, hence checking both ways + return (widthDp >= minWidthDp && heightDp >= minHeightDp) || + (widthDp >= minHeightDp && heightDp >= minWidthDp) + } +} -- cgit v1.2.3-59-g8ed1b From 4e1b337231556a8485fc25b3d0de5b42c18c9555 Mon Sep 17 00:00:00 2001 From: Hani Kazmi Date: Thu, 15 Aug 2024 10:49:13 +0000 Subject: [AAPM] Introduce new Service for Android Advanced Protection Mode We add a new service and manager, behind a feature flag. This service will be used to enroll devices into a security conscious protection mode, and to allow clients to customise behaviour based on the state of this mode. LOW_COVERAGE_REASON=FLAG_NOT_ENABLED Bug: 352420507 Test: atest AdvancedProtectionServiceTest AdvancedProtectionManagerTest Flag: android.security.aapm_api Relnote: Add test for new Advanced Protection permissions Change-Id: I406e6aaf2f3b3a3337bd88381dfab9d7cbc63ec4 --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index f548119b6..e345d17e8 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -3915,6 +3915,20 @@ android:protectionLevel="signature|installer" /> + + + + + + Date: Thu, 17 Oct 2024 15:53:50 -0700 Subject: Add android.permission.ENTER_TRADE_IN_MODE LOW_COVERAGE_REASON=TEST_ONLY Test: atest CtsPermissionPolicyTestCases Bug: 307713521 Relnote: Adding Trade-In Mode for refurbishers Flag: com.android.tradeinmode.flags.enable_trade_in_mode Change-Id: I7cc19ae062c0bbe83d373671efb703d0c5ba3fe8 --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index e345d17e8..2eff8b0af 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8301,6 +8301,14 @@ android:protectionLevel="internal" android:featureFlag="android.content.pm.verification_service" /> + + + -- cgit v1.2.3-59-g8ed1b From 7524fd573150739154d797446fbdf734f8423018 Mon Sep 17 00:00:00 2001 From: Haofan Wang Date: Wed, 9 Oct 2024 21:24:51 +0000 Subject: CTS: Add permissions for media quality service - `android.permission.ACCESS_GLOBAL_PQ_SERVICE for access global PQ params - `android.permission.ACCESS_GLOBAL_PQ_SERVICE for access global AQ params LOW_COVERAGE_REASON=NON_CODE_ONLY Bug: 375312083 Change-Id: I1fbe2f9db12701134389dd9c81f85a30d3621637 Test: m Flag: android.media.tv.flags.media_quality_fw Relnote: add permissions for media quality service --- .../permissionpolicy/res/raw/android_manifest.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 2eff8b0af..cfe790292 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8301,6 +8301,28 @@ android:protectionLevel="internal" android:featureFlag="android.content.pm.verification_service" /> + + + + + + + + -- cgit v1.2.3-59-g8ed1b From 30216160fc35e9960cd503f39f69089ed81d0975 Mon Sep 17 00:00:00 2001 From: Shreshta Manu Date: Thu, 3 Oct 2024 19:58:42 +0000 Subject: [Ranging] Add new permission for Android generic ranging. This will be a part of nearby devices permission group. Bug: 370977414 Test: atest CtsPermissionPolicyTestCases Flag: com.android.ranging.flags.ranging_stack_enabled Relnote: Add new permission for ranging Change-Id: I3027aed81d6ad5f0449f8d82df1161918a16ac88 --- .../permissioncontroller/permission/utils/PermissionMapping.kt | 6 ++++++ tests/cts/permissionpolicy/Android.bp | 1 + tests/cts/permissionpolicy/res/raw/android_manifest.xml | 10 ++++++++++ .../permissionpolicy/cts/RuntimePermissionProperties.kt | 8 ++++++++ 4 files changed, 25 insertions(+) (limited to 'tests') diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt index 3198a4c09..a3446f802 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt @@ -139,6 +139,12 @@ object PermissionMapping { PLATFORM_PERMISSIONS[Manifest.permission.NEARBY_WIFI_DEVICES] = Manifest.permission_group.NEARBY_DEVICES } + // Ranging permission will be supported from Android B+, update this when isAtLeastB() + // is available. + if (SdkLevel.isAtLeastV() && Flags.rangingPermissionEnabled()) { + PLATFORM_PERMISSIONS[Manifest.permission.RANGING] = + Manifest.permission_group.NEARBY_DEVICES + } // Any updates to the permissions for the CALL_LOG permission group must also be made in // Permissions {@link com.android.role.controller.model.Permissions} in the role diff --git a/tests/cts/permissionpolicy/Android.bp b/tests/cts/permissionpolicy/Android.bp index e6041eea2..4249f3c9d 100644 --- a/tests/cts/permissionpolicy/Android.bp +++ b/tests/cts/permissionpolicy/Android.bp @@ -37,6 +37,7 @@ android_test { "permission-test-util-lib", "androidx.test.rules", "flag-junit", + "android.permission.flags-aconfig-java-export", ], srcs: [ "src/**/*.java", diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index cfe790292..3f25f4bf8 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -2396,6 +2396,16 @@ android:label="@string/permlab_nearby_wifi_devices" android:protectionLevel="dangerous" /> + + + + + + + -- cgit v1.2.3-59-g8ed1b From 8e29874c6690ee46995c8b1490597f79d9aa915c Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Tue, 20 Aug 2024 11:09:53 +0100 Subject: Introduce permission to start vibration sessions Bug: 345414356 Test: android.os.cts.VendorVibrationSessionTest Flag: android.os.vibrator.vendor_vibration_effects Change-Id: I7073fb1c1755c9bc02d1623f959e8457953b4d94 Relnote: Introducing permission for new system APIs supporting vendor vibration sessions LOW_COVERAGE_REASON=NON_CODE_ONLY --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index cfe790292..aca61e1d1 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -2606,12 +2606,22 @@ + + + + + + + + -- cgit v1.2.3-59-g8ed1b From 160f7c6d5202992bfd0d3e447488819c9fd0ead6 Mon Sep 17 00:00:00 2001 From: Mayank Garg Date: Sun, 3 Nov 2024 00:10:50 -0700 Subject: Ignore CameraMicIndicatorsPermissionTest for Multi-user-multi-display (MUMD) When visible background user (aka MUMD) is enabled, background users are visible on other displays. Right now, Camera and Mic are not supported for secondary user visible as background user. Flag: EXEMPT test only LOW_COVERAGE_REASON=TEST_ONLY Relnote: n/A Bug: 355564081 Test: atest --user-type secondary_user_on_secondary_display android.permissionui.cts.CameraMicIndicatorsPermissionTest#testChainUsageWithOtherUsage Change-Id: I61c919cef089df055d8598ad92236ff057ecd8d0 --- .../permissionui/cts/CameraMicIndicatorsPermissionTest.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt index e3197599c..19b67e729 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt @@ -28,6 +28,7 @@ import android.os.Build import android.os.Process import android.os.SystemClock import android.os.SystemProperties +import android.os.UserManager import android.permission.PermissionManager import android.permission.cts.MtsIgnore import android.platform.test.annotations.AsbSecurityTest @@ -161,6 +162,8 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase { @Before fun setUp() { + // Camera and Mic are not supported for secondary user visible as a background user. + assumeFalse(isAutomotiveWithVisibleBackgroundUser()) runWithShellPermissionIdentity { screenTimeoutBeforeTest = Settings.System.getLong(context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT) @@ -209,6 +212,9 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase { @After fun tearDown() { + if (isAutomotiveWithVisibleBackgroundUser()) { + return + } uninstall() if (isCar) { // Deselect the indicator since it persists otherwise @@ -775,4 +781,10 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase { private fun byOneOfText(vararg textValues: String) = By.text(Pattern.compile(textValues.joinToString(separator = "|") { Pattern.quote(it) })) + + fun isAutomotiveWithVisibleBackgroundUser(): Boolean { + val userManager = context.getSystemService(UserManager::class.java) + return packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) && + userManager.isVisibleBackgroundUsersSupported() + } } -- cgit v1.2.3-59-g8ed1b From 4cb1f5d332054380fe0197ad8d1dc7a422402329 Mon Sep 17 00:00:00 2001 From: Mayank Garg Date: Tue, 29 Oct 2024 17:29:05 -0700 Subject: Enable testSetWifiEnabled for passenger Flag: EXEMPT test only Relnote: n/a LOW_COVERAGE_REASON=TEST_ONLY Bug: 367313415 Test: atest --user-type secondary_user_on_secondary_display android.permission.cts.NoWifiStatePermissionTest#testSetWifiEnabled Change-Id: I955a99e212e3c739fc1facec42b1d8901b71b3f9 --- .../src/android/permission/cts/NoWifiStatePermissionTest.java | 8 -------- 1 file changed, 8 deletions(-) (limited to 'tests') diff --git a/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java index a0637827c..9fff22747 100644 --- a/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java +++ b/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java @@ -30,9 +30,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.UserHelper; - -import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -217,11 +214,6 @@ public class NoWifiStatePermissionTest { */ @Test(expected = SecurityException.class) public void testSetWifiEnabled() { - // Skip the test for passenger on Multi-user-multi-display devices for Automotive - UserHelper userHelper = new UserHelper(sContext); - Assume.assumeFalse( - "Skipped for visible background User as wifi is disabled for visible background " - + "user.", userHelper.isVisibleBackgroundUser()); mWifiManager.setWifiEnabled(true); } } -- cgit v1.2.3-59-g8ed1b From dec13bc178821c419bee9b9a74841ad55ac1c668 Mon Sep 17 00:00:00 2001 From: Jacqueline Bronger Date: Wed, 30 Oct 2024 01:44:55 +0100 Subject: Add android.permission.TV_IMPLICIT_ENTER_PIP Bug: 281512335 Bug: 283115999 Test: atest CtsPermissionPolicyTestCases Flag: android.app.enable_tv_implicit_enter_pip_restriction Relnote: Adding new permission for implicit PiP entry on TV LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I9abc69e76c8ef1ddc8dbfa9c75b1f3b340bd306c --- tests/cts/permissionpolicy/Android.bp | 1 + tests/cts/permissionpolicy/res/raw/android_manifest.xml | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/Android.bp b/tests/cts/permissionpolicy/Android.bp index 4249f3c9d..07fde8bff 100644 --- a/tests/cts/permissionpolicy/Android.bp +++ b/tests/cts/permissionpolicy/Android.bp @@ -37,6 +37,7 @@ android_test { "permission-test-util-lib", "androidx.test.rules", "flag-junit", + "android.app.flags-aconfig", "android.permission.flags-aconfig-java-export", ], srcs: [ diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 28d1d6c1e..1397205ba 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -4258,6 +4258,18 @@ android:description="@string/permdesc_hideOverlayWindows" android:protectionLevel="normal" /> + + + -- cgit v1.2.3-59-g8ed1b From 7f27dc5ff6a4b2197218d02b680da802e73f4302 Mon Sep 17 00:00:00 2001 From: Richard MacGregor Date: Mon, 14 Oct 2024 16:11:38 -0700 Subject: Add Cross-user role persistence Add persistence for cross-user role support. LOW_COVERAGE_REASON=FLAG_NOT_ENABLED Relnote: Add cross-user role persistence Flag: com.android.permission.flags.cross_user_role_enabled Test: atest RolesPersistenceTest Bug: 373469933 Change-Id: I428f1033e8c76959fea611070a79ac1c7b3eb6ac --- .../com/android/role/controller/model/Role.java | 2 + service/java/com/android/role/RoleService.java | 2 + service/java/com/android/role/RoleUserState.java | 36 ++++++++++++++-- .../role/persistence/RolesPersistenceImpl.java | 22 +++++++++- .../com/android/role/persistence/RolesState.java | 42 +++++++++++++++++-- service/proto/role_service.proto | 3 ++ tests/apex/Android.bp | 2 + .../role/persistence/RolesPersistenceTest.kt | 48 +++++++++++++++++++++- 8 files changed, 149 insertions(+), 8 deletions(-) (limited to 'tests') 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 570ef034a..67a37bdef 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 @@ -447,6 +447,8 @@ public class Role { if (!isAvailableByFeatureFlagAndSdkVersion()) { return false; } + // TODO(b/376133070): ensure that cross-user role is only available if also available for + // the profile-group's full user if (mBehavior != null) { return mBehavior.isAvailableAsUser(this, user, context); } diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index 20250b4f6..b8e3ad8b1 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -176,6 +176,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback registerUserRemovedReceiver(); } + // TODO(b/375029649): enforce single active user for all cross-user roles private void registerUserRemovedReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_USER_REMOVED); @@ -191,6 +192,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback }, intentFilter, null, null); } + // TODO(b/375029649): enforce single active user for all cross-user roles @Override public void onStart() { publishBinderService(Context.ROLE_SERVICE, new Stub()); diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java index 81007d65e..cda7fcfa8 100644 --- a/service/java/com/android/role/RoleUserState.java +++ b/service/java/com/android/role/RoleUserState.java @@ -39,6 +39,7 @@ import com.android.role.persistence.RolesState; import com.android.server.role.RoleServicePlatformHelper; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -95,6 +96,10 @@ class RoleUserState { @NonNull private ArraySet mFallbackEnabledRoles = new ArraySet<>(); + @GuardedBy("mLock") + @NonNull + private ArrayMap mActiveUserIds = new ArrayMap<>(); + @GuardedBy("mLock") private boolean mWriteScheduled; @@ -449,9 +454,15 @@ class RoleUserState { // Force a reconciliation on next boot if we are bypassing role qualification now. String packagesHash = mBypassingRoleQualification ? null : mPackagesHash; - roles = new RolesState(mVersion, packagesHash, - (Map>) (Map) snapshotRolesLocked(), - snapshotFallbackEnabledRoles()); + if (com.android.permission.flags.Flags.crossUserRoleEnabled()) { + roles = new RolesState(mVersion, packagesHash, + (Map>) (Map) snapshotRolesLocked(), + snapshotFallbackEnabledRoles(), snapshotActiveUserIds()); + } else { + roles = new RolesState(mVersion, packagesHash, + (Map>) (Map) snapshotRolesLocked(), + snapshotFallbackEnabledRoles()); + } } mPersistence.writeForUser(roles, UserHandle.of(mUserId)); @@ -463,14 +474,17 @@ class RoleUserState { Map> roles; Set fallbackEnabledRoles; + Map activeUserIds; if (roleState != null) { mVersion = roleState.getVersion(); mPackagesHash = roleState.getPackagesHash(); roles = roleState.getRoles(); fallbackEnabledRoles = roleState.getFallbackEnabledRoles(); + activeUserIds = roleState.getActiveUserIds(); } else { roles = mPlatformHelper.getLegacyRoleState(mUserId); fallbackEnabledRoles = roles.keySet(); + activeUserIds = Collections.emptyMap(); } mRoles.clear(); for (Map.Entry> entry : roles.entrySet()) { @@ -480,6 +494,10 @@ class RoleUserState { } mFallbackEnabledRoles.clear(); mFallbackEnabledRoles.addAll(fallbackEnabledRoles); + mActiveUserIds.clear(); + if (com.android.permission.flags.Flags.crossUserRoleEnabled()) { + mActiveUserIds.putAll(activeUserIds); + } if (roleState == null) { scheduleWriteFileLocked(); } @@ -496,12 +514,14 @@ class RoleUserState { int version; String packagesHash; ArrayMap> roles; + ArrayMap activeUserIds; ArraySet fallbackEnabledRoles; synchronized (mLock) { version = mVersion; packagesHash = mPackagesHash; roles = snapshotRolesLocked(); fallbackEnabledRoles = snapshotFallbackEnabledRoles(); + activeUserIds = snapshotActiveUserIds(); } long fieldToken = dumpOutputStream.start(fieldName, fieldId); @@ -514,10 +534,14 @@ class RoleUserState { String roleName = roles.keyAt(rolesIndex); ArraySet roleHolders = roles.valueAt(rolesIndex); boolean fallbackEnabled = fallbackEnabledRoles.contains(roleName); + Integer activeUserId = activeUserIds.get(roleName); long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES); dumpOutputStream.write("name", RoleProto.NAME, roleName); dumpOutputStream.write("fallback_enabled", RoleProto.FALLBACK_ENABLED, fallbackEnabled); + if (activeUserId != null) { + dumpOutputStream.write("active_user_id", RoleProto.ACTIVE_USER_ID, activeUserId); + } int roleHoldersSize = roleHolders.size(); for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) { String roleHolder = roleHolders.valueAt(roleHoldersIndex); @@ -563,6 +587,12 @@ class RoleUserState { return new ArraySet<>(mFallbackEnabledRoles); } + @GuardedBy("mLock") + @NonNull + private ArrayMap snapshotActiveUserIds() { + return new ArrayMap<>(mActiveUserIds); + } + /** * Destroy this user state and delete the corresponding file. Any pending writes to the file * will be cancelled, and any future interaction with this state will throw an exception. diff --git a/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/service/java/com/android/role/persistence/RolesPersistenceImpl.java index 220a8440b..8382d3632 100644 --- a/service/java/com/android/role/persistence/RolesPersistenceImpl.java +++ b/service/java/com/android/role/persistence/RolesPersistenceImpl.java @@ -67,6 +67,7 @@ public class RolesPersistenceImpl implements RolesPersistence { private static final String ATTRIBUTE_VERSION = "version"; private static final String ATTRIBUTE_NAME = "name"; private static final String ATTRIBUTE_FALLBACK_ENABLED = "fallbackEnabled"; + private static final String ATTRIBUTE_ACTIVE_USER_ID = "activeUserId"; private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash"; @VisibleForTesting @@ -144,6 +145,7 @@ public class RolesPersistenceImpl implements RolesPersistence { Map> roles = new ArrayMap<>(); Set fallbackEnabledRoles = new ArraySet<>(); + Map activeUserIds = new ArrayMap<>(); int type; int depth; int innerDepth = parser.getDepth() + 1; @@ -159,12 +161,23 @@ public class RolesPersistenceImpl implements RolesPersistence { if (Boolean.parseBoolean(fallbackEnabled)) { fallbackEnabledRoles.add(roleName); } + if (com.android.permission.flags.Flags.crossUserRoleEnabled()) { + String activeUserId = parser.getAttributeValue(null, ATTRIBUTE_ACTIVE_USER_ID); + if (activeUserId != null) { + activeUserIds.put(roleName, Integer.parseInt(activeUserId)); + } + } Set roleHolders = parseRoleHolders(parser); roles.put(roleName, roleHolders); } } - return new RolesState(version, packagesHash, roles, fallbackEnabledRoles); + if (com.android.permission.flags.Flags.crossUserRoleEnabled()) { + return new RolesState(version, packagesHash, roles, fallbackEnabledRoles, + activeUserIds); + } else { + return new RolesState(version, packagesHash, roles, fallbackEnabledRoles); + } } @NonNull @@ -244,15 +257,22 @@ public class RolesPersistenceImpl implements RolesPersistence { } Set fallbackEnabledRoles = roles.getFallbackEnabledRoles(); + Map activeUserIds = roles.getActiveUserIds(); for (Map.Entry> entry : roles.getRoles().entrySet()) { String roleName = entry.getKey(); Set roleHolders = entry.getValue(); boolean isFallbackEnabled = fallbackEnabledRoles.contains(roleName); + Integer activeUserId = com.android.permission.flags.Flags.crossUserRoleEnabled() + ? activeUserIds.get(roleName) : null; serializer.startTag(null, TAG_ROLE); serializer.attribute(null, ATTRIBUTE_NAME, roleName); serializer.attribute(null, ATTRIBUTE_FALLBACK_ENABLED, Boolean.toString(isFallbackEnabled)); + if (activeUserId != null) { + serializer.attribute( + null, ATTRIBUTE_ACTIVE_USER_ID, Integer.toString(activeUserId)); + } serializeRoleHolders(serializer, roleHolders); serializer.endTag(null, TAG_ROLE); } diff --git a/service/java/com/android/role/persistence/RolesState.java b/service/java/com/android/role/persistence/RolesState.java index a189dd4c2..f1b3d8dfa 100644 --- a/service/java/com/android/role/persistence/RolesState.java +++ b/service/java/com/android/role/persistence/RolesState.java @@ -23,12 +23,13 @@ import android.annotation.SystemApi; import android.annotation.SystemApi.Client; import android.permission.flags.Flags; +import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; /** - * State of all roles. + * State of all roles for a user. * * TODO(b/147914847): Remove @hide when it becomes the default. * @hide @@ -58,6 +59,12 @@ public final class RolesState { @NonNull private final Set mFallbackEnabledRoles; + /** + * The active users for cross user roles. + */ + @NonNull + private final Map mActiveUserIds; + /** * Create a new instance of this class. * @@ -81,10 +88,27 @@ public final class RolesState { @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) public RolesState(int version, @Nullable String packagesHash, @NonNull Map> roles, @NonNull Set fallbackEnabledRoles) { + this(version, packagesHash, roles, fallbackEnabledRoles, Collections.emptyMap()); + } + + /** + * Create a new instance of this class. + * + * @param version the version of the roles + * @param packagesHash the hash of all packages in the system + * @param roles the roles + * @param fallbackEnabledRoles the roles with fallback enabled + * @param activeUserIds the active users for cross user roles + * @hide + */ + public RolesState(int version, @Nullable String packagesHash, + @NonNull Map> roles, @NonNull Set fallbackEnabledRoles, + @NonNull Map activeUserIds) { mVersion = version; mPackagesHash = packagesHash; mRoles = roles; mFallbackEnabledRoles = fallbackEnabledRoles; + mActiveUserIds = activeUserIds; } /** @@ -127,6 +151,17 @@ public final class RolesState { return mFallbackEnabledRoles; } + /** + * Get the active users for cross user roles. + * + * @return active users for cross user roles + * @hide + */ + @NonNull + public Map getActiveUserIds() { + return mActiveUserIds; + } + @Override public boolean equals(Object object) { if (this == object) { @@ -139,11 +174,12 @@ public final class RolesState { return mVersion == that.mVersion && Objects.equals(mPackagesHash, that.mPackagesHash) && Objects.equals(mRoles, that.mRoles) - && Objects.equals(mFallbackEnabledRoles, that.mFallbackEnabledRoles); + && Objects.equals(mFallbackEnabledRoles, that.mFallbackEnabledRoles) + && Objects.equals(mActiveUserIds, that.mActiveUserIds); } @Override public int hashCode() { - return Objects.hash(mVersion, mPackagesHash, mRoles, mFallbackEnabledRoles); + return Objects.hash(mVersion, mPackagesHash, mRoles, mFallbackEnabledRoles, mActiveUserIds); } } diff --git a/service/proto/role_service.proto b/service/proto/role_service.proto index f982ead5b..fb1866d83 100644 --- a/service/proto/role_service.proto +++ b/service/proto/role_service.proto @@ -56,4 +56,7 @@ message RoleProto { // Whether fallback holders are enabled for this role. optional bool fallback_enabled = 3; + + // The active user id of this cross user role. + optional int32 active_user_id = 4; } diff --git a/tests/apex/Android.bp b/tests/apex/Android.bp index 18f1bea75..9dfbdf589 100644 --- a/tests/apex/Android.bp +++ b/tests/apex/Android.bp @@ -31,6 +31,8 @@ android_test { "androidx.test.rules", "androidx.test.ext.junit", "androidx.test.ext.truth", + "com.android.permission.flags-aconfig-java", + "flag-junit", "mockito-target-extended-minus-junit4", ], jni_libs: [ diff --git a/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt b/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt index 6500b3926..e9c93a33a 100644 --- a/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt +++ b/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt @@ -20,12 +20,18 @@ import android.content.ApexEnvironment import android.content.Context import android.os.Process import android.os.UserHandle +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.test.platform.app.InstrumentationRegistry import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession +import com.android.permission.flags.Flags import com.google.common.truth.Truth.assertThat import java.io.File import org.junit.After +import org.junit.Assume.assumeFalse import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -49,11 +55,22 @@ class RolesPersistenceTest { private val persistence = RolesPersistenceImpl {} private val defaultRoles = mapOf(ROLE_NAME to setOf(HOLDER_1, HOLDER_2)) + private val activeUserIds = mapOf(ROLE_NAME to USER_ID) private val stateVersionUndefined = RolesState(VERSION_UNDEFINED, PACKAGE_HASH, defaultRoles) private val stateVersionFallbackMigrated = RolesState(VERSION_FALLBACK_MIGRATED, PACKAGE_HASH, defaultRoles, setOf(ROLE_NAME)) + private val stateVersionActiveUserIds = + RolesState( + VERSION_ACTIVE_USER_IDS, + PACKAGE_HASH, + defaultRoles, + setOf(ROLE_NAME), + activeUserIds, + ) private val user = Process.myUserHandle() + @get:Rule val flagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + @Before fun setUp() { createMockDataDirectory() @@ -84,16 +101,41 @@ class RolesPersistenceTest { mockitoSession.finishMocking() } + @RequiresFlagsDisabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) @Test fun testWriteRead() { + assumeFalse(stateVersion == StateVersion.VERSION_ACTIVE_USER_IDS) persistence.writeForUser(state, user) val persistedState = persistence.readForUser(user) assertThat(persistedState).isEqualTo(state) } + @RequiresFlagsEnabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + fun testWriteRead_supportsActiveUser() { + persistence.writeForUser(state, user) + val persistedState = persistence.readForUser(user) + + assertThat(persistedState).isEqualTo(state) + } + + @RequiresFlagsDisabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) @Test fun testWriteCorruptReadFromReserveCopy() { + assumeFalse(stateVersion == StateVersion.VERSION_ACTIVE_USER_IDS) + persistence.writeForUser(state, user) + // Corrupt the primary file. + RolesPersistenceImpl.getFile(user) + .writeText(" stateVersionUndefined StateVersion.VERSION_FALLBACK_MIGRATED -> stateVersionFallbackMigrated + StateVersion.VERSION_ACTIVE_USER_IDS -> stateVersionActiveUserIds } enum class StateVersion { VERSION_UNDEFINED, - VERSION_FALLBACK_MIGRATED + VERSION_FALLBACK_MIGRATED, + VERSION_ACTIVE_USER_IDS, } companion object { @@ -130,10 +174,12 @@ class RolesPersistenceTest { private const val VERSION_UNDEFINED = -1 private const val VERSION_FALLBACK_MIGRATED = 1 + private const val VERSION_ACTIVE_USER_IDS = 2 private const val APEX_MODULE_NAME = "com.android.permission" private const val PACKAGE_HASH = "packagesHash" private const val ROLE_NAME = "roleName" private const val HOLDER_1 = "holder1" private const val HOLDER_2 = "holder2" + private const val USER_ID = 10 } } -- cgit v1.2.3-59-g8ed1b From 7d29232bfc401dc3bcdeb86f2c788afca66c9afc Mon Sep 17 00:00:00 2001 From: Mengqi Yang Date: Mon, 11 Nov 2024 15:44:47 +0000 Subject: Update the permission CTS test The permissions are added in ag/29596663 Test: cts tests Flag: android.permission.flags.health_connect_backup_restore_permission_enabled Bug: b/328188870 Change-Id: Ic57fb54b048a731555d5100d5252d4121f8c278a Relnote: adding new permissions for HC backup & restore --- .../permissionpolicy/res/raw/android_manifest.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index d30931c3f..6efe6b8bb 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8139,6 +8139,26 @@ android:protectionLevel="signature|knownSigner" android:knownCerts="@array/config_healthConnectMigrationKnownSigners" /> + + + + + + +

Protection Level: signature|privileged|appop --> + android:protectionLevel="signature|privileged|appop" + android:featureFlag="com.android.settingslib.flags.write_system_preference_permission_enabled" /> -- cgit v1.2.3-59-g8ed1b From f3a1ca0252945e285c7d7a263ffe86283ce85310 Mon Sep 17 00:00:00 2001 From: Matt Gilbride Date: Wed, 13 Nov 2024 16:34:03 +0000 Subject: Add android.permission.DYNAMIC_INSTRUMENTATION Change I1f2dc3780d1bd2a682c1fd3ec41e5c8d73e96fc2 introduced this permission to the core platform. Add the corresponding permission for permission CTS tests. Bug: 372925025 Test: TH Flag: com.android.art.flags.executable_method_file_offsets Change-Id: I699feac1fbbaca7bd3642bd32d1b6516b93ad5d8 LOW_COVERAGE_REASON=TEST_ONLY --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 6efe6b8bb..272035dd8 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8404,6 +8404,16 @@ android:protectionLevel="signature|privileged" android:featureFlag="com.android.tradeinmode.flags.enable_trade_in_mode" /> + + + + + + + + + + + + + + Date: Fri, 1 Nov 2024 12:25:23 -0600 Subject: Update policy for new permissions for applying and listening to picture profiles Bug: 337330263 Test: build Flag: android.media.tv.flags.apply_picture_profiles Relnote: N/A LOW_COVERAGE_REASON=NON_CODE_ONLY Change-Id: Ib3ff5a33688f431a4dc42b04df536613e6c2e4aa --- .../permissionpolicy/res/raw/android_manifest.xml | 68 +++++++++++++++------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 272035dd8..4db948e61 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -4091,6 +4091,52 @@ + + + + + + + + + + + + + + + + + @@ -8374,28 +8420,6 @@ android:protectionLevel="internal" android:featureFlag="android.content.pm.verification_service" /> - - - - - - + android:protectionLevel="signature|installer" + android:featureFlag="!android.content.pm.sdk_dependency_installer" /> + + + + + + + + + -- cgit v1.2.3-59-g8ed1b From ee9b513d016443ec6b25492916d7fbe7615c0bdb Mon Sep 17 00:00:00 2001 From: Liefu Liu Date: Wed, 13 Nov 2024 14:56:21 -0800 Subject: CTS test of updating the SET_DEFAULT_ACCOUNT_FOR_CONTACTS's permission protection level to knownSigner. Bug: 378012462 Test: Tested on device Flag: android.provider.new_default_account_api_enabled Relnote: N/A Change-Id: I113a34313b6817d9b38f36707d8c875d6b4f4884 LOW_COVERAGE_REASON=TEST_ONLY --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 6efe6b8bb..c35e7f4c4 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -898,13 +898,26 @@ android:featureFlag="android.provider.user_keys" /> + android:protectionLevel="internal|role" + android:featureFlag="!android.provider.new_default_account_api_enabled"/> + + + -- cgit v1.2.3-59-g8ed1b From 24f197c6d15e9b9d3905d0b5c520489161e939ae Mon Sep 17 00:00:00 2001 From: Biswarup Pal Date: Wed, 30 Oct 2024 14:05:50 +0000 Subject: Allow host permission dialogs to show on virtual devices Relnote: Allow host permission dialogs to show on virtual devices Test: atest DeviceAwarePermissionGrantTest Bug: 371173672 Flag: android.permission.flags.allow_host_permission_dialogs_on_virtual_devices Change-Id: I0126de39b5533303573a2126a73fb66de9a07cb7 --- .../permission/ui/GrantPermissionsActivity.java | 36 ++++++++++++-------- .../ui/model/GrantPermissionsViewModel.kt | 25 ++++++++++++-- .../cts/DeviceAwarePermissionGrantTest.kt | 39 +++++++++++++++++++--- 3 files changed, 80 insertions(+), 20 deletions(-) (limited to 'tests') diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java index a4f629d80..c1479caf2 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java @@ -46,7 +46,6 @@ import android.app.KeyguardManager; import android.app.ecm.EnhancedConfirmationManager; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -195,7 +194,7 @@ public class GrantPermissionsActivity extends SettingsActivity /** A list of permissions requested on an app's behalf by the system. Usually Implicitly * requested, although this isn't necessarily always the case. */ - private List mSystemRequestedPermissions = new ArrayList<>(); + private final List mSystemRequestedPermissions = new ArrayList<>(); /** A copy of the list of permissions originally requested in the intent to this activity */ private String[] mOriginalRequestedPermissions = new String[0]; @@ -209,7 +208,7 @@ public class GrantPermissionsActivity extends SettingsActivity * A list of other GrantPermissionActivities for the same package which passed their list of * permissions to this one. They need to be informed when this activity finishes. */ - private List mFollowerActivities = new ArrayList<>(); + private final List mFollowerActivities = new ArrayList<>(); /** Whether this activity has asked another GrantPermissionsActivity to show on its behalf */ private boolean mDelegated; @@ -235,7 +234,7 @@ public class GrantPermissionsActivity extends SettingsActivity private PackageManager mPackageManager; - private ActivityResultLauncher mShowWarningDialog = + private final ActivityResultLauncher mShowWarningDialog = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { @@ -284,7 +283,7 @@ public class GrantPermissionsActivity extends SettingsActivity return; } try { - PackageInfo packageInfo = mPackageManager.getPackageInfo(mTargetPackage, 0); + mPackageManager.getPackageInfo(mTargetPackage, 0); } catch (PackageManager.NameNotFoundException e) { Log.e(LOG_TAG, "Unable to get package info for the calling package.", e); finishAfterTransition(); @@ -314,20 +313,23 @@ public class GrantPermissionsActivity extends SettingsActivity .getPackageManager(); } - // When the dialog is streamed to a remote device, verify requested permissions are all - // device aware and target device is the same as the remote device. Otherwise show a - // warning dialog. + // 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, + // device-aware permissions will use virtual device id and non-device aware permissions + // will use default device id for granting. If flag is not enabled, we would show a + // warning dialog for this use case. if (getDeviceId() != ContextCompat.DEVICE_ID_DEFAULT) { boolean showWarningDialog = mTargetDeviceId != getDeviceId(); for (String permission : mRequestedPermissions) { - if (!MultiDeviceUtils.isPermissionDeviceAware( - getApplicationContext(), mTargetDeviceId, permission)) { + if (!MultiDeviceUtils.isPermissionDeviceAware(getApplicationContext(), + mTargetDeviceId, permission)) { showWarningDialog = true; + break; } } - if (showWarningDialog) { + if (showWarningDialog && !Flags.allowHostPermissionDialogsOnVirtualDevices()) { mShowWarningDialog.launch( new Intent(this, PermissionDialogStreamingBlockedActivity.class)); return; @@ -1115,9 +1117,17 @@ 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++) { - grantResults[i] = - mPackageManager.checkPermission(resultPermissions[i], mTargetPackage); + String permission = resultPermissions[i]; + PackageManager pm = MultiDeviceUtils.isPermissionDeviceAware( + getApplicationContext(), mTargetDeviceId, permission) + ? targetDevicePackageManager : defaultDevicePackageManager; + grantResults[i] = pm.checkPermission(resultPermissions[i], mTargetPackage); } } else { grantResults = new int[0]; diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt index 0a01929e6..1e5b96c2e 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt @@ -29,6 +29,7 @@ import android.annotation.SuppressLint import android.app.Activity import android.app.Application import android.app.admin.DevicePolicyManager +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED @@ -41,6 +42,8 @@ import android.os.Build import android.os.Bundle import android.os.Process import android.permission.PermissionManager +import android.permission.flags.Flags +import android.util.ArrayMap import android.util.Log import androidx.core.util.Consumer import androidx.lifecycle.ViewModel @@ -116,6 +119,7 @@ import com.android.permissioncontroller.permission.utils.SafetyNetLogger import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils +import com.android.permissioncontroller.permission.utils.v35.MultiDeviceUtils.isPermissionDeviceAware /** * ViewModel for the GrantPermissionsActivity. Tracks all permission groups that are affected by the @@ -153,6 +157,21 @@ class GrantPermissionsViewModel( } else { null } + private val permissionGroupToDeviceIdMap: Map = + if (SdkLevel.isAtLeastV() && Flags.allowHostPermissionDialogsOnVirtualDevices()) { + requestedPermissions + .filter({ PermissionMapping.getGroupOfPlatformPermission(it) != null }) + .associateBy({ PermissionMapping.getGroupOfPlatformPermission(it)!! }, { + if (isPermissionDeviceAware( + app.applicationContext, + deviceId, + it + ) + ) deviceId else Context.DEVICE_ID_DEFAULT + }) + } else { + ArrayMap() + } private val dpm = app.getSystemService(DevicePolicyManager::class.java)!! private val permissionPolicy = dpm.getPermissionPolicy(null) private val groupStates = mutableMapOf() @@ -314,7 +333,8 @@ class GrantPermissionsViewModel( } val getLiveDataFun = { groupName: String -> - LightAppPermGroupLiveData[packageName, groupName, user, deviceId] + LightAppPermGroupLiveData[packageName, groupName, user, + permissionGroupToDeviceIdMap.get(groupName) ?: deviceId] } setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun) } @@ -398,7 +418,8 @@ class GrantPermissionsViewModel( safetyLabel, groupState.group.permGroupName ), - deviceId + permissionGroupToDeviceIdMap.get(groupState.group.permGroupName) + ?: deviceId ) ) } diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt index f0a0e3fc1..687234582 100644 --- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt +++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt @@ -21,6 +21,7 @@ import android.app.Instrumentation import android.companion.virtual.VirtualDeviceManager 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_CAMERA import android.content.ComponentName import android.content.Intent @@ -39,7 +40,9 @@ 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 import android.virtualdevice.cts.common.VirtualDeviceRule import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -47,7 +50,6 @@ import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import com.android.compatibility.common.util.SystemUtil -import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit @@ -146,6 +148,7 @@ class DeviceAwarePermissionGrantTest { 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() { requestPermissionOnDevice(virtualDisplay.display.displayId, DEVICE_ID_DEFAULT) @@ -154,6 +157,32 @@ class DeviceAwarePermissionGrantTest { waitFindObject(By.displayId(displayId).textContains("Permission request suppressed")) } + @RequiresFlagsEnabled( + Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, + Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES + ) + @Test + fun onRemoteDevice_requestPermissionForHostDevice_shouldGrantPermission() { + // 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), + expectPermissionGrantedOnDefaultDevice = true, + expectPermissionGrantedOnRemoteDevice = false + ) + } + @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED @@ -199,7 +228,7 @@ class DeviceAwarePermissionGrantTest { TestConstants.PERMISSION_RESULT_KEY_PERMISSIONS ) ) - .isEqualTo(arrayOf(DEVICE_AWARE_PERMISSION)) + .isEqualTo(arrayOf(PERMISSION)) assertThat( grantPermissionResult.getIntArray(TestConstants.PERMISSION_RESULT_KEY_GRANT_RESULTS) ) @@ -237,7 +266,7 @@ class DeviceAwarePermissionGrantTest { private fun assertPermissionMessageContainsDeviceName(displayId: Int, deviceName: String) { waitFindObject(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) val text = findTextForView(By.displayId(displayId).res(PERMISSION_MESSAGE_ID)) - Truth.assertThat(text).contains(deviceName) + assertThat(text).contains(deviceName) } private fun assertAppHasPermissionForDevice(deviceId: Int, expectPermissionGranted: Boolean) { @@ -245,7 +274,7 @@ class DeviceAwarePermissionGrantTest { defaultDeviceContext .createDeviceContext(deviceId) .packageManager - .checkPermission(DEVICE_AWARE_PERMISSION, APP_PACKAGE_NAME) + .checkPermission(PERMISSION, APP_PACKAGE_NAME) if (expectPermissionGranted) { Assert.assertEquals(PackageManager.PERMISSION_GRANTED, checkPermissionResult) @@ -269,7 +298,7 @@ class DeviceAwarePermissionGrantTest { "com.android.permissioncontroller:id/permission_allow_foreground_only_button" const val DEVICE_ID_DEFAULT = 0 const val PERSISTENT_DEVICE_ID_DEFAULT = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT - const val DEVICE_AWARE_PERMISSION = Manifest.permission.CAMERA + const val PERMISSION = Manifest.permission.CAMERA const val TIMEOUT = 5000L private const val DISPLAY_HEIGHT = 1920 private const val DISPLAY_WIDTH = 1080 -- cgit v1.2.3-59-g8ed1b From 3018ab968013866716b76219b4968c173279b1d9 Mon Sep 17 00:00:00 2001 From: Wenhao Wang Date: Sat, 16 Nov 2024 20:55:30 -0800 Subject: [ID] Replace "forensic" with "intrusion detection" Improve terminology: Use "intrusion detection" instead of "forensic" for accuracy The following 3 permissions are renamed: READ_FORENSIC_STATE -> READ_INTRUSION_DETECTION_STATE MANAGE_FORENSIC_STATE -> MANAGE_INTRUSION_DETECTION_STATE BIND_FORENSIC_BACKUP_SERVICE -> BIND_INTRUSION_DETECTION_BACKUP_SERVICE Bug: 365994454 Test: atest IntrusionDetectionServiceTest Test: atest IntrusionDetectionManagerTest Flag: android.security.afl_api Ignore-AOSP-First: security feature LOW_COVERAGE_REASON=TEST_ONLY Relnote: Add test for new Forensic permissions Change-Id: I60088c80385e79deac5145e052aeff17bcaf6053 --- .../permissionpolicy/res/raw/android_manifest.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 34190e459..3b97352d7 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -3962,36 +3962,36 @@ android:protectionLevel="normal" android:featureFlag="android.security.aapm_api"/> - - - - - - - - - + Date: Tue, 29 Oct 2024 19:39:15 +0000 Subject: Add SecureLockDevice permission to manifest Adds MANAGE_SECURE_LOCK_DEVICE permission to manifest Bug: 373422357 Flag: android.security.secure_lockdown Test: N/A Relnote: N/A Change-Id: I3b80d1ccad62f9eea07a09ddb49fc98bb9765802 --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 34190e459..21d163588 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -5685,6 +5685,17 @@ + + + + + -- cgit v1.2.3-59-g8ed1b From 58f82b3ab3dbed5e82090b876b86961ada62fd9a Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Tue, 29 Oct 2024 15:42:54 +0000 Subject: Add hidden SystemAPI permissions required for copyAccount and removeAccount Give the device policy management role the copy and remove account permissions Bug: 375382324 Test: atest PermissionPolicyTest Relnote: N/A Flag: android.app.admin.flags.split_create_managed_profile_enabled Change-Id: I558608eb4359a396a554cacff261c35d0baef463 LOW_COVERAGE_REASON=NON_CODE_ONLY --- PermissionController/res/xml/roles.xml | 8 ++++++++ tests/cts/permissionpolicy/res/raw/android_manifest.xml | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'tests') diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 64642f403..6864506f0 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -720,6 +720,10 @@ featureFlag="android.app.appfunctions.flags.Flags.enableAppFunctionManager" /> + + @@ -1480,6 +1484,10 @@ + + diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 6efe6b8bb..067364ac4 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -2574,6 +2574,22 @@ android:label="@string/permlab_getAccounts" /> + + + + + + Date: Mon, 18 Nov 2024 20:19:18 +0000 Subject: Update minSdkVersion=Baklava for health permissions background permission test When we enabled the flag, verifyBackgroundPropertiesForHealthPermissions() CTS test on V image fails. We're able to reproduce this locally, and we found the reason is: the V-image does not have this flag(flag not enabled on device), but the test is built from head where the flag is enabled(flag enabled for test). To fix this, we need to update the minSdkVerision so that it does not run on a device that has inconsistent flag values. Test: https://android-build.corp.google.com/builds/abtd/run/L10800030007846189 Relnote: Granular health permission phase one Bug: 364638912 Bug: 379377663 Flag: android.permission.flags.replace_body_sensor_permission_enabled LOW_COVERAGE_REASON=TEST_ONLY Change-Id: I74c431778d0069bd40f9c4857b4a72521a511c92 --- .../src/android/permission/cts/BackgroundPermissionsTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java index fcdccd87a..f4bed4ada 100644 --- a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java +++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java @@ -95,8 +95,7 @@ public class BackgroundPermissionsTest { verifyBackgroundPermissionsProperties("android"); } - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, - codeName = "VanillaIceCream") + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @RequiresFlagsEnabled({Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED}) @Test @AppModeFull(reason = "Instant apps cannot read properties of other packages") -- cgit v1.2.3-59-g8ed1b From 9cf2aa0773312425b2fe37ef1d7847b2718aea57 Mon Sep 17 00:00:00 2001 From: Song Chun Fan Date: Mon, 18 Nov 2024 10:12:45 -0800 Subject: Revert "Add missing permission declaration to fix PermissionPolicyTest" This reverts commit 93d445a8b687d86d1b79c5744d9a8006cde36e63. BUG: 374797861 Test: n/a FLAG: android.content.pm.verification_service Relnote: revert BIND_VERIFICATION_AGENT permission LOW_COVERAGE_REASON=NON_CODE_ONLY Change-Id: I0ac353c71bb6214142a99afaed923da96f98dd57 --- tests/cts/permissionpolicy/res/raw/android_manifest.xml | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'tests') diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index 34190e459..76ac7d92b 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8475,18 +8475,6 @@ android:protectionLevel="signature|privileged" android:featureFlag="android.content.pm.verification_service"/> - - - - - + + diff --git a/PermissionController/tests/inprocess/Android.bp b/PermissionController/tests/inprocess/Android.bp index 60b35e80f..4cd9e0e6f 100644 --- a/PermissionController/tests/inprocess/Android.bp +++ b/PermissionController/tests/inprocess/Android.bp @@ -50,6 +50,9 @@ android_test { "compatibility-device-util-axt", "kotlin-test", "permission-test-util-lib", + // This may result in two flag libs being included. This should only be used for Flag + //string referencing for test annotations. + "com.android.permission.flags-aconfig-java-export", ], data: [ diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt index e15887576..3222eeda8 100644 --- a/framework-s/api/system-current.txt +++ b/framework-s/api/system-current.txt @@ -37,6 +37,7 @@ package android.app.role { method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); + method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @Nullable @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, android.Manifest.permission.MANAGE_ROLE_HOLDERS, android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, conditional=true) public android.os.UserHandle getActiveUserForRole(@NonNull String); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) public String getDefaultApplication(@NonNull String); method @Deprecated @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List getHeldRolesFromController(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List getRoleHolders(@NonNull String); @@ -48,6 +49,7 @@ package android.app.role { method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String); + method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, android.Manifest.permission.MANAGE_ROLE_HOLDERS, android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, conditional=true) public void setActiveUserForRole(@NonNull String, @NonNull android.os.UserHandle, int); method @RequiresPermission(android.Manifest.permission.BYPASS_ROLE_QUALIFICATION) public void setBypassingRoleQualification(boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) public void setDefaultApplication(@NonNull String, @Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("android.permission.flags.system_server_role_controller_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleFallbackEnabled(@NonNull String, boolean); @@ -55,6 +57,7 @@ package android.app.role { field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1 field public static final String ROLE_DEVICE_POLICY_MANAGEMENT = "android.app.role.DEVICE_POLICY_MANAGEMENT"; field public static final String ROLE_FINANCED_DEVICE_KIOSK = "android.app.role.FINANCED_DEVICE_KIOSK"; + field @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") public static final String ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY = "android.app.role.RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY"; field public static final String ROLE_SYSTEM_ACTIVITY_RECOGNIZER = "android.app.role.SYSTEM_ACTIVITY_RECOGNIZER"; field public static final String ROLE_SYSTEM_CALL_STREAMING = "android.app.role.SYSTEM_CALL_STREAMING"; field public static final String ROLE_SYSTEM_SUPERVISION = "android.app.role.SYSTEM_SUPERVISION"; diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl index 522967630..cd0079e08 100644 --- a/framework-s/java/android/app/role/IRoleManager.aidl +++ b/framework-s/java/android/app/role/IRoleManager.aidl @@ -45,6 +45,10 @@ interface IRoleManager { void setDefaultApplicationAsUser(in String roleName, in String packageName, int flags, int userId, in RemoteCallback callback); + int getActiveUserForRoleAsUser(in String roleName, int userId); + + void setActiveUserForRoleAsUser(in String roleName, int activeUserId, int flags, int userId); + void addOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, int userId); void removeOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java index 4b8c9b388..6f62fdd76 100644 --- a/framework-s/java/android/app/role/RoleManager.java +++ b/framework-s/java/android/app/role/RoleManager.java @@ -40,6 +40,7 @@ import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.permission.flags.Flags; +import android.permission.internal.compat.UserHandleCompat; import android.util.ArrayMap; import android.util.SparseArray; @@ -210,6 +211,16 @@ public final class RoleManager { public static final String ROLE_SYSTEM_CALL_STREAMING = "android.app.role.SYSTEM_CALL_STREAMING"; + /** + * The name of the role used for testing cross-user roles. + * + * @hide + */ + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @SystemApi + public static final String ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY = + "android.app.role.RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY"; + /** * @hide */ @@ -574,6 +585,87 @@ public final class RoleManager { } } + /** + * Get the {@link UserHandle} of the user who that is the active user for the specified role. + *

+ * Only profile-group exclusive roles can be used with this method, and they will + * have one active user within a profile group. + *

+ * Note: Using this API requires holding + * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of + * {@code android.permission.MANAGE_ROLE_HOLDERS} or + * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. + * + * @param roleName the name of the role to get the active user for + * + * @return a {@link UserHandle} of the active user for the specified role + * + * @see #setActiveUserForRole(String, UserHandle, int) + * + * @hide + */ + @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.MANAGE_ROLE_HOLDERS, + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, + conditional = true) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Nullable + public UserHandle getActiveUserForRole(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + int userId = mService.getActiveUserForRoleAsUser(roleName, + mContext.getUser().getIdentifier()); + return userId == UserHandleCompat.USER_NULL ? null : UserHandle.of(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set a specific user as active user for a role. + *

+ * Only profile-group exclusive roles can be used with this method, and they will have + * one active user within a profile group. + *

+ * Note: Using this API requires holding + * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of + * {@code android.permission.MANAGE_ROLE_HOLDERS} or + * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. + * + * @param roleName the name of the role to set the active user for + * @param user the user to set as active user for specified role + * @param flags optional behavior flags + * + * @see #getActiveUserForRole(String) + * + * @hide + */ + @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.MANAGE_ROLE_HOLDERS, + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, + conditional = true) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + // The user handle parameter is a value to be set by this method, while the context user of the + // operation is indeed read from the context + @SuppressLint("UserHandle") + public void setActiveUserForRole( + @NonNull String roleName, @NonNull UserHandle user, @ManageHoldersFlags int flags) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Objects.requireNonNull(user, "user cannot be null"); + try { + mService.setActiveUserForRoleAsUser(roleName, user.getIdentifier(), flags, + mContext.getUser().getIdentifier()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @NonNull private static RemoteCallback createRemoteCallback(@NonNull Executor executor, @NonNull Consumer callback) { diff --git a/service/java/com/android/ecm/EnhancedConfirmationService.java b/service/java/com/android/ecm/EnhancedConfirmationService.java index 708884e85..73f66609e 100644 --- a/service/java/com/android/ecm/EnhancedConfirmationService.java +++ b/service/java/com/android/ecm/EnhancedConfirmationService.java @@ -228,7 +228,8 @@ public class EnhancedConfirmationService extends SystemService { } private void enforcePermissions(@NonNull String methodName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, methodName, mContext); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, methodName, mContext); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES, methodName); } diff --git a/service/java/com/android/permission/util/UserUtils.java b/service/java/com/android/permission/util/UserUtils.java index 986b5af5b..c69afb199 100644 --- a/service/java/com/android/permission/util/UserUtils.java +++ b/service/java/com/android/permission/util/UserUtils.java @@ -17,9 +17,10 @@ package com.android.permission.util; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.admin.DevicePolicyManager; import android.content.Context; -import android.content.pm.PackageManager; import android.os.Binder; import android.os.Process; import android.os.UserHandle; @@ -30,8 +31,8 @@ import com.android.internal.util.Preconditions; import com.android.modules.utils.build.SdkLevel; import com.android.permission.flags.Flags; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; /** Utility class to deal with Android users. */ public final class UserUtils { @@ -42,11 +43,12 @@ public final class UserUtils { public static void enforceCrossUserPermission( @UserIdInt int userId, boolean allowAll, + boolean enforceForProfileGroup, @NonNull String message, @NonNull Context context) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandleCompat.getUserId(callingUid); - if (userId == callingUserId) { + if (userId == callingUserId && !enforceForProfileGroup) { return; } Preconditions.checkArgument( @@ -55,13 +57,40 @@ public final class UserUtils { "Invalid user " + userId); context.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); - if (callingUid != Process.SHELL_UID || userId < UserHandleCompat.USER_SYSTEM) { + if (callingUid != Process.SHELL_UID || userId == UserHandleCompat.USER_ALL) { return; } + + if (enforceForProfileGroup) { + DevicePolicyManager devicePolicyManager = + context.getSystemService(DevicePolicyManager.class); + if (!devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()) { + // For profileGroup exclusive roles users on BYOD are free to choose personal o + // work profile app regardless of DISALLOW_DEBUGGING_FEATURES + return; + } + + Context userContext = UserUtils.getUserContext(userId, context); + List profiles = getUserProfiles(userContext, true); + final int profilesSize = profiles.size(); + for (int i = 0; i < profilesSize; i++) { + int profileId = profiles.get(i).getIdentifier(); + if (profileId == callingUserId) { + continue; + } + enforceShellRestriction(profileId, context); + } + } else { + enforceShellRestriction(userId, context); + } + } + + private static void enforceShellRestriction(int userId, @NonNull Context context) { UserManager userManager = context.getSystemService(UserManager.class); if (userManager.hasUserRestrictionForUser( UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.of(userId))) { - throw new SecurityException("Shell does not have permission to access user " + userId); + throw new SecurityException( + "Shell does not have permission to access user " + userId); } } @@ -86,18 +115,54 @@ public final class UserUtils { /** Returns all the enabled user profiles on the device. */ @NonNull public static List getUserProfiles(@NonNull Context context) { + return getUserProfiles(context, false); + } + + /** + * Returns all the enabled user profiles on the device + * + * @param context the {@link Context} + * @param excludePrivate {@code true} to exclude private profiles from returned list of users + */ + @NonNull + public static List getUserProfiles(@NonNull Context context, + boolean excludePrivate) { UserManager userManager = context.getSystemService(UserManager.class); // This call requires the QUERY_USERS permission. final long identity = Binder.clearCallingIdentity(); try { - return userManager.getUserProfiles(); + List profiles = userManager.getUserProfiles(); + if (!excludePrivate) { + return profiles; + } + List filteredProfiles = new ArrayList<>(); + final int profilesSize = profiles.size(); + for (int i = 0; i < profilesSize; i++) { + UserHandle user = profiles.get(i); + if (!isPrivateProfile(user.getIdentifier(), context)) { + filteredProfiles.add(user); + } + } + return filteredProfiles; } finally { Binder.restoreCallingIdentity(identity); } } + /** + * Returns the parent of a given user, or userId if it has no parent (e.g. it is the primary + * profile) + */ + @UserIdInt + public static int getProfileParentIdOrSelf(@UserIdInt int userId, @NonNull Context context) { + UserHandle profileParent = getProfileParent(userId, context); + // If profile parent userhandle is null, then original user id is the parent + return profileParent != null ? profileParent.getIdentifier() : userId; + } + /** Returns the parent of a given user. */ - public static UserHandle getProfileParent(@UserIdInt int userId, @NonNull Context context) { + @Nullable + private static UserHandle getProfileParent(@UserIdInt int userId, @NonNull Context context) { Context userContext = getUserContext(userId, context); UserManager userManager = userContext.getSystemService(UserManager.class); // This call requires the INTERACT_ACROSS_USERS permission. diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index c4316ff71..1145f273d 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -18,6 +18,7 @@ package com.android.role; import android.Manifest; import android.annotation.AnyThread; +import android.annotation.ChecksSdkIntAtLeast; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; @@ -45,8 +46,8 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; -import android.permission.internal.compat.UserHandleCompat; import android.permission.flags.Flags; +import android.permission.internal.compat.UserHandleCompat; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; @@ -69,6 +70,8 @@ import com.android.permission.util.ForegroundThread; import com.android.permission.util.PackageUtils; import com.android.permission.util.ThrottledRunnable; import com.android.permission.util.UserUtils; +import com.android.role.controller.model.Role; +import com.android.role.controller.model.Roles; import com.android.server.LocalManagerRegistry; import com.android.server.SystemService; import com.android.server.role.RoleServicePlatformHelper; @@ -77,6 +80,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -466,8 +470,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean isRoleAvailableAsUser(@NonNull String roleName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "isRoleAvailableAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "isRoleAvailableAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -483,7 +487,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @UserIdInt int userId) { mAppOpsManager.checkPackage(getCallingUid(), packageName); - UserUtils.enforceCrossUserPermission(userId, false, "isRoleHeldAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "isRoleHeldAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -502,8 +507,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @NonNull @Override public List getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "getRoleHoldersAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return Collections.emptyList(); @@ -525,8 +530,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - UserUtils.enforceCrossUserPermission(userId, false, "addRoleHolderAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "addRoleHolderAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return; @@ -546,8 +551,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - UserUtils.enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "removeRoleHolderAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return; @@ -568,8 +573,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void clearRoleHoldersAsUser(@NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - UserUtils.enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "clearRoleHoldersAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return; @@ -587,7 +592,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override @Nullable public String getDefaultApplicationAsUser(@NonNull String roleName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "getDefaultApplicationAsUser", + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "getDefaultApplicationAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -612,7 +618,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void setDefaultApplicationAsUser(@NonNull String roleName, @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - UserUtils.enforceCrossUserPermission(userId, false, "setDefaultApplicationAsUser", + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "setDefaultApplicationAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -634,11 +641,102 @@ public class RoleService extends SystemService implements RoleUserState.Callback } } + @Override + public int getActiveUserForRoleAsUser(@NonNull String roleName, @UserIdInt int userId) { + Preconditions.checkState(isProfileGroupExclusivityAvailable(), + "getActiveUserForRoleAsUser not available"); + enforceProfileGroupExclusiveRole(roleName); + + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ true, "getActiveUserForRole", getContext()); + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return UserHandleCompat.USER_NULL; + } + + enforceCallingOrSelfAnyPermissions(new String[] { + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, + Manifest.permission.MANAGE_ROLE_HOLDERS + }, "getActiveUserForRole"); + + int profileParentId = UserUtils.getProfileParentIdOrSelf(userId, getContext()); + RoleUserState userState = getOrCreateUserState(profileParentId); + return userState.getActiveUserForRole(roleName); + } + + @Override + public void setActiveUserForRoleAsUser(@NonNull String roleName, + @UserIdInt int activeUserId, @RoleManager.ManageHoldersFlags int flags, + @UserIdInt int userId) { + Preconditions.checkState(isProfileGroupExclusivityAvailable(), + "setActiveUserForRoleAsUser not available"); + enforceProfileGroupExclusiveRole(roleName); + + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ true, "setActiveUserForRole", getContext()); + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return; + } + if (!UserUtils.isUserExistent(activeUserId, getContext())) { + Log.e(LOG_TAG, "user " + activeUserId + " does not exist"); + return; + } + if (UserUtils.isPrivateProfile(activeUserId, getContext())) { + Log.e(LOG_TAG, "Cannot set private profile " + activeUserId + " as active user" + + " for role"); + return; + } + Context userContext = UserUtils.getUserContext(userId, getContext()); + List profiles = UserUtils.getUserProfiles(userContext, true); + if (!profiles.contains(UserHandle.of(activeUserId))) { + Log.e(LOG_TAG, "User " + activeUserId + " is not in the same profile-group as " + + userId); + return; + } + + enforceCallingOrSelfAnyPermissions(new String[] { + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, + Manifest.permission.MANAGE_ROLE_HOLDERS + }, "setDefaultApplicationAsUser"); + + int profileParentId = UserUtils.getProfileParentIdOrSelf(userId, getContext()); + RoleUserState userState = getOrCreateUserState(profileParentId); + + if (!userState.setActiveUserForRole(roleName, activeUserId)) { + Log.i(LOG_TAG, "User " + activeUserId + " is already the active user for role"); + return; + } + + final int profilesSize = profiles.size(); + for (int i = 0; i < profilesSize; i++) { + final AndroidFuture future = new AndroidFuture<>(); + final RemoteCallback callback = new RemoteCallback(result -> { + boolean successful = result != null; + if (successful) { + future.complete(null); + } else { + future.completeExceptionally(new RuntimeException()); + } + }); + int profilesUserId = profiles.get(i).getIdentifier(); + getOrCreateController(profilesUserId) + .onClearRoleHolders(roleName, flags, callback); + try { + future.get(5, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + Log.e(LOG_TAG, "Exception while clearing role holders for non-active" + + "user: " + profilesUserId, e); + } + } + } + @Override public void addOnRoleHoldersChangedListenerAsUser( @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, true, - "addOnRoleHoldersChangedListenerAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ true, + /* enforceForProfileGroup= */ false, "addOnRoleHoldersChangedListenerAsUser", + getContext()); if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -658,7 +756,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public void removeOnRoleHoldersChangedListenerAsUser( @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, true, + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ true, + /* enforceForProfileGroup= */ false, "removeOnRoleHoldersChangedListenerAsUser", getContext()); if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId, getContext())) { @@ -711,7 +810,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean isRoleFallbackEnabledAsUser(@NonNull String roleName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "isRoleFallbackEnabledAsUser", + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "isRoleFallbackEnabledAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -729,7 +829,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public void setRoleFallbackEnabledAsUser(@NonNull String roleName, boolean fallbackEnabled, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "setRoleFallbackEnabledAsUser", + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "setRoleFallbackEnabledAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -747,7 +848,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public void setRoleNamesFromControllerAsUser(@NonNull List roleNames, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "setRoleNamesFromControllerAsUser", + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "setRoleNamesFromControllerAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); @@ -766,8 +868,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean addRoleHolderFromControllerAsUser(@NonNull String roleName, @NonNull String packageName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, - "addRoleHolderFromControllerAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "addRoleHolderFromControllerAsUser", + getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -786,8 +889,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean removeRoleHolderFromControllerAsUser(@NonNull String roleName, @NonNull String packageName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, - "removeRoleHolderFromControllerAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "removeRoleHolderFromControllerAsUser", + getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -806,8 +910,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public List getHeldRolesFromControllerAsUser(@NonNull String packageName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, - "getHeldRolesFromControllerAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "getHeldRolesFromControllerAsUser", + getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return Collections.emptyList(); @@ -916,7 +1021,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public String getSmsRoleHolder(int userId) { final Context context = getContext(); - UserUtils.enforceCrossUserPermission(userId, false, "getSmsRoleHolder", context); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "getSmsRoleHolder", context); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return null; @@ -940,7 +1046,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public String getEmergencyRoleHolder(int userId) { final Context context = getContext(); - UserUtils.enforceCrossUserPermission(userId, false, "getEmergencyRoleHolder", context); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "getEmergencyRoleHolder", context); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return null; @@ -966,8 +1073,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser", - getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "isRoleVisibleAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -984,8 +1091,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public boolean isApplicationVisibleForRoleAsUser(@NonNull String roleName, @NonNull String packageName, @UserIdInt int userId) { - UserUtils.enforceCrossUserPermission(userId, false, - "isApplicationVisibleForRoleAsUser", getContext()); + UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, + /* enforceForProfileGroup= */ false, "isApplicationVisibleForRoleAsUser", + getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return false; @@ -1042,6 +1150,36 @@ public class RoleService extends SystemService implements RoleUserState.Callback return true; } } + + private void enforceCallingOrSelfAnyPermissions(@NonNull String[] permissions, + @NonNull String message) { + for (String permission : permissions) { + if (getContext().checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED) { + return; + } + } + + throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() + + " nor current process has at least one of" + Arrays.toString(permissions) + + "."); + } + + private void enforceProfileGroupExclusiveRole(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Role role = Roles.get(getContext()).get(roleName); + Objects.requireNonNull(role, "Unknown role: " + roleName); + Preconditions.checkArgument( + role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP, + roleName + " is not a profile-group exclusive role"); + } + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.VANILLA_ICE_CREAM) + private boolean isProfileGroupExclusivityAvailable() { + // TODO(b/372743073): change to isAtLeastB once available + return SdkLevel.isAtLeastV() + && com.android.permission.flags.Flags.crossUserRoleEnabled(); + } } private class Local implements RoleManagerLocal { diff --git a/service/java/com/android/role/RoleShellCommand.java b/service/java/com/android/role/RoleShellCommand.java index 41f0702a2..538e62f47 100644 --- a/service/java/com/android/role/RoleShellCommand.java +++ b/service/java/com/android/role/RoleShellCommand.java @@ -87,6 +87,10 @@ class RoleShellCommand extends BasicShellCommandHandler { return runClearRoleHolders(); case "set-bypassing-role-qualification": return runSetBypassingRoleQualification(); + case "get-active-user-for-role": + return runGetActiveUserForRole(); + case "set-active-user-for-role": + return runSetActiveUserForRole(); default: return handleDefaultCommands(cmd); } @@ -162,6 +166,27 @@ class RoleShellCommand extends BasicShellCommandHandler { return 0; } + private int runGetActiveUserForRole() throws RemoteException { + int userId = getUserIdMaybe(); + String roleName = getNextArgRequired(); + + int activeUserId = mRoleManager.getActiveUserForRoleAsUser(roleName, userId); + if (activeUserId != UserHandleCompat.USER_NULL) { + getOutPrintWriter().println(activeUserId); + } + return 0; + } + + private int runSetActiveUserForRole() throws RemoteException { + int userId = getUserIdMaybe(); + String roleName = getNextArgRequired(); + int activeUserId = Integer.parseInt(getNextArgRequired()); + int flags = getFlagsMaybe(); + + mRoleManager.setActiveUserForRoleAsUser(roleName, activeUserId, flags, userId); + return 0; + } + @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); @@ -174,6 +199,8 @@ class RoleShellCommand extends BasicShellCommandHandler { pw.println(" remove-role-holder [--user USER_ID] ROLE PACKAGE [FLAGS]"); pw.println(" clear-role-holders [--user USER_ID] ROLE [FLAGS]"); pw.println(" set-bypassing-role-qualification true|false"); + pw.println(" get-active-user-for-role [--user USER_ID] ROLE"); + pw.println(" set-active-user-for-role [--user USER_ID] ROLE ACTIVE_USER_ID [FLAGS]"); pw.println(); } } diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java index cda7fcfa8..c94b58826 100644 --- a/service/java/com/android/role/RoleUserState.java +++ b/service/java/com/android/role/RoleUserState.java @@ -24,6 +24,7 @@ import android.annotation.WorkerThread; import android.os.Build; import android.os.Handler; import android.os.UserHandle; +import android.permission.internal.compat.UserHandleCompat; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -427,6 +428,42 @@ class RoleUserState { } } + /** + * Return the active user for the role + * + * @param roleName the name of the role to get the active user for + */ + public int getActiveUserForRole(@NonNull String roleName) { + synchronized (mLock) { + return mActiveUserIds.getOrDefault(roleName, UserHandleCompat.USER_NULL); + } + } + + /** + * Set the active user for the role + * + * @param roleName the name of the role to set the active user for + * @param userId User id to set as active for this role + * @return whether any changes were made + */ + public boolean setActiveUserForRole(@NonNull String roleName, @UserIdInt int userId) { + if (!com.android.permission.flags.Flags.crossUserRoleEnabled()) { + return false; + } + synchronized (mLock) { + Integer currentActiveUserId = mActiveUserIds.get(roleName); + // If we have pre-existing roles that weren't profile group exclusive and don't have an + // active user, ensure we set and write value, and return modified, otherwise other + // users might not have role holder revoked. + if (currentActiveUserId != null && currentActiveUserId == userId) { + return false; + } + mActiveUserIds.put(roleName, userId); + scheduleWriteFileLocked(); + return true; + } + } + /** * Schedule writing the state to file. */ diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java index 250be5f25..6df4184e1 100644 --- a/service/java/com/android/safetycenter/SafetyCenterService.java +++ b/service/java/com/android/safetycenter/SafetyCenterService.java @@ -694,7 +694,8 @@ public final class SafetyCenterService extends SystemService { /** Enforces cross user permission and returns whether the user is valid. */ private boolean enforceCrossUserPermission(String message, @UserIdInt int userId) { UserUtils.enforceCrossUserPermission( - userId, /* allowAll= */ false, message, getContext()); + userId, /* allowAll= */ false, /* enforceForProfileGroup= */ false, message, + getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.w( TAG, diff --git a/service/java/com/android/safetycenter/UserProfileGroup.java b/service/java/com/android/safetycenter/UserProfileGroup.java index d4b051d0f..1f5258437 100644 --- a/service/java/com/android/safetycenter/UserProfileGroup.java +++ b/service/java/com/android/safetycenter/UserProfileGroup.java @@ -21,16 +21,12 @@ import static java.util.Objects.requireNonNull; import android.annotation.IntDef; import android.annotation.UserIdInt; import android.content.Context; -import android.content.pm.PackageManager; import android.os.Binder; -import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.permission.internal.compat.UserHandleCompat; import android.util.Log; -import androidx.annotation.Nullable; - import com.android.permission.util.UserUtils; import java.lang.annotation.Retention; @@ -135,11 +131,7 @@ public final class UserProfileGroup { public static UserProfileGroup fromUser(Context context, @UserIdInt int userId) { Context userContext = UserUtils.getUserContext(userId, context); List userProfiles = UserUtils.getUserProfiles(userContext); - UserHandle profileParent = UserUtils.getProfileParent(userId, userContext); - int profileParentUserId = userId; - if (profileParent != null) { - profileParentUserId = profileParent.getIdentifier(); - } + int profileParentUserId = UserUtils.getProfileParentIdOrSelf(userId, userContext); int[] managedProfilesUserIds = new int[userProfiles.size()]; int[] managedRunningProfilesUserIds = new int[userProfiles.size()]; diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp index 5751aaada..9f1e6cff6 100644 --- a/tests/cts/role/Android.bp +++ b/tests/cts/role/Android.bp @@ -30,10 +30,12 @@ android_test { static_libs: [ "android.permission.flags-aconfig-java-export", "androidx.test.rules", + "com.android.permission.flags-aconfig-java-export", "compatibility-device-util-axt", "ctstestrunner-axt", "Harrier", "bedstead-multiuser", + "flag-junit", "platform-test-annotations", "truth", ], 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 e3bf054b0..9f89140d7 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -104,6 +104,8 @@ public class RoleManagerTest { private static final String ROLE_NAME = RoleManager.ROLE_BROWSER; private static final String ROLE_PHONE_NAME = RoleManager.ROLE_DIALER; private static final String ROLE_SMS_NAME = RoleManager.ROLE_SMS; + private static final String PROFILE_GROUP_EXCLUSIVE_ROLE_NAME = + RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY; private static final String ROLE_SHORT_LABEL = "Browser app"; private static final String APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk"; @@ -1349,6 +1351,51 @@ public class RoleManagerTest { }); } + @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + public void cannotGetActiveUserForRoleWithoutPermission() throws Exception { + assertThrows(SecurityException.class, ()-> + sRoleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME)); + } + + @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + public void cannotGetActiveUserForNonProfileGroupExclusiveRole() throws Exception { + runWithShellPermissionIdentity(() -> + assertThrows(IllegalArgumentException.class, () -> + sRoleManager.getActiveUserForRole( + RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))); + } + + @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + public void cannotSetActiveUserForRoleWithoutPermission() throws Exception { + assertThrows(SecurityException.class, ()-> + sRoleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, + Process.myUserHandle(), 0)); + } + + @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + public void cannotSetActiveUserForNonProfileGroupExclusiveRole() throws Exception { + runWithShellPermissionIdentity(() -> + assertThrows(IllegalArgumentException.class, () -> + sRoleManager.setActiveUserForRole( + RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, Process.myUserHandle(), + 0))); + } + + @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + public void setAndGetActiveUserForRole() throws Exception { + runWithShellPermissionIdentity(() -> { + sRoleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, + Process.myUserHandle(), 0); + assertThat(sRoleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME)) + .isEqualTo(Process.myUserHandle()); + }); + } + @NonNull private List getRoleHolders(@NonNull String roleName) throws Exception { return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName)); diff --git a/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt b/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt index 83d4f78ad..f615f0f4b 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt +++ b/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt @@ -19,15 +19,19 @@ package android.app.role.cts import android.app.role.RoleManager import android.os.Build import android.os.UserHandle +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.test.InstrumentationRegistry import androidx.test.filters.SdkSuppress import androidx.test.runner.AndroidJUnit4 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow +import com.android.permission.flags.Flags import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Assert.assertThrows import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -43,6 +47,8 @@ class RoleShellCommandTest { private var roleHolder: String? = null private var wasBypassingRoleQualification: Boolean = false + @get:Rule val flagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + @Before public fun setUp() { saveRoleHolder() @@ -156,6 +162,28 @@ class RoleShellCommandTest { assertThat(isBypassingRoleQualification()).isFalse() } + @RequiresFlagsEnabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + fun setActiveUserForProfileGroupExclusiveRoleAsUser() { + val activeUser = userId + setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, activeUser) + + val currentActiveUserId = getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) + assertThat(currentActiveUserId).isEqualTo(activeUser) + } + + @RequiresFlagsEnabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + fun setActiveUserForNonProfileGroupExclusiveRoleThenFails() { + assertThrows(AssertionError::class.java) { setActiveUserForRole(ROLE_NAME, userId) } + } + + @RequiresFlagsEnabled(Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Test + fun getActiveUserForNonProfileGroupExclusiveRoleThenFails() { + assertThrows(AssertionError::class.java) { getActiveUserForRole(ROLE_NAME) } + } + private fun addRoleHolder(packageName: String = APP_PACKAGE_NAME) { runShellCommandOrThrow("cmd role add-role-holder --user $userId $ROLE_NAME $packageName") } @@ -204,8 +232,22 @@ class RoleShellCommandTest { callWithShellPermissionIdentity { roleManager.setBypassingRoleQualification(value) } } + private fun getActiveUserForRole(roleName: String): Int? { + return runShellCommandOrThrow("cmd role get-active-user-for-role --user $userId $roleName") + .trim() + .toIntOrNull() + } + + private fun setActiveUserForRole(roleName: String, activeUserId: Int) { + runShellCommandOrThrow( + "cmd role set-active-user-for-role --user $userId $roleName $activeUserId" + ) + } + companion object { private const val ROLE_NAME = RoleManager.ROLE_BROWSER + private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME = + RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY private const val APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk" private const val APP_PACKAGE_NAME = "android.app.role.cts.app" private const val APP_CLONE_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestAppClone.apk" diff --git a/tests/functional/safetycenter/singleuser/AndroidTest.xml b/tests/functional/safetycenter/singleuser/AndroidTest.xml index 3aa173508..af040eb6f 100644 --- a/tests/functional/safetycenter/singleuser/AndroidTest.xml +++ b/tests/functional/safetycenter/singleuser/AndroidTest.xml @@ -47,6 +47,10 @@