diff options
author | 2024-11-20 17:04:00 +0000 | |
---|---|---|
committer | 2024-11-20 17:04:00 +0000 | |
commit | 89b7fee0b08414d872a6d49027294bf54ce5a1fd (patch) | |
tree | 0b2336f26c0ecda4e8e44e61da1f2ad145cb218b | |
parent | 66ade31f5f206833b69f5a646a7b7eb40c282e81 (diff) | |
parent | 24f197c6d15e9b9d3905d0b5c520489161e939ae (diff) |
Merge "Allow host permission dialogs to show on virtual devices" into main
3 files changed, 80 insertions, 20 deletions
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<String> mSystemRequestedPermissions = new ArrayList<>(); + private final List<String> 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<GrantPermissionsActivity> mFollowerActivities = new ArrayList<>(); + private final List<GrantPermissionsActivity> 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<Intent> mShowWarningDialog = + private final ActivityResultLauncher<Intent> 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<String, Int> = + 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<String, GroupState>() @@ -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) @@ -156,6 +159,32 @@ class DeviceAwarePermissionGrantTest { @RequiresFlagsEnabled( Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED, + Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED, + Flags.FLAG_ALLOW_HOST_PERMISSION_DIALOGS_ON_VIRTUAL_DEVICES + ) + @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 ) @Test @@ -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 |