Android 10 introduces User Data Checkpoint (UDC), which allows Android to roll back to its previous state when an Android over-the-air (OTA) update fails. With UDC, if an Android OTA update fails, the device can safely roll back to its previous state. Although A/B updates solve this problem for early boot, rollback isn't supported when the user data partition (mounted on /data
) is modified.
UDC enables the device to revert the user data partition even after being modified. The UDC feature accomplishes this with checkpoint capabilities to the file system, an alternative implementation when the file system doesn't support checkpoints, integration with the bootloader A/B mechanism while also supporting non-A/B updates, and support for key version binding and key rollback prevention.
User impact
The UDC feature improves the OTA update experience for users as fewer users lose their data when an OTA update fails. This can reduce the number of support calls from users who run into issues during the update process. However, when an OTA update fails, users may notice the device rebooting multiple times.
How it works
Checkpoint functionality in different file systems
For the F2FS file system, UDC adds the checkpoint functionality to the upstream 4.20 Linux kernel and backports it to all common kernels supported by devices running Android 10.
For other file systems, UDC uses a device mapper virtual device called dm_bow
for checkpoint functionality. dm_bow
sits between the device and the file system. When a partition is mounted, a trim is issued causing the file system to issue trim commands on all free blocks. dm_bow
intercepts these trims and uses them to set up a free block list. Reads and writes are then sent to the device unmodified, but before a write is allowed, data needed for a restore is backed up to a free block.
Checkpoint process
When a partition with the checkpoint=fs/block
flag is mounted, Android calls restoreCheckpoint
on the drive to allow the device to restore any current checkpoint. init
then calls the needsCheckpoint
function to determine if the device either is in a bootloader A/B state or has set the update retry count. If either is true, Android calls createCheckpoint
to either add mount flags or build a dm_bow
device.
After the partition is mounted, the checkpoint code is called to issue trims. The boot process then continues as normal. At LOCKED_BOOT_COMPLETE
, Android calls commitCheckpoint
to commit the current checkpoint and the update continues as normal.
Manage KeyMint (previously Keymaster) keys
KeyMint keys are used for device encryption or other purposes. To manage these keys, Android delays key delete calls until the checkpoint is committed.
Monitor health
A health daemon verifies that there's enough disk space to create a checkpoint. The health daemon is located in cp_healthDaemon
in Checkpoint.cpp
.
The health daemon has the following behaviors that can be configured:
ro.sys.cp_msleeptime
: Controls how often the device checks disk usage.ro.sys.cp_min_free_bytes
: Controls the minimum value the health daemon looks for.ro.sys.cp_commit_on_full
: Controls whether the health daemon reboots the device or commits the checkpoint and continues when the disk is full.
Checkpoint APIs
Checkpoint APIs are used by the UDC feature. For other APIs used by UDC, see IVold.aidl
.
void startCheckpoint(int retry)
Creates a checkpoint.
The framework calls this method when it's ready to start an update. The checkpoint is created before checkpointed file systems such as userdata are mounted R/W after reboot. If the retry count is positive, the API handles tracking retries, and the updater calls needsRollback
to check if a rollback of the update is required. If the retry count is -1
, the API defers to the A/B bootloader's judgement.
This method isn't called when doing a normal A/B update.
void commitChanges()
Commits the changes.
The framework calls this method after reboot when the changes are ready to be committed. This is called before data (such as pictures, video, SMS, server receipt of receival) is written to userdata and before BootComplete
.
If no active checkpointed update exists, this method has no effect.
abortChanges()
Forces reboot and reverts to the checkpoint. Abandons all userdata modifications since the first reboot.
The framework calls this method after reboot but before commitChanges
. retry_counter
is decreased when this method is called. Log entries are generated.
bool needsRollback()
Determines whether a rollback is required.
On noncheckpoint devices, returns false
. On checkpoint devices, returns true
during a noncheckpoint boot.
Implement UDC
Reference implementation
For an example of how UDC can be implemented, see dm-bow.c. For additional documentation on the feature, see dm-bow.txt.
Setup
In on fs
in your init.hardware.rc
file, make sure you have:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
In on late-fs
in your init.hardware.rc
file, make sure you have:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
In your fstab.hardware
file, make sure /data
is tagged as latemount
.
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs
Add metadata partition
UDC requires a metadata partition to store the nonbootloader retry count and keys. Set up a metadata partition and early mount it at /metadata
.
In your fstab.hardware
file, make sure /metadata
is tagged as earlymount
or first_stage_mount
.
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
Initialize the partition to all zeroes.
Add the following lines to BoardConfig.mk
:
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
Update systems
F2FS systems
For systems that use F2FS to format data, make sure that your version of F2FS supports checkpoints. For more information, see Checkpoint functionality in different file systems.
Add the checkpoint=fs
flag to the <fs_mgr_flags>
section of fstab for the device mounted at /data
.
Non-F2FS systems
For non-F2FS systems, dm-bow
must be enabled in the kernel config.
Add the checkpoint=block
flag to the <fs_mgr_flags>
section of fstab for the device mounted at /data
.
Check logs
Log entries are generated when Checkpoint APIs are called.
Validation
To test your UDC implementation, run the VtsKernelCheckpointTest
set of VTS tests.