Size the super partition

Sizing the super partition correctly is important for device updateability. The size directly impacts how many updates a device can take and how many users can successfully take those updates.

There are a few important variables to consider. The first is factory size, which is the size of all dynamic partitions when the device is first flashed. The second is the growth rate, which is the percentage the OS size increases over the entire updatable life of the device.

Additionally, Virtual A/B devices can use space on /data during an update, and this must be considered when sizing super. If too much space is needed on /data, then some users are unable (or unwilling) to take the update. However, if it's known that most users have some percentage of space free, then devices can comfortably subtract that space from super. Or, devices can guarantee that /data is never needed, simply by making super large enough.

Below are some models to help guide super partition sizing based on these variables.

Rely on /data

Virtual A/B encourages shrinking super to allow increasing the size of /data. Some of that space is needed during an update. To understand the impact on updateability, it's essential to know what percentage of devices are likely to have that amount of space free over time. Figuring out this number is highly dependent on the device's hardware and users' behavior of that device. In the examples below, this number is referred to as AllowedUserdataUse.

Without compression

Without compression, a full OTA needs a snapshot roughly the same size as the OS, so that must be taken into account when sizing super:

  FinalDessertSize = FactorySize + (FactorySize * ExpectedGrowth)
  Super = Max(FinalDessertUpdate, FinalDessertSize * 2 - AllowedUserdataUse)

For example, consider a Virtual A/B device with a factory size of 4 GB, expected growth of 50%, and knowledge that almost all users have 1 GB free (or are willing to free up to 1 GB of space for an update). For this device, super can be sized like so:

  FinalDessertSize = 4GB + (4GB * 0.5) = 6GB
  Super = Max(6GB, 6GB * 2 - 1GB) = Max(6GB, 11GB)

Thus, this device should have an 11 GB super partition.

With compression

With compression, a full OTA needs a snapshot roughly 70% of the size of the OS:

  FinalDessertSize = FactorySize + (FactorySize * ExpectedGrowth)
  FinalOTASnapshotSize = FinalDessertSize * 0.7
  Super = Max(FinalDessertUpdate, FinalDessertSize + FinalOTASnapshotSize - AllowedUserdataUse)

For example, consider a device configured with Virtual A/B compression, with a factory size of 4GB, expected growth of 50%, and knowledge that almost all users have 1 GB free (or are willing to free up to 1 GB of space for an update). For this device, super can be sized like so:

  FinalDessertSize = 4GB + (4GB * 0.5) = 6GB
  FinalOTASnapshotSize = 6GB * 0.7 = 4.2GB
  Super = Max(6GB, 6GB + 4.2GB - 1GB) = Max(6GB, 9.2GB) = 9.2GB

Thus, this device should have a 9.2 GB super partition.

Without relying on /data

If you want to have OTAs that never require snapshot space on /data, then sizing super is straightforward.

Without compression

For a Virtual A/B device without compression, or a normal A/B device:

  FinalDessertSize = FactorySize + (FactorySize * ExpectedGrowth)
  Super = FinalDessertSize * 2

For example, consider a Virtual A/B device with a factory size of 4 GB and expected growth of 50%. To ensure this device never uses /data for OTA snapshots, its calculation would look like:

  FinalDessertSize = 4GB + (4GB * 0.5) = 6GB
  Super = FinalDessertSize * 2 = 12GB

Thus, this device should have a 12 GB super partition.

With compression

For a Virtual A/B device with compression:

  FinalDessertSize = FactorySize + (FactorySize * ExpectedGrowth)
  FinalOTASnapshotSize = FinalDessertSize * 0.7
  Super = FinalDessertSize + FinalOTASnapshotSize

For example, consider a Virtual A/B compression device with a factory size of 4 GB and expected growth of 50%. To ensure this device never uses /data for OTA snapshots, its calculation would look like:

  FinalDessertSize = 4GB + (4GB * 0.5) = 6GB
  FinalOTASnapshotSize = 6GB * 0.7 = 4.2GB
  Super = 6GB + 4.2GB = 10.2GB

Thus, this device should have a 10.2 GB super partition.

Caveats

It might be tempting to observe that if the factory size is 4 GB, and the final update is 5 GB, then super needs to be 9 GB, rather than 10 GB. However, if the first update and final update are both 5 GB, then space in super might be insufficient for the final update. The formulas above assume that partition growth could happen at any time. The space needed to apply the final update might be the same as required to apply the first update.

Note that compression ratios are an estimate. An OS image might compress better or worse depending on its contents. If using a compressed file system such as EROFS, the additional compression from Virtual A/B has diminishing returns. In this case it's better to use one of the uncompressed formulas as a guideline.

Calculate the size

To find the value of FinalDessertSize in the above examples, add the sizes of all dynamic partitions together. The AOSP dynamic partition images are:

  • system.img
  • vendor.img
  • product.img
  • system_ext.img
  • vendor_dlkm.img
  • system_dlkm.img

Make sure to calculate the size based on unsparsed images. When building Android 12 or lower, images are sparsed by default, and can be unsparsed with simg2img.

It's also possible to calculate partition sizes from an OTA package. Doing so also estimates the Virtual A/B snapshot size for each partition:

  python3 system/update_engine/scripts/payload_info.py path/to/ota-package.zip

Or, you can use the OTA Analysis Tool. This tool doesn't upload any files and analyzes OTA packages locally.

To find the value of ExpectedGrowth, use a previously released device. Use the earliest and most recent super image to calculate the growth.