本文深入讲解了Android权限管理系统的核心模块 PermissionManagerService,我会用更通俗的方式拆解其核心机制,并结合生活场景帮助你彻底理解。
一、权限管理服务(PermissionManagerService)是什么?
- 角色定位:它是Android系统的“权限管家”,像学校的教务处管理学生权限一样,管理所有App的权限授予、撤销和检查。
- 工作地点:运行在系统进程(systemserver)中,和ActivityManagerService(AMS)、PackageManagerService(PMS)是同事。
- 服务方式:通过Binder机制对外提供服务,开发者通过
PermissionManager和PermissionCheckerManager这两个工具类调用它。
二、权限的分类与核心概念
1. 声明权限 vs 使用权限
-
声明权限:相当于“制定规则”。
- 例子:微信声明了“读取联系人”权限,表示它要保护用户联系人数据。
- 存储方式:用
Permission类记录权限名、保护级别等信息,存在全局的ArrayMap中。
-
使用权限:相当于“申请通行证”。
- 例子:抖音申请“读取联系人”权限,用户同意后才能访问微信的联系人。
- 存储方式:通过多层嵌套结构(后文详解)记录每个App在每个用户下的权限状态。
2. 权限的三种来源
- 内置权限:系统自带的权限(如网络权限),归属系统进程(包名
android)。 - App声明权限:App在
AndroidManifest.xml中声明的权限。 - 动态权限:App运行时通过代码动态添加的权限(较少见)。
三、权限的数据结构:层层嵌套的“权限档案”
1. 声明权限的存储
-
核心类:
Permission- 记录权限名、保护级别(如
dangerous)、所属组(如STORAGE组)等。
- 记录权限名、保护级别(如
-
全局存储:所有声明的权限存在一个全局的
ArrayMap,键是权限名,值是Permission对象。
2. 使用权限的存储(核心难点)
权限状态需要区分 设备用户 和 具体App,因此设计了多层嵌套结构:
-
DevicePermissionState
- 作用:管理整个设备所有用户的权限状态。
- 数据结构:
SparseArray<UserPermissionState>,键是用户ID(如用户0、用户1)。
-
UserPermissionState
- 作用:管理某个用户下所有App的权限状态。
- 数据结构:
SparseArray<UidPermissionState>,键是App的UID(唯一标识)。
-
UidPermissionState
- 作用:管理某个App的所有权限状态。
- 数据结构:
ArrayMap<权限名, PermissionState>,键是权限名。
-
PermissionState
- 作用:记录单个权限的状态(是否授予、额外标志位)。
- 属性:
mGranted(是否授权)、mFlags(如用户是否固定授权)。
3. 直观比喻
- DevicePermissionState 像一台手机的“总权限档案柜”。
- 每个抽屉(UserPermissionState) 对应一个用户(如家长和孩子的账户)。
- 每个文件夹(UidPermissionState) 对应一个App(如微信、抖音)。
- 每张纸(PermissionState) 记录一个权限的状态(如“相机权限:已授予”)。
四、权限数据初始化:系统启动时的“建档”过程
-
加载内置权限
- 从系统配置文件(如
/system/etc/permissions)读取预定义的权限,生成Permission对象。
- 从系统配置文件(如
-
加载App声明的权限
- 安装App时,解析其
AndroidManifest.xml中的<permission>标签,生成Permission对象。
- 安装App时,解析其
-
加载历史权限状态
- 从
/data/misc/.../runtime-permissions.xml读取用户之前授予/拒绝的权限,构建多层嵌套结构(如DevicePermissionState)。
- 从
-
动态调整
- 系统升级或App更新后,重新扫描权限,增删无效权限(如已卸载App的权限)。
五、权限管理:增删查改的“档案操作”
1. 权限的增删
-
安装App时:
- 添加其声明的权限到全局
ArrayMap。 - 将其申请的权限状态(如默认授予
normal权限)写入UidPermissionState。
- 添加其声明的权限到全局
-
卸载App时:
- 移除其声明的权限(如果是该App独有的)。
- 清除其在所有用户下的权限状态。
2. 权限的查询
- 检查权限是否授予:
从DevicePermissionState逐层向下查询,最终找到PermissionState.mGranted的值。
六、权限授予/撤销:用户操作的背后流程
-
用户点击“允许”
- 通过
PermissionControllerApp(系统权限管理界面)发起请求。
- 通过
-
Binder通信到PermissionManagerService
- 修改目标App对应的
PermissionState.mGranted为true或false。
- 修改目标App对应的
-
持久化存储
- 将变更写入
runtime-permissions.xml,确保重启后权限状态不丢失。
- 将变更写入
七、总结:PermissionManagerService的核心价值
- 权限中枢:管理所有权限的声明、状态和生命周期。
- 多用户支持:通过分层结构隔离不同用户的权限设置。
- 安全性:确保危险权限(如相机、位置)必须由用户显式授权。
通过这套机制,Android实现了细粒度的权限控制,既保护用户隐私,又为App提供了灵活的权限管理能力。