Android 10 introduit la fonctionnalité User Data Checkpoint (UDC), qui permet à Android de revenir à son état précédent en cas d'échec d'une mise à jour Android OTA (Over-The-Air). Avec UDC, si une mise à jour Android OTA échoue, l'appareil peut revenir en toute sécurité à son état précédent. Bien que
les mises à jour A/B résolvent ce problème pour le démarrage anticipé, la restauration
n'est pas prise en charge lorsque la partition de données utilisateur (montée sur /data) est modifiée.
UDC permet à l'appareil de rétablir la partition de données utilisateur même après sa modification. La fonctionnalité UDC y parvient grâce à des fonctionnalités de point de contrôle pour le système de fichiers, une implémentation alternative lorsque le système de fichiers ne prend pas en charge les points de contrôle, une intégration au mécanisme A/B du bootloader tout en prenant en charge les mises à jour non A/B, et une prise en charge de la liaison de version de clé et de la prévention de la restauration de clé.
Impact sur l'utilisateur
La fonctionnalité UDC améliore l'expérience de mise à jour OTA pour les utilisateurs, car moins d'utilisateurs perdent leurs données en cas d'échec d'une mise à jour OTA. Cela peut réduire le nombre d'appels d'assistance des utilisateurs qui rencontrent des problèmes lors du processus de mise à jour. Toutefois, en cas d'échec d'une mise à jour OTA, les utilisateurs peuvent remarquer que l'appareil redémarre plusieurs fois.
Fonctionnement
Fonctionnalité de point de contrôle dans différents systèmes de fichiers
Pour le système de fichiers F2FS, UDC ajoute la fonctionnalité de point de contrôle au noyau Linux 4.20 en amont et la rétroporte à tous les noyaux courants compatibles avec les appareils exécutant Android 10.
Pour les autres systèmes de fichiers, UDC utilise un appareil virtuel de mappeur d'appareil appelé dm_bow pour la fonctionnalité de point de contrôle. dm_bow se situe entre l'appareil et le système de fichiers. Lorsqu'une partition est montée, une commande trim est émise, ce qui entraîne l'émission de commandes trim par le système de fichiers sur tous les blocs libres. dm_bow intercepte ces commandes trim et les utilise pour configurer une liste de blocs libres. Les lectures et les écritures sont ensuite envoyées à l'appareil sans modification, mais avant qu'une écriture ne soit autorisée, les données nécessaires à une restauration sont sauvegardées dans un bloc libre.
Processus de point de contrôle
Lorsqu'une partition avec le flag checkpoint=fs/block est montée, Android appelle restoreCheckpoint sur le lecteur pour permettre à l'appareil de restaurer n'importe quel point de contrôle actuel. init appelle ensuite la fonction needsCheckpoint pour déterminer si l'appareil est dans un état A/B du bootloader ou s'il a défini le nombre de tentatives de mise à jour. Si l'une de ces conditions est remplie, Android appelle createCheckpoint pour ajouter des flags de montage ou créer un appareil dm_bow.
Une fois la partition montée, le code de point de contrôle est appelé pour émettre des commandes trim.
Le processus de démarrage se poursuit ensuite normalement. À LOCKED_BOOT_COMPLETE, Android appelle commitCheckpoint pour valider le point de contrôle actuel, et la mise à jour se poursuit normalement.
Gérer les clés KeyMint (anciennement Keymaster)
Les clés KeyMint sont utilisées pour le chiffrement des appareils ou à d'autres fins. Pour gérer ces clés, Android retarde les appels de suppression de clé jusqu'à ce que le point de contrôle soit validé.
Surveiller l'état
Un daemon d'état vérifie qu'il y a suffisamment d'espace disque pour créer un point de contrôle. Le daemon d'état se trouve dans
cp_healthDaemon
dans Checkpoint.cpp.
Le daemon d'état présente les comportements configurables suivants :
ro.sys.cp_msleeptime: contrôle la fréquence à laquelle l'appareil vérifie l'utilisation du disque.ro.sys.cp_min_free_bytes: contrôle la valeur minimale recherchée par le daemon d'état.ro.sys.cp_commit_on_full: contrôle si le daemon d'état redémarre l'appareil ou valide le point de contrôle et continue lorsque le disque est plein.
API de point de contrôle
Les API de point de contrôle sont utilisées par la fonctionnalité UDC. Pour les autres API utilisées par UDC, consultez
IVold.aidl.
void startCheckpoint(int retry)
Crée un point de contrôle.
Le framework appelle cette méthode lorsqu'il est prêt à démarrer une mise à jour. Le point de contrôle est créé avant que les systèmes de fichiers avec point de contrôle tels que les données utilisateur ne soient montés en lecture/écriture après le redémarrage. Si le nombre de tentatives est positif, l'API gère le suivi des tentatives, et le programme de mise à jour appelle needsRollback pour vérifier si une restauration de la mise à jour est requise. Si le nombre de tentatives est -1, l'API s'en remet au jugement du bootloader A/B.
Cette méthode n'est pas appelée lors d'une mise à jour A/B normale.
void commitChanges()
Valide les modifications.
Le framework appelle cette méthode après le redémarrage lorsque les modifications sont prêtes à être validées. Elle est appelée avant que les données (telles que les photos, les vidéos, les SMS, la réception du serveur) ne soient écrites dans les données utilisateur et avant BootComplete.
Si aucune mise à jour active avec point de contrôle n'existe, cette méthode n'a aucun effet.
abortChanges()
Force le redémarrage et rétablit le point de contrôle. Abandonne toutes les modifications des données utilisateur depuis le premier redémarrage.
Le framework appelle cette méthode après le redémarrage, mais avant commitChanges.
retry_counter est diminué lorsque cette méthode est appelée. Des entrées de journal sont générées.
bool needsRollback()
Détermine si une restauration est requise.
Sur les appareils sans point de contrôle, renvoie false. Sur les appareils avec point de contrôle, renvoie true lors d'un démarrage sans point de contrôle.
Implémenter UDC
Implémentation de référence
Pour obtenir un exemple d'implémentation d'UDC, consultez dm-bow.c.
Pour obtenir de la documentation supplémentaire sur la fonctionnalité, consultez dm-bow.txt.
Configuration
Dans on fs de votre fichier init.hardware.rc, assurez-vous d'avoir :
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
Dans on late-fs de votre fichier init.hardware.rc, assurez-vous d'avoir :
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
Dans votre fichier fstab.hardware, assurez-vous que /data est tagué comme 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
Ajouter une partition de métadonnées
UDC nécessite une partition de métadonnées pour stocker le nombre de tentatives sans bootloader et les clés. Configurez une partition de métadonnées et montez-la de manière anticipée sur /metadata.
Dans votre fichier fstab.hardware, assurez-vous que /metadata est tagué comme earlymount ou first_stage_mount.
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
Initialisez la partition à zéro.
Ajoutez les lignes suivantes à BoardConfig.mk :
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
Mettre à jour les systèmes
Systèmes F2FS
Pour les systèmes qui utilisent F2FS pour mettre en forme les données, assurez-vous que votre version de F2FS prend en charge les points de contrôle. Pour en savoir plus, consultez Fonctionnalité de point de contrôle dans différents systèmes de fichiers.
Ajoutez le checkpoint=fs flag à la section <fs_mgr_flags> de fstab pour l'
appareil monté sur /data.
Systèmes non F2FS
Pour les systèmes non F2FS, dm-bow doit être activé dans la configuration du noyau.
Ajoutez le checkpoint=block flag à la section <fs_mgr_flags> de fstab pour l'
appareil monté sur /data.
Consulter les journaux
Des entrées de journal sont générées lorsque les API de point de contrôle sont appelées.
Validation
Pour tester votre implémentation UDC, exécutez l'ensemble de tests VTS VtsKernelCheckpointTest.