Loading services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt +458 −8 Original line number Diff line number Diff line Loading @@ -16,18 +16,468 @@ package com.android.server.permission.access.permission import android.app.AppOpsManager import android.app.admin.DevicePolicyManager import android.content.pm.PackageManager import android.os.Build import android.permission.PermissionManager import com.android.server.permission.access.util.andInv import com.android.server.permission.access.util.hasAnyBit import com.android.server.permission.access.util.hasBits /** * A set of internal permission flags that's better than the set of `FLAG_PERMISSION_*` constants on * [PackageManager]. * * The old binary permission state is now tracked by multiple `*_GRANTED` and `*_REVOKED` flags, so * that: * * - With [INSTALL_GRANTED] and [INSTALL_REVOKED], we can now get rid of the old per-package * `areInstallPermissionsFixed` attribute and correctly track it per-permission, finally fixing * edge cases during module rollbacks. * * - With [LEGACY_GRANTED] and [IMPLICIT_GRANTED], we can now ensure that legacy permissions and * implicit permissions split from non-runtime permissions are never revoked, without checking * split permissions and package state everywhere slowly and in slightly different ways. * * - With [RESTRICTION_REVOKED], we can now get rid of the error-prone logic about revoking and * potentially re-granting permissions upon restriction state changes. * * Permission grants due to protection level are now tracked by [PROTECTION_GRANTED], and permission * grants due to [PackageManager.grantRuntimePermission] are now tracked by [RUNTIME_GRANTED]. * * The [PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED] and * [PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED] flags are now unified into [IMPLICIT], and * they can be differentiated by the presence of [LEGACY_GRANTED]. * * The rest of the permission flags have a 1:1 mapping to the old `FLAG_PERMISSION_*` constants, and * don't have any effect on the binary permission state. */ object PermissionFlags { /** * Permission flag for a normal permission that is granted at package installation. */ const val INSTALL_GRANTED = 1 shl 0 /** * Permission flag for a normal permission that is revoked at package installation. * * Normally packages that have already been installed cannot be granted new normal permissions * until its next installation (update), so this flag helps track that the normal permission was * revoked upon its most recent installation. */ const val INSTALL_REVOKED = 1 shl 1 /** * Permission flag for a signature or internal permission that is granted based on the * permission's protection level, including its protection and protection flags. * * For example, this flag may be set when the permission is a signature permission and the * package is having a compatible signing certificate with the package defining the permission, * or when the permission is a privileged permission and the package is a privileged app with * its permission in the * [privileged permission allowlist](https://source.android.com/docs/core/permissions/perms-allowlist). */ const val PROTECTION_GRANTED = 1 shl 2 const val ROLE_GRANTED = 1 shl 3 // For permissions that are granted in other ways, // ex: via an API or implicit permissions that inherit from granted install permissions const val OTHER_GRANTED = 1 shl 4 // For the permissions that are implicit for the package const val IMPLICIT = 1 shl 5 /** * Permission flag for a role or runtime permission that is or was granted by a role. * * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE */ const val ROLE = 1 shl 3 /** * Permission flag for a development, role or runtime permission that is granted via * [PackageManager.grantRuntimePermission]. */ const val RUNTIME_GRANTED = 1 shl 4 /** * Permission flag for a runtime permission whose state is set by the user. * * For example, this flag may be set when the permission is allowed by the user in the * request permission dialog, or managed in the permission settings. * * @see PackageManager.FLAG_PERMISSION_USER_SET */ const val USER_SET = 1 shl 5 /** * Permission flag for a runtime permission whose state is (revoked and) fixed by the user. * * For example, this flag may be set when the permission is denied twice by the user in the * request permission dialog. * * @see PackageManager.FLAG_PERMISSION_USER_FIXED */ const val USER_FIXED = 1 shl 6 /** * Permission flag for a runtime permission whose state is set and fixed by the device policy * via [DevicePolicyManager.setPermissionGrantState]. * * @see PackageManager.FLAG_PERMISSION_POLICY_FIXED */ const val POLICY_FIXED = 1 shl 7 /** * Permission flag for a runtime permission that is (pregranted and) fixed by the system. * * For example, this flag may be set in * [com.android.server.pm.permission.DefaultPermissionGrantPolicy]. * * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED */ const val SYSTEM_FIXED = 1 shl 8 /** * Permission flag for a runtime permission that is or was pregranted by the system. * * For example, this flag may be set in * [com.android.server.pm.permission.DefaultPermissionGrantPolicy]. * * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED */ const val PREGRANT = 1 shl 9 /** * Permission flag for a runtime permission that is granted because the package targets a legacy * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions. * * As long as this flag is set, the permission should always be considered granted, although * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the * package targets a higher SDK version so that it started supporting runtime permissions, this * flag should be removed and the remaining flags should take effect. * * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val LEGACY_GRANTED = 1 shl 10 /** * Permission flag for a runtime permission that is granted because the package targets a lower * SDK version and the permission is implicit to it as a * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions. * * As long as this flag is set, the permission should always be considered granted, although * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the * package targets a higher SDK version so that the permission is no longer implicit to it, this * flag should be removed and the remaining flags should take effect. * * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val IMPLICIT_GRANTED = 1 shl 11 /** * Permission flag for a runtime permission that is granted because the package targets a legacy * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions, so that * it needs to be reviewed by the user; or granted because the package targets a lower SDK * version and the permission is implicit to it as a * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions, * so that it needs to be revoked when it's no longer implicit. * * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED */ const val IMPLICIT = 1 shl 12 /** * Permission flag for a runtime permission that is user-sensitive when it's granted. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED */ const val USER_SENSITIVE_WHEN_GRANTED = 1 shl 13 /** * Permission flag for a runtime permission that is user-sensitive when it's revoked. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED */ const val USER_SENSITIVE_WHEN_REVOKED = 1 shl 14 /** * Permission flag for a restricted runtime permission that is exempt by the package's * installer. * * For example, this flag may be set when the installer applied the exemption as part of the * [session parameters](https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(java.util.Set%3Cjava.lang.String%3E)). * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT */ const val INSTALLER_EXEMPT = 1 shl 15 /** * Permission flag for a restricted runtime permission that is exempt by the system. * * For example, this flag may be set when the package is a system app. * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT */ const val SYSTEM_EXEMPT = 1 shl 16 /** * Permission flag for a restricted runtime permission that is exempt due to system upgrade. * * For example, this flag may be set when the package was installed before the system was * upgraded to [Build.VERSION_CODES.Q], when restricted permissions were introduced. * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT */ const val UPGRADE_EXEMPT = 1 shl 17 /** * Permission flag for a restricted runtime permission that is revoked due to being hard * restricted. * * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION */ const val RESTRICTION_REVOKED = 1 shl 18 /** * Permission flag for a restricted runtime permission that is soft restricted. * * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION */ const val SOFT_RESTRICTED = 1 shl 19 /** * Permission flag for a runtime permission whose app op is revoked. * * For example, this flag may be set when the runtime permission is legacy or implicit but still * "revoked" by the user in permission settings, or when the app op mode for the runtime * permission is set to revoked via [AppOpsManager.setUidMode]. * * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val APP_OP_REVOKED = 1 shl 20 /** * Permission flag for a runtime permission that is granted as one-time. * * For example, this flag may be set when the user selected "Only this time" in the request * permission dialog. * * This flag, along with other user decisions when it is set, should never be persisted, and * should be removed once the permission is revoked. * * @see PackageManager.FLAG_PERMISSION_ONE_TIME */ const val ONE_TIME = 1 shl 21 /** * Permission flag for a runtime permission that was revoked due to app hibernation. * * This flag is informational and added by PermissionController, and should be removed once the * permission is granted again. * * @see PackageManager.FLAG_PERMISSION_AUTO_REVOKED */ const val HIBERNATION = 1 shl 22 /** * Permission flag for a runtime permission that is selected by the user. * * For example, this flag may be set when one of the coarse/fine location accuracies is * selected by the user. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY */ const val USER_SELECTED = 1 shl 23 /** * Mask for all permission flags. */ const val MASK_ALL = 0.inv() const val MASK_GRANTED = INSTALL_GRANTED or PROTECTION_GRANTED or OTHER_GRANTED or ROLE_GRANTED const val MASK_RUNTIME = OTHER_GRANTED or IMPLICIT /** * Mask for all permission flags that may be applied to a runtime permission. */ const val MASK_RUNTIME = ROLE or RUNTIME_GRANTED or USER_SET or USER_FIXED or POLICY_FIXED or SYSTEM_FIXED or PREGRANT or LEGACY_GRANTED or IMPLICIT_GRANTED or IMPLICIT or USER_SENSITIVE_WHEN_GRANTED or USER_SENSITIVE_WHEN_REVOKED or INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT or RESTRICTION_REVOKED or SOFT_RESTRICTED or APP_OP_REVOKED or ONE_TIME or HIBERNATION or USER_SELECTED /** * Mask for all API permission flags about permission restriction. */ private const val API_MASK_RESTRICTION = PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION /** * Mask for all permission flags about permission restriction. */ private const val MASK_RESTRICTION = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT or RESTRICTION_REVOKED or SOFT_RESTRICTED fun isPermissionGranted(policyFlags: Int): Boolean { if (policyFlags.hasBits(INSTALL_GRANTED)) { return true } if (policyFlags.hasBits(INSTALL_REVOKED)) { return false } if (policyFlags.hasBits(PROTECTION_GRANTED)) { return true } if (policyFlags.hasBits(LEGACY_GRANTED) || policyFlags.hasBits(IMPLICIT_GRANTED)) { return true } if (policyFlags.hasBits(RESTRICTION_REVOKED)) { return false } return policyFlags.hasBits(RUNTIME_GRANTED) } fun isAppOpGranted(policyFlags: Int): Boolean = isPermissionGranted(policyFlags) && !policyFlags.hasBits(APP_OP_REVOKED) fun isReviewRequired(policyFlags: Int): Boolean = policyFlags.hasBits(LEGACY_GRANTED) && policyFlags.hasBits(IMPLICIT) fun toApiFlags(policyFlags: Int): Int { var apiFlags = 0 if (policyFlags.hasBits(USER_SET)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SET } if (policyFlags.hasBits(USER_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_FIXED } if (policyFlags.hasBits(POLICY_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_POLICY_FIXED } if (policyFlags.hasBits(SYSTEM_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SYSTEM_FIXED } if (policyFlags.hasBits(PREGRANT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT } if (policyFlags.hasBits(IMPLICIT)) { apiFlags = apiFlags or if (policyFlags.hasBits(LEGACY_GRANTED)) { PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED } else { PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED } } if (policyFlags.hasBits(USER_SENSITIVE_WHEN_GRANTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED } if (policyFlags.hasBits(USER_SENSITIVE_WHEN_REVOKED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED } if (policyFlags.hasBits(INSTALLER_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT } if (policyFlags.hasBits(SYSTEM_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT } if (policyFlags.hasBits(UPGRADE_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT } if (policyFlags.hasBits(RESTRICTION_REVOKED) || policyFlags.hasBits(SOFT_RESTRICTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION } if (policyFlags.hasBits(ROLE)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE } if (policyFlags.hasBits(APP_OP_REVOKED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_REVOKED_COMPAT } if (policyFlags.hasBits(ONE_TIME)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_ONE_TIME } if (policyFlags.hasBits(HIBERNATION)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_AUTO_REVOKED } if (policyFlags.hasBits(USER_SELECTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY } return apiFlags } fun setRuntimePermissionGranted(policyFlags: Int, isGranted: Boolean): Int = if (isGranted) policyFlags or RUNTIME_GRANTED else policyFlags andInv RUNTIME_GRANTED fun updatePolicyFlags(policyFlags: Int, apiFlagMask: Int, apiFlagValues: Int): Int { check(!apiFlagMask.hasAnyBit(API_MASK_RESTRICTION)) { "Permission flags about permission restriction can only be directly mutated by the" + " policy" } val oldApiFlags = toApiFlags(policyFlags) val newApiFlags = (oldApiFlags andInv apiFlagMask) or (apiFlagValues and apiFlagMask) return toPolicyFlags(policyFlags, newApiFlags) } private fun toPolicyFlags(oldPolicyFlags: Int, apiFlags: Int): Int { var policyFlags = 0 policyFlags = policyFlags or (oldPolicyFlags and INSTALL_GRANTED) policyFlags = policyFlags or (oldPolicyFlags and INSTALL_REVOKED) policyFlags = policyFlags or (oldPolicyFlags and PROTECTION_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) { policyFlags = policyFlags or ROLE } policyFlags = policyFlags or (oldPolicyFlags and RUNTIME_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SET)) { policyFlags = policyFlags or USER_SET } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_FIXED)) { policyFlags = policyFlags or USER_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) { policyFlags = policyFlags or POLICY_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) { policyFlags = policyFlags or SYSTEM_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT)) { policyFlags = policyFlags or PREGRANT } policyFlags = policyFlags or (oldPolicyFlags and LEGACY_GRANTED) policyFlags = policyFlags or (oldPolicyFlags and IMPLICIT_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) || apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)) { policyFlags = policyFlags or IMPLICIT } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)) { policyFlags = policyFlags or USER_SENSITIVE_WHEN_GRANTED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED)) { policyFlags = policyFlags or USER_SENSITIVE_WHEN_REVOKED } // FLAG_PERMISSION_APPLY_RESTRICTION can be either REVOKED_BY_RESTRICTION when the // permission is hard restricted, or SOFT_RESTRICTED when the permission is soft restricted. // However since we should never allow indirect mutation of restriction state, we can just // get the flags about restriction from the old policy flags. policyFlags = policyFlags or (oldPolicyFlags and MASK_RESTRICTION) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)) { policyFlags = policyFlags or APP_OP_REVOKED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_ONE_TIME)) { policyFlags = policyFlags or ONE_TIME } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)) { policyFlags = policyFlags or HIBERNATION } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY)) { policyFlags = policyFlags or USER_SELECTED } return policyFlags } } services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +12 −2 Original line number Diff line number Diff line Loading @@ -232,7 +232,12 @@ class PermissionService( } override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { TODO("Not yet implemented") // TODO: Implement permission checks. val appId = 0 val flags = service.getState { with(policy) { getPermissionFlags(appId, userId, permissionName) } } return PermissionFlags.toApiFlags(flags) } override fun isPermissionRevokedByPolicy( Loading @@ -244,7 +249,12 @@ class PermissionService( } override fun isPermissionsReviewRequired(packageName: String, userId: Int): Boolean { TODO("Not yet implemented") val packageState = packageManagerLocal.withUnfilteredSnapshot() .use { it.packageStates[packageName] } ?: return false val permissionFlags = service.getState { with(policy) { getUidPermissionFlags(packageState.appId, userId) } } ?: return false return permissionFlags.anyIndexed { _, _, flags -> PermissionFlags.isReviewRequired(flags) } } override fun shouldShowRequestPermissionRationale( Loading services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +11 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt +458 −8 Original line number Diff line number Diff line Loading @@ -16,18 +16,468 @@ package com.android.server.permission.access.permission import android.app.AppOpsManager import android.app.admin.DevicePolicyManager import android.content.pm.PackageManager import android.os.Build import android.permission.PermissionManager import com.android.server.permission.access.util.andInv import com.android.server.permission.access.util.hasAnyBit import com.android.server.permission.access.util.hasBits /** * A set of internal permission flags that's better than the set of `FLAG_PERMISSION_*` constants on * [PackageManager]. * * The old binary permission state is now tracked by multiple `*_GRANTED` and `*_REVOKED` flags, so * that: * * - With [INSTALL_GRANTED] and [INSTALL_REVOKED], we can now get rid of the old per-package * `areInstallPermissionsFixed` attribute and correctly track it per-permission, finally fixing * edge cases during module rollbacks. * * - With [LEGACY_GRANTED] and [IMPLICIT_GRANTED], we can now ensure that legacy permissions and * implicit permissions split from non-runtime permissions are never revoked, without checking * split permissions and package state everywhere slowly and in slightly different ways. * * - With [RESTRICTION_REVOKED], we can now get rid of the error-prone logic about revoking and * potentially re-granting permissions upon restriction state changes. * * Permission grants due to protection level are now tracked by [PROTECTION_GRANTED], and permission * grants due to [PackageManager.grantRuntimePermission] are now tracked by [RUNTIME_GRANTED]. * * The [PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED] and * [PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED] flags are now unified into [IMPLICIT], and * they can be differentiated by the presence of [LEGACY_GRANTED]. * * The rest of the permission flags have a 1:1 mapping to the old `FLAG_PERMISSION_*` constants, and * don't have any effect on the binary permission state. */ object PermissionFlags { /** * Permission flag for a normal permission that is granted at package installation. */ const val INSTALL_GRANTED = 1 shl 0 /** * Permission flag for a normal permission that is revoked at package installation. * * Normally packages that have already been installed cannot be granted new normal permissions * until its next installation (update), so this flag helps track that the normal permission was * revoked upon its most recent installation. */ const val INSTALL_REVOKED = 1 shl 1 /** * Permission flag for a signature or internal permission that is granted based on the * permission's protection level, including its protection and protection flags. * * For example, this flag may be set when the permission is a signature permission and the * package is having a compatible signing certificate with the package defining the permission, * or when the permission is a privileged permission and the package is a privileged app with * its permission in the * [privileged permission allowlist](https://source.android.com/docs/core/permissions/perms-allowlist). */ const val PROTECTION_GRANTED = 1 shl 2 const val ROLE_GRANTED = 1 shl 3 // For permissions that are granted in other ways, // ex: via an API or implicit permissions that inherit from granted install permissions const val OTHER_GRANTED = 1 shl 4 // For the permissions that are implicit for the package const val IMPLICIT = 1 shl 5 /** * Permission flag for a role or runtime permission that is or was granted by a role. * * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE */ const val ROLE = 1 shl 3 /** * Permission flag for a development, role or runtime permission that is granted via * [PackageManager.grantRuntimePermission]. */ const val RUNTIME_GRANTED = 1 shl 4 /** * Permission flag for a runtime permission whose state is set by the user. * * For example, this flag may be set when the permission is allowed by the user in the * request permission dialog, or managed in the permission settings. * * @see PackageManager.FLAG_PERMISSION_USER_SET */ const val USER_SET = 1 shl 5 /** * Permission flag for a runtime permission whose state is (revoked and) fixed by the user. * * For example, this flag may be set when the permission is denied twice by the user in the * request permission dialog. * * @see PackageManager.FLAG_PERMISSION_USER_FIXED */ const val USER_FIXED = 1 shl 6 /** * Permission flag for a runtime permission whose state is set and fixed by the device policy * via [DevicePolicyManager.setPermissionGrantState]. * * @see PackageManager.FLAG_PERMISSION_POLICY_FIXED */ const val POLICY_FIXED = 1 shl 7 /** * Permission flag for a runtime permission that is (pregranted and) fixed by the system. * * For example, this flag may be set in * [com.android.server.pm.permission.DefaultPermissionGrantPolicy]. * * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED */ const val SYSTEM_FIXED = 1 shl 8 /** * Permission flag for a runtime permission that is or was pregranted by the system. * * For example, this flag may be set in * [com.android.server.pm.permission.DefaultPermissionGrantPolicy]. * * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED */ const val PREGRANT = 1 shl 9 /** * Permission flag for a runtime permission that is granted because the package targets a legacy * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions. * * As long as this flag is set, the permission should always be considered granted, although * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the * package targets a higher SDK version so that it started supporting runtime permissions, this * flag should be removed and the remaining flags should take effect. * * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val LEGACY_GRANTED = 1 shl 10 /** * Permission flag for a runtime permission that is granted because the package targets a lower * SDK version and the permission is implicit to it as a * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions. * * As long as this flag is set, the permission should always be considered granted, although * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the * package targets a higher SDK version so that the permission is no longer implicit to it, this * flag should be removed and the remaining flags should take effect. * * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val IMPLICIT_GRANTED = 1 shl 11 /** * Permission flag for a runtime permission that is granted because the package targets a legacy * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions, so that * it needs to be reviewed by the user; or granted because the package targets a lower SDK * version and the permission is implicit to it as a * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions, * so that it needs to be revoked when it's no longer implicit. * * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED */ const val IMPLICIT = 1 shl 12 /** * Permission flag for a runtime permission that is user-sensitive when it's granted. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED */ const val USER_SENSITIVE_WHEN_GRANTED = 1 shl 13 /** * Permission flag for a runtime permission that is user-sensitive when it's revoked. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED */ const val USER_SENSITIVE_WHEN_REVOKED = 1 shl 14 /** * Permission flag for a restricted runtime permission that is exempt by the package's * installer. * * For example, this flag may be set when the installer applied the exemption as part of the * [session parameters](https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(java.util.Set%3Cjava.lang.String%3E)). * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT */ const val INSTALLER_EXEMPT = 1 shl 15 /** * Permission flag for a restricted runtime permission that is exempt by the system. * * For example, this flag may be set when the package is a system app. * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT */ const val SYSTEM_EXEMPT = 1 shl 16 /** * Permission flag for a restricted runtime permission that is exempt due to system upgrade. * * For example, this flag may be set when the package was installed before the system was * upgraded to [Build.VERSION_CODES.Q], when restricted permissions were introduced. * * The permission will be restricted when none of the exempt flags is set. * * @see PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT */ const val UPGRADE_EXEMPT = 1 shl 17 /** * Permission flag for a restricted runtime permission that is revoked due to being hard * restricted. * * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION */ const val RESTRICTION_REVOKED = 1 shl 18 /** * Permission flag for a restricted runtime permission that is soft restricted. * * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION */ const val SOFT_RESTRICTED = 1 shl 19 /** * Permission flag for a runtime permission whose app op is revoked. * * For example, this flag may be set when the runtime permission is legacy or implicit but still * "revoked" by the user in permission settings, or when the app op mode for the runtime * permission is set to revoked via [AppOpsManager.setUidMode]. * * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT */ const val APP_OP_REVOKED = 1 shl 20 /** * Permission flag for a runtime permission that is granted as one-time. * * For example, this flag may be set when the user selected "Only this time" in the request * permission dialog. * * This flag, along with other user decisions when it is set, should never be persisted, and * should be removed once the permission is revoked. * * @see PackageManager.FLAG_PERMISSION_ONE_TIME */ const val ONE_TIME = 1 shl 21 /** * Permission flag for a runtime permission that was revoked due to app hibernation. * * This flag is informational and added by PermissionController, and should be removed once the * permission is granted again. * * @see PackageManager.FLAG_PERMISSION_AUTO_REVOKED */ const val HIBERNATION = 1 shl 22 /** * Permission flag for a runtime permission that is selected by the user. * * For example, this flag may be set when one of the coarse/fine location accuracies is * selected by the user. * * This flag is informational and managed by PermissionController. * * @see PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY */ const val USER_SELECTED = 1 shl 23 /** * Mask for all permission flags. */ const val MASK_ALL = 0.inv() const val MASK_GRANTED = INSTALL_GRANTED or PROTECTION_GRANTED or OTHER_GRANTED or ROLE_GRANTED const val MASK_RUNTIME = OTHER_GRANTED or IMPLICIT /** * Mask for all permission flags that may be applied to a runtime permission. */ const val MASK_RUNTIME = ROLE or RUNTIME_GRANTED or USER_SET or USER_FIXED or POLICY_FIXED or SYSTEM_FIXED or PREGRANT or LEGACY_GRANTED or IMPLICIT_GRANTED or IMPLICIT or USER_SENSITIVE_WHEN_GRANTED or USER_SENSITIVE_WHEN_REVOKED or INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT or RESTRICTION_REVOKED or SOFT_RESTRICTED or APP_OP_REVOKED or ONE_TIME or HIBERNATION or USER_SELECTED /** * Mask for all API permission flags about permission restriction. */ private const val API_MASK_RESTRICTION = PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION /** * Mask for all permission flags about permission restriction. */ private const val MASK_RESTRICTION = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT or RESTRICTION_REVOKED or SOFT_RESTRICTED fun isPermissionGranted(policyFlags: Int): Boolean { if (policyFlags.hasBits(INSTALL_GRANTED)) { return true } if (policyFlags.hasBits(INSTALL_REVOKED)) { return false } if (policyFlags.hasBits(PROTECTION_GRANTED)) { return true } if (policyFlags.hasBits(LEGACY_GRANTED) || policyFlags.hasBits(IMPLICIT_GRANTED)) { return true } if (policyFlags.hasBits(RESTRICTION_REVOKED)) { return false } return policyFlags.hasBits(RUNTIME_GRANTED) } fun isAppOpGranted(policyFlags: Int): Boolean = isPermissionGranted(policyFlags) && !policyFlags.hasBits(APP_OP_REVOKED) fun isReviewRequired(policyFlags: Int): Boolean = policyFlags.hasBits(LEGACY_GRANTED) && policyFlags.hasBits(IMPLICIT) fun toApiFlags(policyFlags: Int): Int { var apiFlags = 0 if (policyFlags.hasBits(USER_SET)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SET } if (policyFlags.hasBits(USER_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_FIXED } if (policyFlags.hasBits(POLICY_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_POLICY_FIXED } if (policyFlags.hasBits(SYSTEM_FIXED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SYSTEM_FIXED } if (policyFlags.hasBits(PREGRANT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT } if (policyFlags.hasBits(IMPLICIT)) { apiFlags = apiFlags or if (policyFlags.hasBits(LEGACY_GRANTED)) { PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED } else { PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED } } if (policyFlags.hasBits(USER_SENSITIVE_WHEN_GRANTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED } if (policyFlags.hasBits(USER_SENSITIVE_WHEN_REVOKED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED } if (policyFlags.hasBits(INSTALLER_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT } if (policyFlags.hasBits(SYSTEM_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT } if (policyFlags.hasBits(UPGRADE_EXEMPT)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT } if (policyFlags.hasBits(RESTRICTION_REVOKED) || policyFlags.hasBits(SOFT_RESTRICTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION } if (policyFlags.hasBits(ROLE)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE } if (policyFlags.hasBits(APP_OP_REVOKED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_REVOKED_COMPAT } if (policyFlags.hasBits(ONE_TIME)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_ONE_TIME } if (policyFlags.hasBits(HIBERNATION)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_AUTO_REVOKED } if (policyFlags.hasBits(USER_SELECTED)) { apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY } return apiFlags } fun setRuntimePermissionGranted(policyFlags: Int, isGranted: Boolean): Int = if (isGranted) policyFlags or RUNTIME_GRANTED else policyFlags andInv RUNTIME_GRANTED fun updatePolicyFlags(policyFlags: Int, apiFlagMask: Int, apiFlagValues: Int): Int { check(!apiFlagMask.hasAnyBit(API_MASK_RESTRICTION)) { "Permission flags about permission restriction can only be directly mutated by the" + " policy" } val oldApiFlags = toApiFlags(policyFlags) val newApiFlags = (oldApiFlags andInv apiFlagMask) or (apiFlagValues and apiFlagMask) return toPolicyFlags(policyFlags, newApiFlags) } private fun toPolicyFlags(oldPolicyFlags: Int, apiFlags: Int): Int { var policyFlags = 0 policyFlags = policyFlags or (oldPolicyFlags and INSTALL_GRANTED) policyFlags = policyFlags or (oldPolicyFlags and INSTALL_REVOKED) policyFlags = policyFlags or (oldPolicyFlags and PROTECTION_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) { policyFlags = policyFlags or ROLE } policyFlags = policyFlags or (oldPolicyFlags and RUNTIME_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SET)) { policyFlags = policyFlags or USER_SET } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_FIXED)) { policyFlags = policyFlags or USER_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) { policyFlags = policyFlags or POLICY_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) { policyFlags = policyFlags or SYSTEM_FIXED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT)) { policyFlags = policyFlags or PREGRANT } policyFlags = policyFlags or (oldPolicyFlags and LEGACY_GRANTED) policyFlags = policyFlags or (oldPolicyFlags and IMPLICIT_GRANTED) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) || apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)) { policyFlags = policyFlags or IMPLICIT } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)) { policyFlags = policyFlags or USER_SENSITIVE_WHEN_GRANTED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED)) { policyFlags = policyFlags or USER_SENSITIVE_WHEN_REVOKED } // FLAG_PERMISSION_APPLY_RESTRICTION can be either REVOKED_BY_RESTRICTION when the // permission is hard restricted, or SOFT_RESTRICTED when the permission is soft restricted. // However since we should never allow indirect mutation of restriction state, we can just // get the flags about restriction from the old policy flags. policyFlags = policyFlags or (oldPolicyFlags and MASK_RESTRICTION) if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)) { policyFlags = policyFlags or APP_OP_REVOKED } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_ONE_TIME)) { policyFlags = policyFlags or ONE_TIME } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)) { policyFlags = policyFlags or HIBERNATION } if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY)) { policyFlags = policyFlags or USER_SELECTED } return policyFlags } }
services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +12 −2 Original line number Diff line number Diff line Loading @@ -232,7 +232,12 @@ class PermissionService( } override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { TODO("Not yet implemented") // TODO: Implement permission checks. val appId = 0 val flags = service.getState { with(policy) { getPermissionFlags(appId, userId, permissionName) } } return PermissionFlags.toApiFlags(flags) } override fun isPermissionRevokedByPolicy( Loading @@ -244,7 +249,12 @@ class PermissionService( } override fun isPermissionsReviewRequired(packageName: String, userId: Int): Boolean { TODO("Not yet implemented") val packageState = packageManagerLocal.withUnfilteredSnapshot() .use { it.packageStates[packageName] } ?: return false val permissionFlags = service.getState { with(policy) { getUidPermissionFlags(packageState.appId, userId) } } ?: return false return permissionFlags.anyIndexed { _, _, flags -> PermissionFlags.isReviewRequired(flags) } } override fun shouldShowRequestPermissionRationale( Loading
services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +11 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes