O Android 10 apresenta o Checkpoint de dados do usuário (UDC, na sigla em inglês), que
permite que o Android seja revertido ao estado anterior quando uma atualização OTA
falha. Com o UDC, se uma atualização OTA do Android falhar, o dispositivo poderá
ser revertido com segurança para o estado anterior. Embora
atualizações A/B resolvam esse problema para inicialização antecipada, não há suporte para
reversão 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 depois de ser modificado. O recurso UDC faz isso com funcionalidades de checkpoint para o uma implementação alternativa quando o sistema de arquivos não oferecer suporte checkpoints, a integração com o mecanismo A/B do carregador de inicialização, além de suporte atualizações não A/B e suporte para vinculação de versão de chave e reversão de chave prevenção.
Impacto no usuário
O recurso UDC melhora a experiência de atualização OTA para os usuários, já que menos usuários perdem os 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 OTA falha, os usuários podem notar que o dispositivo reinicia várias vezes.
Como funciona
Funcionalidade de checkpoint 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 a envia de volta para todos os kernels comuns aceitos 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 a funcionalidade do checkpoint. 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. O dm_bow
intercepta esses cortes e os usa
para configurar uma lista de bloqueios gratuita. As leituras e gravações são enviadas ao dispositivo
sem modificações, mas antes que uma gravação seja permitida, os dados necessários para uma restauração são
armazenados em um bloco livre.
Processo de checkpoint
Quando uma partição com a flag checkpoint=fs/block
é montada, o Android chama
restoreCheckpoint
na unidade para permitir que o dispositivo restaure qualquer checkpoint
atual. Em seguida, init
chama a função needsCheckpoint
para determinar se
o dispositivo está no estado A/B do carregador de inicialização ou definiu a configuração
contagem. Se uma delas for verdadeira, o Android chamará createCheckpoint
para adicionar a montagem.
ou criar um dispositivo dm_bow
.
Depois que a partição é montada, o código de ponto de verificação é chamado para emitir cortes.
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.
Gerenciar chaves mestras
As chaves do Keymaster são usadas para criptografia de dispositivos ou outras finalidades. Para gerenciar chaves, o Android atrasa as chamadas de exclusão de chaves até que o checkpoint seja confirmado.
Monitorar a integridade
Um daemon de integridade verifica se há espaço em disco suficiente para criar
de segurança. 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 reinicia o dispositivo ou confirma o ponto de verificação e continua quando o disco está cheio.
APIs do Checkpoint
As APIs de checkpoint são usadas pelo recurso UDC. Para outras APIs usadas pelo UDC, consulte
IVold.aidl
void startCheckpoint(int retry)
Cria um ponto de controle.
O framework chama esse método quando está pronto para iniciar uma atualização. O
checkpoint é criado antes que sistemas de arquivos com checkpoint, como userdata, sejam
montados em R/W após a reinicialização. Se a contagem de novas tentativas for positiva, a API vai processar
as novas tentativas de rastreamento, e o atualizador vai chamar needsRollback
para verificar se é necessário fazer um rollback
da atualização. Se a contagem de novas tentativas for -1
, a API vai adiar para a
do carregador de inicialização.
Esse método não é chamado ao fazer uma atualização A/B normal.
void commitChanges()
Faz o commit das alterações.
O framework chama esse método após a reinicialização, quando as mudanças estão prontas para serem
comprometido. Isso é chamado antes que os dados (como imagens, vídeos, SMS, recibo de
servidor) sejam gravados no userdata e antes de BootComplete
.
Se não houver uma atualização ativa com ponto de verificação, 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 userdata desde a primeira reinicialização.
O framework chama esse método após a reinicialização, mas antes de commitChanges
.
retry_counter
é diminuído quando esse método é chamado. As entradas de registro
gerada.
bool needRollback()
Determina se uma reversão é necessária.
Em dispositivos sem ponto de verificação, retorna false
. Em dispositivos de checkpoint, retorna true
durante uma inicialização sem checkpoint.
Implementar UDC
Implementação de referência
Para conferir um exemplo de como o UDC pode ser implementado, consulte dm-bow.c (link em inglês). Para acessar a documentação adicional sobre o recurso, consulte dm-bow.txt.
Configurar
Em on fs
, no arquivo init.hardware.rc
, verifique se você tem:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
Em on late-fs
, no arquivo init.hardware.rc
, verifique se você tem:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
No arquivo fstab.hardware
, verifique se /data
está 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
Adicionar partição de metadados
A UDC exige uma partição de metadados para armazenar a contagem de novas tentativas de não inicialização e
as chaves. Configure uma partição de metadados e ative-a antecipadamente em /metadata
.
No arquivo fstab.hardware
, verifique se /metadata
está marcado como earlymount
ou first_stage_mount
.
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
Inicializa a partição com todos os zeros.
Adicione as linhas abaixo a BoardConfig.mk
:
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
Atualizar sistemas
Sistemas F2FS
Para sistemas que usam o F2FS para formatar dados, verifique se a versão do F2FS oferece suporte a pontos de verificação. Para mais informações, consulte Funcionalidade de ponto de verificação em diferentes sistemas de arquivos.
Adicione a sinalização checkpoint=fs
à seção <fs_mgr_flags>
do fstab para o
dispositivo montado em /data
.
Sistemas que não são F2FS
Para sistemas não F2FS, dm-bow
precisa estar ativado na configuração do kernel.
Adicione a sinalização checkpoint=block
à seção <fs_mgr_flags>
do fstab para o
dispositivo montado em /data
.
Verificar registros
As entradas de registro são geradas quando as APIs de Checkpoint são chamadas.
Validação
Para testar a implementação de UDC, execute o conjunto VtsKernelCheckpointTest
de VTS
provas.