O Android 10 apresenta o User Data Checkpoint (UDC), que permite que o Android volte ao estado anterior quando uma atualização do Android over-the-air (OTA) falha. Com o UDC, se uma atualização do Android OTA falhar, o dispositivo poderá voltar ao estado anterior com segurança. Embora as atualizações A/B resolvam esse problema para inicialização antecipada, a reversão não é suportada quando a partição de dados do usuário (montada em /data
) é modificada.
O UDC permite que o dispositivo reverta a partição de dados do usuário mesmo após ser modificado. O recurso UDC faz isso com recursos de ponto de verificação para o sistema de arquivos, uma implementação alternativa quando o sistema de arquivos não oferece suporte a pontos de verificação, integração com o mecanismo A/B do carregador de inicialização ao mesmo tempo em que oferece suporte a atualizações não A/B e suporte para vinculação de versão de chave e prevenção de reversão de chave.
Impacto do usuário
O recurso UDC melhora a experiência de atualização OTA para os usuários, pois menos usuários perdem seus dados quando uma atualização OTA falha. Isso pode reduzir o número de chamadas de suporte de usuários que enfrentam problemas durante o processo de atualização. No entanto, quando uma atualização OTA falha, os usuários podem notar que o dispositivo é reinicializado várias vezes.
Como funciona
Funcionalidade de ponto de verificação em diferentes sistemas de arquivos
Para o sistema de arquivos F2FS, o UDC adiciona a funcionalidade de ponto de verificação ao kernel Linux 4.20 upstream e o retroporta para todos os kernels comuns suportados por dispositivos que executam o Android 10.
Para outros sistemas de arquivos, o UDC usa um dispositivo virtual mapeador de dispositivo chamado dm_bow
para funcionalidade de ponto de verificação. dm_bow
fica entre o dispositivo e o sistema de arquivos. Quando uma partição é montada, um trim é emitido, fazendo com que o sistema de arquivos emita comandos de trim em todos os blocos livres. dm_bow
intercepta esses trims e os usa para configurar uma lista de bloqueio livre. As leituras e gravações são enviadas para o dispositivo sem modificações, mas antes que uma gravação seja permitida, os dados necessários para uma restauração são copiados para um bloco livre.
Processo de verificação
Quando uma partição com o sinalizador checkpoint=fs/block
é montada, o Android chama restoreCheckpoint
na unidade para permitir que o dispositivo restaure qualquer checkpoint atual. O init
então chama a função needsCheckpoint
para determinar se o dispositivo está em um estado A/B do carregador de inicialização ou definiu a contagem de novas tentativas de atualização. Se um deles for verdadeiro, o Android chama createCheckpoint
para adicionar sinalizadores de montagem ou construir um dispositivo dm_bow
.
Depois que a partição é montada, o código do ponto de verificação é chamado para emitir trims. O processo de inicialização continua normalmente. Em LOCKED_BOOT_COMPLETE
, o Android chama commitCheckpoint
para confirmar o checkpoint atual e a atualização continua normalmente.
Gerenciando chaves mestras
As chaves Keymaster são usadas para criptografia de dispositivos ou outros propósitos. Para gerenciar essas chaves, o Android atrasa as chamadas de exclusão de chave até que o ponto de verificação seja confirmado.
Monitorando a integridade
Um daemon de integridade verifica se há espaço em disco suficiente para criar um ponto de verificação. O daemon de integridade está localizado em cp_healthDaemon
em Checkpoint.cpp
.
O daemon de integridade tem os seguintes comportamentos que podem ser configurados:
-
ro.sys.cp_msleeptime
: Controla a frequência com que o dispositivo verifica o uso do disco. -
ro.sys.cp_min_free_bytes
: Controla o valor mínimo que o daemon de integridade procura. -
ro.sys.cp_commit_on_full
: Controla se o daemon de integridade reinicializa o dispositivo ou confirma o ponto de verificação e continua quando o disco está cheio.
APIs de ponto de verificação
As APIs de ponto de verificação são usadas pelo recurso UDC. Para outras APIs usadas pelo UDC, consulte IVoid.aidl
.
void startCheckpoint(int retry)
Cria um ponto de verificação.
A estrutura chama esse método quando está pronta para iniciar uma atualização. O ponto de verificação é criado antes que os sistemas de arquivos com ponto de verificação, como userdata, sejam montados em R/W após a reinicialização. Se a contagem de novas tentativas for positiva, a API lidará com novas tentativas de rastreamento e o atualizador chamará needsRollback
para verificar se uma reversão da atualização é necessária. Se a contagem de novas tentativas for -1
, a API adiará o julgamento do carregador de inicialização A/B.
Este método não é chamado ao fazer uma atualização A/B normal.
void commitAlterações()
Confirma as alterações.
A estrutura chama esse método após a reinicialização quando as alterações estão prontas para serem confirmadas. Isso é chamado antes que os dados (como fotos, vídeo, SMS, recibo de recebimento do servidor) sejam gravados em userdata e antes BootComplete
.
Se não existir nenhuma atualização de ponto de verificação ativa, esse método não terá efeito.
abortChanges()
Força a reinicialização e reverte para o ponto de verificação. Abandona todas as modificações de dados do usuário desde a primeira reinicialização.
A estrutura chama esse método após a reinicialização, mas antes commitChanges
. retry_counter
é reduzido quando esse método é chamado. As entradas de log são geradas.
bool precisaRollback()
Determina se uma reversão é necessária.
Em dispositivos sem ponto de verificação, retorna false
. Em dispositivos de ponto de verificação, retorna true
durante uma inicialização sem ponto de verificação.
Implementando UDC
Implementação de referência
Para obter um exemplo de como o UDC pode ser implementado, consulte dm-bow.c . Para documentação adicional sobre o recurso, consulte dm-bow.txt .
Configuração
Em on fs
em seu arquivo init.hardware.rc
, certifique-se de ter:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
Em on late-fs
em seu arquivo init.hardware.rc
, certifique-se de ter:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
Em seu arquivo fstab.hardware
, certifique-se de que /data
esteja marcado como 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
Adicionando partição de metadados
O UDC requer uma partição de metadados para armazenar as chaves e a contagem de novas tentativas do não carregador de inicialização. Configure uma partição de metadados e monte-a antecipadamente em /metadata
.
Em seu arquivo fstab.hardware
, certifique-se de que /metadata
esteja marcado como earlymount
ou first_stage_mount
.
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
Inicialize a partição com todos os zeros.
Adicione as seguintes linhas ao BoardConfig.mk
:
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
Atualizando sistemas
Sistemas F2FS
Para sistemas que usam F2FS para formatar dados, verifique se sua versão do F2FS oferece suporte a pontos de verificação. Para obter mais informações, consulte Funcionalidade de ponto de verificação em diferentes sistemas de arquivos .
Adicione o sinalizador checkpoint=fs
à seção <fs_mgr_flags>
do fstab para o dispositivo montado em /data
.
Sistemas não F2FS
Para sistemas não F2FS, dm-bow
deve estar habilitado na configuração do kernel.
Adicione o sinalizador checkpoint=block
à seção <fs_mgr_flags>
do fstab para o dispositivo montado em /data
.
Verificando registros
As entradas de log são geradas quando as APIs do Checkpoint são chamadas.
Validação
Para testar sua implementação de UDC, execute o conjunto de testes VTS VtsKernelCheckpointTest
.