permission flags 是什么为什么 App Ops 需要它
三层独立的权限控制
Android 完整的权限控制由三层构成:
| 层级 | 系统组件 | App Ops 能否操作 | 说明 |
|---|---|---|---|
| 1. 运行时权限(runtime permission) | PackageManager | Shizuku 模式可设置 | 系统面板里能看到的权限开关 |
| 2. appops | AppOpsService | Shizuku/DPM 模式都可操作 | App Ops 直接操作的隐藏权限层 |
| 3. permission flags | PackageManager | 只有 Shizuku 模式可设置 | 决定运行时权限的可修改性和条件性 |
permission flags 是什么
permission flags 是附加在每个运行时权限上的标志位,决定了该权限的额外行为。重要的 flags 包括:
- FIXED:权限状态被锁定,系统面板和 App Ops 都无法修改
- USER_SET:权限是用户手动设置的(系统不应轻易重置)
- USER_FIXED:用户锁定了权限状态,系统重置时跳过这个权限
- TRUSTED:权限来自可信来源,即使应用未活动也保持授予
- INSTALLED:权限来自安装时的默认设置
为什么 App Ops 必须关心 permission flags
App Ops v5.0.0 之前的版本只管理 appops 层,完全忽略了 permission flags。这在 Android 11 上导致严重问题:
问题场景
在 Android 11 上,系统有"每次都询问"权限状态。要实现这个状态,需要:
- 运行时权限(runtime permission)设为 allow
- appops 设为 ignore(让系统每次都检查是否临时授予)
- permission flags 设为 FIXED(锁定,让系统不能自动重置)
App Ops 旧版本只做了第 1、2 步,没做第 3 步——系统重置时发现没有 FIXED 标志,就把 appops 从 ignore 重置为 allow,"每次都询问"状态就失效了。
三种工作模式的 flags 能力对比
| 能力 | Shizuku 模式 | DPM 模式 | 已移除的 Root 模式 |
|---|---|---|---|
| 读取 permission flags | ✅ | ❌ | ❌ |
| 设置 permission flags | ✅ | ❌ | ❌ |
| 修改 runtime permission | ✅ | 部分 | ❌ |
| 修改 appops | ✅ | ✅ | ✅ |
结论:只有 Shizuku 模式具备完整的三层操作能力。这也是为什么:
- 纯 root 模式被移除(只有 shell,没有 Java API 操作 permission flags 的能力)
- DPM 模式不支持 Android 11 的"每次都询问"(无法设置 FIXED flag)
Android 11 自动重置的真正原因
Android 11 引入的 appops 自动重置机制有两个触发条件:
- 系统认为"运行时权限状态和 appops 状态不一致"
- permission flags 中没有 FIXED 或 USER_FIXED
当 App Ops 设置"运行时权限 allow + appops ignore"但没设 FIXED flag 时,系统重置机制会检测到"不一致"且没有锁定标志,就把 appops 改回 allow 以"同步"两层状态。
Shizuku 模式如何正确处理
Shizuku 模式提供了完整的 Binder 接口,让 App Ops 可以通过 Java API:
- 在设置 appops 的同时读取和修改 permission flags
- 检测运行时权限状态和 appops 状态的组合是否正确
- 在系统可能重置的场景下提前设置 FIXED 标志位
这就是 App Ops v5.0.0 重写后"权限设置更正确"的根本原因——不再只管 appops,而是三层一起管理。
对用户意味着什么
- 选 Shizuku 模式(无论是 ADB 激活还是 Root 激活)才能获得正确的权限设置行为
- DPM 模式和旧 root 模式都缺少完整能力,会在某些场景下失效
- 系统自动重置的问题在 Shizuku 模式下被缓解,但不是 100% 消除——系统层面的重置机制 App Ops 无法完全阻止
详见 权限自动恢复问题。