在早期版本的 Android 中,系统会遍历特定应用拥有的所有文件来测量磁盘使用情况。这种手动测量可能需要几分钟才能计算完成,然后才能在“设置”中向用户显示结果。
此外,用于清除缓存数据文件的内部算法仅查看所有应用的修改时间。这使得恶意应用能够通过将修改时间设置为遥远的未来,从而不公平地偏袒自己而不是其他应用,以此来降低整体用户体验。
为了改善这些体验,Android 8.0 提供了利用 ext4 文件系统的“quota”支持来几乎立即返回磁盘使用情况统计信息的功能。此 quota 功能还通过防止任何单个应用使用超过 90% 的磁盘空间或 50% 的 inode 来提高系统稳定性。
实现
quota 功能是 installd
的默认实现的一部分。installd
在特定文件系统上启用 quota 功能时会自动使用该功能。当在被测量的块设备上未启用或不支持 quota 功能时,系统会自动且透明地恢复手动计算。
要在特定块设备上启用 quota 支持
- 启用
CONFIG_QUOTA
、CONFIG_QFMT_V2
和CONFIG_QUOTACTL
内核选项。 - 将
quota
选项添加到 fstab 文件中 userdata 分区。/dev/block/platform/soc/624000.ufshc/by-name/userdata /data ext4 noatime,nosuid,nodev,barrier=1,noauto_da_alloc latemount,wait,check,formattable,fileencryption=ice,quota
fstab
选项可以在现有设备上安全地启用或禁用。在更改 fstab
选项后的首次启动期间,fsmgr
会强制执行 fsck
传递以更新所有 quota 数据结构,这可能会导致首次启动花费稍长的时间。随后的启动将不会受到影响。
Quota 支持仅在 ext4 和 Linux 3.18 或更高版本上经过测试。如果在其他文件系统或较旧的内核版本上启用,设备制造商有责任测试和审查统计信息的正确性。
不需要特殊的硬件支持。
验证
在 StorageHostTest
下有 CTS 测试,这些测试会执行用于测量磁盘使用情况的公共 API。无论是否启用 quota 支持,这些 API 都应返回正确的值。
调试
测试应用会仔细分配磁盘空间区域,并使用唯一的素数作为大小。在调试这些测试时,请使用此方法来确定任何差异的原因。例如,如果测试失败,并且差异为 11MB,请检查 Utils.useSpace()
方法,以查看 11MB blob 是否存储在 getExternalCacheDir()
中。
还有一些内部测试可能对调试有用,但它们可能需要禁用安全检查才能通过
runtest -x frameworks/base/services/tests/servicestests/ \ src/com/android/server/pm/InstallerTest.java
adb shell /data/nativetest64/installd_utils_test/installd_utils_test
adb shell /data/nativetest64/installd_cache_test/installd_cache_test
adb shell /data/nativetest64/installd_service_test/installd_service_test