权限框架
本文面向已经读过 安装权限处理 和 包设置状态 的读者。目标不是背诵权限常量,而是建立 Android 17 的源码地图:Manifest 权限定义由谁接收,安装回调如何进入权限状态事务,checkPermission 到底读取哪份状态,运行时 grant/revoke 如何修改并持久化,以及带 AppOps 的权限为什么还需要第二层判定。读完后,读者应能从 API 入口定位到真实状态 owner,而不会把 PackageManager、PermissionController、PermissionManagerService 和 AppOps 当成同一个组件。
1. 架构迁移
1.1 Binder 门面
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
public class PermissionManagerService extends IPermissionManager.Stub {
private final Object mLock = new Object();
private final PackageManagerInternal mPackageManagerInt;
private final AppOpsManager mAppOpsManager;
private final Context mContext;
private final PermissionManagerServiceInterface
mPermissionManagerServiceImpl;
PermissionManagerService(Context context,
ArrayMap<String, FeatureInfo> availableFeatures) {
mContext = context;
mPackageManagerInt = LocalServices.getService(
PackageManagerInternal.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
final PermissionManagerServiceInternalImpl localService =
new PermissionManagerServiceInternalImpl();
LocalServices.addService(
PermissionManagerServiceInternal.class, localService);
LocalServices.addService(
PermissionManagerInternal.class, localService);
mPermissionManagerServiceImpl = LocalServices.getService(
PermissionManagerServiceInterface.class);
}
}PermissionManagerService 对外实现 IPermissionManager,对 system_server 内部注册两个 LocalServices,但核心操作委托给 PermissionManagerServiceInterface。因此看到 grantRuntimePermission() 的 Java Binder 方法时,还没有到达真正的状态算法。
1.2 现代实现
源码文件:
frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.ktframeworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
class AccessCheckingService(context: Context) : SystemService(context) {
@Volatile private lateinit var state: AccessState
private val stateLock = Any()
private val policy = AccessPolicy()
private val persistence = AccessPersistence(policy)
private lateinit var appOpService: AppOpService
lateinit var permissionService: PermissionService
override fun onStart() {
appOpService = AppOpService(this)
permissionService = PermissionService(this)
LocalServices.addService(
AppOpsCheckingServiceInterface::class.java,
appOpService,
)
LocalServices.addService(
PermissionManagerServiceInterface::class.java,
permissionService,
)
}
}Android 17 的真实状态 owner 是 AccessCheckingService 中的 AccessState。PermissionService 与 AppOpService 共享访问策略和持久化框架,再分别实现 permission 与 app-op 接口。旧式 Java PermissionManagerService 是兼容门面和 attribution/one-time permission 等协调层。
2. 服务启动
2.1 注册入口
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
public static PermissionManagerServiceInternal create(
Context context,
ArrayMap<String, FeatureInfo> availableFeatures) {
PermissionManagerService permissionService =
(PermissionManagerService) ServiceManager.getService(
"permissionmgr");
if (permissionService == null) {
permissionService = new PermissionManagerService(
context, availableFeatures);
ServiceManager.addService(
"permissionmgr", permissionService);
ServiceManager.addService(
"permission_checker",
new PermissionCheckerService(context));
}
return LocalServices.getService(
PermissionManagerServiceInternal.class);
}系统注册两个 Binder service:permissionmgr 负责权限管理 API,permission_checker 负责带 attribution 和数据访问语义的检查。system_server 内部组件通常使用 PermissionManagerServiceInternal,减少 Binder 往返。
2.2 状态初始化
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
fun initialize() {
packageManagerInternal =
LocalServices.getService(PackageManagerInternal::class.java)
packageManagerLocal =
LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
userManagerService = UserManagerService.getInstance()
systemConfig = SystemConfig.getInstance()
val userIds = MutableIntSet(
userManagerService.userIdsIncludingPreCreated
)
val (packageStates, disabledSystemPackageStates) =
packageManagerLocal.allPackageStates
val mutableState = MutableAccessState()
policy.initialize(
mutableState,
userIds,
packageStates,
disabledSystemPackageStates,
packageManagerInternal.knownPackages,
systemConfig.isLeanback,
systemConfig.permissions,
systemConfig.privilegedPermissionAllowlistPackages,
systemConfig.permissionAllowlist,
systemConfig.implicitToSourcePermissions,
)
persistence.initialize()
persistence.read(mutableState)
state = mutableState
}初始化同时读取用户、当前包、disabled system 包、known packages、系统配置权限、特权 allowlist 和持久化状态。权限结果不是只从 APK Manifest 推导,也不是只读一个 runtime-permissions 文件;它是包事实、系统策略和历史授权状态的合成。
3. 权限分类
3.1 基础保护级别
源码文件:frameworks/base/core/java/android/content/pm/PermissionInfo.java
public static final int PROTECTION_NORMAL = 0;
public static final int PROTECTION_DANGEROUS = 1;
public static final int PROTECTION_SIGNATURE = 2;
@Deprecated
public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;
public static final int PROTECTION_INTERNAL = 4;
public static final int PROTECTION_MASK_BASE = 0xf;normal 权限通常随安装状态计算;dangerous 权限需要运行时用户决策;signature 权限要求签名或 lineage 能力;internal 用于系统内部边界。基础级别只占低位,额外 flags 会叠加更具体的授予条件。
3.2 保护 flags
public static final int PROTECTION_FLAG_PRIVILEGED = 0x10;
public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
public static final int PROTECTION_FLAG_APPOP = 0x40;
public static final int PROTECTION_FLAG_PRE23 = 0x80;
public static final int PROTECTION_FLAG_INSTALLER = 0x100;
public static final int PROTECTION_FLAG_ROLE = 0x04000000;
public static final int PROTECTION_FLAG_KNOWN_SIGNER = 0x08000000;flags 不是新的基础类型。例如 signature|privileged 允许符合特权 allowlist 的预装应用获得权限;dangerous|appop 表示权限 grant 通过后,真实数据访问还可能受 AppOps mode 限制。具体授予矩阵由 PermissionService/Policy 结合包身份计算。
3.3 三类使用方式
| 类别 | 典型入口 | 状态 owner | 最终消费者 |
|---|---|---|---|
| 安装权限 | 包扫描/安装回调 | AccessState 的 appId permission flags | 系统服务的权限检查 |
| 运行时权限 | requestPermissions 后的 grant/revoke | 每用户、每 appId、每 permission flags | API 调用与 PermissionChecker |
| 特殊访问 | Settings/专用 manager/AppOps | 对应服务或 AppOps mode | Window、存储、通知等服务 |
“特殊权限”不是统一保护级别。例如 overlay、write settings、安装未知应用等由不同服务和 AppOps/设置页控制,不能仅查询 checkPermission 就断定最终访问一定允许。
4. 包生命周期
4.1 包新增
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
override fun onPackageAdded(
packageState: PackageState,
isInstantApp: Boolean,
oldPackage: AndroidPackage?,
) {
if (packageState.isApex) {
return
}
synchronized(storageVolumeLock) {
storageVolumePackageNames
.getOrPut(packageState.volumeUuid) { mutableListOf() }
.add(packageState.packageName)
if (packageState.volumeUuid !in mountedStorageVolumes) {
return
}
}
service.onPackageAdded(packageState.packageName)
}PMS 提交包后调用 onPackageAdded。未挂载 volume 的包先登记顺序,等 volume mount 后批量进入状态事务;这样权限定义 owner 的选择保持确定顺序。APEX 本体不按普通 APK 权限包处理。
4.2 安装参数
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
public void onPackageInstalled(AndroidPackage pkg,
int previousAppId,
PackageInstalledParams params,
int rawUserId) {
mPermissionManagerServiceImpl.onPackageInstalled(
pkg, previousAppId, params, rawUserId);
final int[] userIds = rawUserId == UserHandle.USER_ALL
? getAllUserIds() : new int[] { rawUserId };
for (int userId : userIds) {
final int mode = params.getAutoRevokePermissionsMode();
if (mode == AppOpsManager.MODE_ALLOWED
|| mode == AppOpsManager.MODE_IGNORED) {
setAutoRevokeExemptedInternal(
pkg, mode == AppOpsManager.MODE_IGNORED, userId);
}
}
}安装回调除了权限 states 和 restricted allowlist,还把 auto-revoke exemption 映射到 AppOps mode。权限初始化与 AppOps 策略因此在同一安装事件中协作,但仍由不同状态域消费。
4.3 现代安装处理
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
override fun onPackageInstalled(
androidPackage: AndroidPackage,
previousAppId: Int,
params: PackageInstalledParams,
userId: Int,
) {
if (androidPackage.isApex) return
if (params === PackageInstalledParams.DEFAULT) return
val userIds = if (userId == UserHandle.USER_ALL) {
userManagerService.userIdsIncludingPreCreated
} else {
intArrayOf(userId)
}
userIds.forEach {
service.onPackageInstalled(androidPackage.packageName, it)
}
userIds.forEach {
val packageState = packageManagerInternal
.getPackageStateInternal(androidPackage.packageName)!!
addAllowlistedRestrictedPermissionsUnchecked(
androidPackage,
packageState.appId,
params.allowlistedRestrictedPermissions,
it,
)
setRequestedPermissionStates(
packageState, it, params.permissionStates
)
}
}USER_ALL 展开到包含预创建用户的用户集合。默认参数路径在现代实现中直接返回,因为基础权限状态已在 onPackageAdded 初始化;显式 installer 参数才追加受限权限 allowlist 和逐权限请求。
5. 状态事务
5.1 Copy-on-write
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
internal inline fun <T> getState(
action: GetStateScope.() -> T
): T {
return GetStateScope(state).action()
}
internal inline fun mutateState(
crossinline action: MutateStateScope.() -> Unit
) {
synchronized(stateLock) {
val oldState = state
val newState = oldState.toMutable()
MutateStateScope(oldState, newState).action()
persistence.write(newState)
state = newState
with(policy) {
GetStateScope(newState).onStateMutated()
}
}
}读操作使用当前 volatile AccessState 快照;写操作在 stateLock 下复制旧状态、执行 policy 变更、请求持久化、原子替换引用,最后通知策略消费者。读者不会看到正在半途修改的 mutable state。这是 Android 17 权限状态并发模型的核心,而不是旧式“所有读取都锁住 PermissionRegistry”。
5.2 生命周期事件
internal fun onPackageAdded(packageName: String) {
val (packageStates, disabledSystemPackageStates) =
packageManagerLocal.allPackageStates
mutateState {
with(policy) {
onPackageAdded(
packageStates,
disabledSystemPackageStates,
packageManagerInternal.knownPackages,
packageName,
)
}
}
}包、用户和 volume 生命周期事件都会先取得 PackageManagerLocal 快照,再在单个权限状态事务中应用。PackageManager 提供包事实,AccessPolicy 决定状态变化,AccessPersistence 保存结果;三者职责不可互换。
6. 权限检查
6.1 Binder 入口
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
public int checkPermission(String packageName,
String permissionName,
String persistentDeviceId,
int userId) {
if (packageName == null || permissionName == null) {
return PackageManager.PERMISSION_DENIED;
}
final CheckPermissionDelegate delegate;
synchronized (mLock) {
delegate = mCheckPermissionDelegate;
}
if (delegate == null) {
return mPermissionManagerServiceImpl.checkPermission(
packageName, permissionName,
persistentDeviceId, userId);
}
return delegate.checkPermission(
packageName, permissionName, persistentDeviceId,
userId, mPermissionManagerServiceImpl::checkPermission);
}null 参数按兼容行为直接 denied。测试、shell delegation 或权限代理存在时,CheckPermissionDelegate 可以包装真实检查;正常路径进入 PermissionService。
6.2 状态读取
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
override fun checkPermission(
packageName: String,
permissionName: String,
deviceId: String,
userId: Int,
): Int {
if (!userManagerInternal.exists(userId)) {
return PackageManager.PERMISSION_DENIED
}
val packageState = packageManagerLocal
.withFilteredSnapshot(Binder.getCallingUid(), userId)
.use { it.getPackageState(packageName) }
?: return PackageManager.PERMISSION_DENIED
val granted = service.getState {
isPermissionGranted(
packageState, userId, permissionName, deviceId
)
}
return if (granted) {
PackageManager.PERMISSION_GRANTED
} else {
PackageManager.PERMISSION_DENIED
}
}检查先验证用户,再通过调用者过滤后的 PackageManagerLocal snapshot 查包,最后从 AccessState 读取 appId/user/permission/device 组合的 flags。包不可见或不存在时直接 denied;权限检查不会因调用者知道包名就绕过包可见性。
6.3 权限包含
isPermissionGranted 还会查询 FULLER_PERMISSIONS 映射:若目标 permission 未授予,但其更完整权限已授予,也可能返回 granted。真正的单权限检查集中在 isSinglePermissionGranted,其中 permission flags、instant-app 限制和 device context 共同参与。
7. AppOps 协作
7.1 数据访问检查
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
private static final class PermissionCheckerService
extends IPermissionChecker.Stub {
public int checkPermission(String permission,
AttributionSourceState sourceState,
String message,
boolean forDataDelivery,
boolean startDataDelivery,
boolean fromDatasource,
int attributedOp) {
final int result = checkPermission(
mContext,
mPermissionManagerServiceInternal,
permission,
new AttributionSource(sourceState),
message,
forDataDelivery,
startDataDelivery,
fromDatasource,
attributedOp);
if (startDataDelivery
&& result != PermissionChecker.PERMISSION_GRANTED
&& result != PermissionChecker.PERMISSION_SOFT_DENIED) {
finishDataDelivery(...);
}
return result;
}
}checkPermission 回答静态 grant;PermissionCheckerService 还检查 attribution chain、AppOps 和数据访问开始/结束。带 PROTECTION_FLAG_APPOP 的权限可能 permission granted 但 AppOps ignored,从而得到 soft denied 或 hard denied。系统 API 若涉及真实数据访问,应使用对应的 PermissionChecker/AppOps 模式,而不是只调用 PackageManager.checkPermission。
8. Grant 与 revoke
8.1 门面委托
public void grantRuntimePermission(String packageName,
String permissionName, String persistentDeviceId,
int userId) {
mPermissionManagerServiceImpl.grantRuntimePermission(
packageName, permissionName,
persistentDeviceId, userId);
}
public void revokeRuntimePermission(String packageName,
String permissionName, String persistentDeviceId,
int userId, String reason) {
mPermissionManagerServiceImpl.revokeRuntimePermission(
packageName, permissionName,
persistentDeviceId, userId, reason);
}8.2 统一写入函数
源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
override fun grantRuntimePermission(
packageName: String,
permissionName: String,
deviceId: String,
userId: Int,
) {
setRuntimePermissionGranted(
packageName, userId, permissionName,
deviceId, isGranted = true,
)
}
override fun revokeRuntimePermission(
packageName: String,
permissionName: String,
deviceId: String,
userId: Int,
reason: String?,
) {
setRuntimePermissionGranted(
packageName, userId, permissionName,
deviceId, isGranted = false,
revokeReason = reason,
)
}grant/revoke 共用 setRuntimePermissionGranted,后者检查用户存在、跨用户权限、shell restriction、包和权限类型,再在 AccessState 事务中修改 flags。revoke 通常还会杀 UID,使进程不能继续使用撤销前缓存的能力;测试专用 notification revoke 路径可以显式跳过 kill。
9. 权限生命周期
10. 失败边界
10.1 包与用户不存在
checkPermission 对不存在用户、不可见包或未知包直接 denied;grant/revoke 对未知用户记录警告并返回或抛出权限相关异常。不存在对象不是 granted 的默认状态。
10.2 Volume 未挂载
包位于未挂载 volume 时,onPackageAdded 只记录顺序并等待 mount;安装参数也可能延迟应用。此时 PMS 有 PackageSetting 不代表 PermissionService 已完成该 volume 的状态变更。
10.3 AppOps 分歧
permission granted、AppOps ignored 是合法组合,常用于前台限制、用户隐私开关和兼容行为。故障排查必须同时读取 permission flags 和 app-op mode,不能用一个结果替代另一个。
10.4 shared UID
单用户卸载和 shared UID 删除需要保留其他包/用户仍使用的权限状态;PermissionService 的 onPackageUninstalled 接收 package、appId、shared user packages 和 userId 来判断清理范围。删除一个包不必然删除整个 appId 的 permission flags。
11. 验证方法
11.1 安装初始化
准备包含 normal、dangerous 和 signature 权限请求的 APK。安装后使用 dumpsys package 和 pm list permissions 比较定义与 grant:normal 可随安装获得,dangerous 默认不等于用户已授权,signature 取决于证书关系。该实验验证保护级别分叉,不覆盖 AppOps。
11.2 Grant/revoke
对 debuggable 测试包执行 pm grant、pm revoke,前后调用 checkPermission 并观察进程是否因 revoke 被终止。关键断言是状态按 userId 变化,另一个用户不受影响;不具备 runtime 类型或未声明权限时应失败。
11.3 AppOps 组合
选择一个 permission-to-op 映射的危险权限,保持 permission granted,分别把 AppOps mode 设为 allowed 与 ignored。比较 checkPermission 和真实 API/PermissionChecker 结果:前者可能保持 granted,后者随 AppOps 改变。这验证两层访问控制。
adb shell dumpsys package <package.name>
adb shell pm check-permission <permission> <package.name> --user 0
adb shell appops get <package.name>11.4 卸载重装
先授予运行时权限,再普通卸载与 -k 卸载并重装。比较 AccessState/最终 grant:完整删除应清理相应用户权限状态;保留数据路径可能保留身份和部分授权事实,但重新安装仍受签名、版本和 installer params 约束。
12. 源码路线
AccessCheckingService.onStart/initialize:确认现代实现、输入事实和持久化。PermissionManagerService.create:确认 Binder 与 LocalServices 门面。PermissionService.onPackageAdded/onPackageInstalled:连接 PMS 安装生命周期。AccessCheckingService.mutateState:理解权限状态事务和并发读取。PermissionService.checkPermission:跟踪包可见性、user/appId/device 与 flags。setRuntimePermissionGranted:继续阅读 grant/revoke 的权限、flag 和 kill UID 分支。PermissionCheckerService:连接 attribution chain 与 AppOps 数据访问。
Android 17 权限框架的核心不是单个 PermissionManagerService 类,而是一条分层链路:PackageManager 提供包和用户事实,Java Binder 门面承接 API,PermissionService 在 AccessPolicy 下读写 AccessState,AccessPersistence 保存事务结果,PermissionChecker 再把静态 grant 与 AppOps、attribution 组合成真实访问决定。后续阅读任何权限问题,都应先判断它属于定义、状态、运行时变更、AppOps 还是最终资源服务检查中的哪一层。
