App Ops 里的 uid 模式和 package 模式是什么关系
两层优先级
Android 的每个 appops 操作都有两层独立的 mode 设置:
- uid mode:针对应用进程所属的 Linux 用户 ID。Android 的多用户(工作资料夹、子账号)就是靠不同的 uid 实现的,应用会在不同 uid 下有独立的 appops 设置
- package mode:针对应用包名的全局设置
uid mode 优先级更高——只有当 uid mode 为默认值时,系统才会使用 package mode 的设置。
系统是怎么设置 uid mode 的
从系统权限面板修改应用权限时,系统写入的是 uid mode。不同 Android 版本有不同的映射关系:
Android 6 - Android 9
| 系统设置 | 写入的 uid mode |
|---|---|
| 允许 | allow |
| 拒绝(target 23 以下) | ignore |
| 未设定 | allow |
Android 10
| 系统设置 | 写入的 uid mode |
|---|---|
| 仅在使用期间允许 | foreground |
| 允许 | allow |
| 拒绝 | ignore |
| 未设定 | allow |
Android 11+
| 系统设置 | 写入的 uid mode |
|---|---|
| 每次都询问 | ignore |
| 仅在使用期间允许 | foreground |
| 允许 | allow |
| 拒绝 | ignore |
| 未设定 | ignore |
旧版本 App Ops 的致命缺陷
App Ops v5.0.0 之前的版本只会读取和修改 package mode,完全忽略了 uid mode 的存在。这在 Android 10 发布后变成了大问题:
- 一旦用户在系统设置里把某应用的权限设为"拒绝"或"仅在使用期间允许",系统就写入了 uid mode
- 此时 uid mode 优先级高于 package mode,App Ops 无论怎么改 package mode 都无法让设置生效
- 更要命的是从低版本升级 Android 时,系统的权限设置会被保留,于是这个问题在 Android 10 发布一年后才逐渐大面积暴露
App Ops v5.0.0 的解决方案
v5.0.0 完全重写了逻辑,跟随系统的实际行为:
- 同时管理 uid mode 和 package mode
- 根据运行时权限状态和 permission flags 综合计算正确的 appops 设置
- 需要同时具备"取得和设置 runtime permission、permission flags、appops"的能力
这也是为什么纯 root 模式被移除了——root 只有 uid 0 的 shell 权限,没有修改 permission flags 的能力,只有 Shizuku 模式提供完整的 Java API 调用。
查看两层设置
App Ops 应用中可以查看当前应用的 appops 两层设置状态。进入应用详情 → 权限项 → 查看底层数值,就能看到 uid mode 和 package mode 分别是什么。不过这属于调试信息,普通使用不需要关心。