应用数据与存储:包、用户与文件的对应关系
2026/8/9大约 4 分钟PMS 专题Android 14PMS存储多用户
应用数据与存储:包、用户与文件的对应关系
上一章看了权限。这一章回答:APK 放在哪、应用数据放在哪、多用户下怎么隔离、 /data/app、/data/user 和外部存储是什么关系?
安装包、每用户应用数据与共享存储具有不同的所有者和清理规则。理解这些边界,才能判断 清除数据、卸载、保留数据重装和用户删除分别会影响哪些目录。
APK 与用户数据属于不同生命周期
| 常见误解 | 正确理解 |
|---|---|
| /data/data 是所有应用数据唯一位置 | /data/data 是默认用户(用户 0)的符号入口,真实路径按用户隔离 |
| 外部存储和内部存储是两块物理盘 | 它们是一套磁盘上按权限划分的两类目录语义 |
| 清除数据就是删 APK | 清除数据删的是用户数据目录,APK 与包信息保留 |
核心结论
/data/app/<pkg>-<suffix>/存 APK 与优化产物,更新会换目录。/data/user/<userId>/<pkg>/按用户隔离数据,用户 0 兼容/data/data。- 外部存储按用户分区(
/storage/emulated/<userId>/),读写受 Scoped Storage 约束。 - 卸载只删包文件与用户数据;清除数据只删用户数据,两者范围不同。
- 包信息与授予状态仍由 PMS 的 packages.xml 与权限数据库持久化。
目录对应关系
逐步解释:
- 包目录:每个已安装包一个带后缀目录,更新生成新目录便于回滚。
- 用户数据:每个用户一份
/data/user/<userId>/<pkg>/。 - 外部存储:
/storage/emulated/<userId>/提供用户视角的共享文件。 - 元数据:PMS 的 xml 与权限库记录包与授予状态,不随用户数据删除。
卸载与清除数据为什么不同
卸载(uninstall)删除 /data/app 下的包目录与所有用户的数据目录,包名从清单消失; 清除数据(clear)只删除当前用户的数据目录,包与 APK 仍在。因此“卸载重装”和 “清除数据重登”是两个不同力度的操作,排查问题时不要混用。
源码证据
阅读目标:确认目录计算的入口。
正文指针:PackageManagerService.java 中包目录的构造与 StorageManager; Environment.java 中用户目录路径的生成。
// Environment.java(伪代码,行号以 r75 为准)
File getDataUserDirectory(int userId) {
return new File("/data/user", String.valueOf(userId));
}这段代码证明: 用户数据目录按 userId 拼路径;/data/data 是对用户 0 的兼容入口。 包目录、用户数据、外部存储分别由不同路径计算逻辑管理。
验证与排障
环境:开发设备或模拟器;查看 /data 需要 root。
adb shell pm path <包名>
adb shell su 0 ls -l /data/app/ | grep <包名>
adb shell su 0 ls -l /data/user/0/<包名>/
adb shell pm clear <包名>pm path 确认 APK 位置;/data/app 与 /data/user 确认目录结构;pm clear 验证 清除数据的范围。磁盘不足、数据目录异常、多用户数据错乱等问题,先按这三类目录对号入座。
常见误区
- “/data/data 是唯一数据位置”:只是用户 0 的兼容入口。
- “外部存储就是另一块盘”:是同一磁盘上的权限语义划分。
- “清除数据 = 卸载”:范围不同,一个是删数据,一个是删包。
- “卸载会保留数据”:卸载删除包目录与各用户数据。
延伸问题
- Scoped Storage 下应用如何访问共享媒体文件?
- FUSE 与 sdcardfs 的差异在哪里?
- 应用数据备份(backup)涉及哪些目录?
- 多用户切换时,PMS 如何隔离包列表与权限?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
Environment.java | 用户目录路径 | 目录计算 |
PackageManagerService.java | 包目录构造 | /data/app 管理 |
StorageManager.java | 存储卷管理 | 外部存储 |
packages.xml | /data/system/ | 包信息持久化 |
公共路径:frameworks/base/core/java/android/os/ 与 frameworks/base/services/core/java/com/android/server/pm/。行号以 r75 检索为准。
这些目录在替换与删除时如何变化,见 包更新、卸载与状态变更。