Faster storage statistics

In earlier versions of Android, the system traversed all files owned by a particular app to measure disk usage. This manual measurement could take minutes to compute before displaying the results to users in Settings.

In addition, the internal algorithm to clear cached data files only looked at modified time across all apps. This allowed malicious apps to degrade the overall user experience by setting modified times far in the future to unfairly favor themselves over other apps.

To improve these experiences, Android 8.0 offers to leverage the ext4 filesystem's "quota" support to return disk usage statistics almost instantly. This quota feature also improves system stability by preventing any single app from using more than 90% of disk space or 50% of inodes.

Implementation

The quota feature is part of the default implementation of installd. installd automatically uses the quota feature when enabled on a particular filesystem. The system automatically and transparently resumes manual calculation when the quota feature isn't enabled or supported on the block device being measured.

To enable quota support on a particular block device:

  1. Enable the CONFIG_QUOTA, CONFIG_QFMT_V2, and CONFIG_QUOTACTL kernel options.
  2. Add the quota option to your userdata partition in your fstab file:
    /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

The fstab option can safely be enabled or disabled on existing devices. During the first boot after changing the fstab option, fsmgr forces an fsck pass to update all quota data structures, which may cause that first boot to take slightly longer. Subsequent boots will not be affected.

Quota support has only been tested on ext4 and Linux 3.18 or higher. If enabling on other filesystems, or on older kernel versions, device manufacturers are responsible for testing and vetting for statistics correctness.

No special hardware support is required.

Validation

There are CTS tests under StorageHostTest, which exercise public APIs for measuring disk usage. These APIs are expected to return correct values regardless of quota support being enabled or disabled.

Debugging

The test app carefully allocates disk space regions using unique prime numbers for the size. When debugging these tests, use this to determine the cause of any discrepancies. For example, if a test fails with a delta of 11MB, examine the Utils.useSpace() method to see that the 11MB blob was stored in getExternalCacheDir().

There are also some internal tests that may be useful for debugging, but they may require disabling security checks to pass:

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