外观
系统应用、平台签名、特权权限分别意味着什么?
标准回答
系统应用通常指随系统镜像提供的应用,但“预装”不代表所有权限都自动拥有。我会把安装位置、签名证书、权限类型和实际授予状态分开检查。
普通应用主要使用公开 API 和获得授权的权限。平台签名涉及签名类权限的身份匹配;特权应用涉及系统镜像中的特定位置,并且受相应权限允许清单等规则约束。危险权限、特殊访问授权、角色、AppOps,以及系统服务自身的调用者检查,又各有规则。某个 API 的豁免也不能推导为整个应用不受后台或安全限制。
如果调用失败,我会先记录系统版本、targetSdk、包名、调用进程和具体异常,再用 dumpsys package 核对权限与组件信息,检查签名、分区及适用的允许清单,并查看服务端拒绝原因。权限看起来正确时,还要确认用户或工作资料范围、AppOps、设备策略等条件;涉及底层访问拒绝时再看 SELinux 日志。
解决方式应落在正确的授权配置或受控接口上。需要跨进程代理系统能力时,服务端必须识别真实调用者并校验参数,不能因为自己权限大,就无条件替任意应用执行操作。
关键机制
- 安装身份不等于签名身份,签名身份不等于任意权限都已授予。
- 先查实际拒绝点:Manifest、授予状态、服务端校验、AppOps、用户范围或底层策略。
- 平台版本可能新增授权要求;按目标系统规则核对,不凭旧版本经验推断。
通俗例子
同一 APK 在工程镜像能调用某服务,在正式镜像报 SecurityException。先比对签名、镜像配置和授予状态,而不是只看源代码里是否声明了 uses-permission。
追问与回答
平台签名之后是不是就不用请求权限?
不是。平台签名只影响特定权限的签名匹配,应用仍需满足权限声明及目标版本的授予规则。危险权限、角色、AppOps 和接口额外条件也要分别检查。我会以实际授予状态和服务端检查为准,不把签名当作一个全能开关。
为什么不能直接在服务里 clearCallingIdentity 再调用?
因为那会切换为服务自身身份执行,可能把服务权限借给未经授权的调用者。应先在保留调用身份时检查 UID、权限、目标用户和参数;确实需要切换身份时,将范围收窄,并在 finally 中恢复。不能用身份切换掩盖本来应该拒绝的请求。
易混淆点
平台签名不是 root;放入 priv-app 也不是获得全部特权。蓝牙等 API 的系统应用豁免属于该 API 的具体规则。
参考资料
内容来源
- Android 技术札记 · 原条目
system-privileges