perguntas frequentes

O Google usou OTAs A/B em algum dispositivo?

Sim. O nome de marketing para atualizações A/B é atualizações contínuas . Os telefones Pixel e Pixel XL de outubro de 2016 foram enviados com A/B, e todos os Chromebooks usam a mesma implementação update_engine de A/B. A implementação do código de plataforma necessária é pública no Android 7.1 e superior.

Por que as OTAs A/B são melhores?

As OTAs A/B proporcionam uma melhor experiência do usuário ao fazer atualizações. Medições de atualizações de segurança mensais mostram que esse recurso já provou ser um sucesso: em maio de 2017, 95% dos proprietários do Pixel estavam executando a atualização de segurança mais recente após um mês, em comparação com 87% dos usuários do Nexus, e os usuários do Pixel atualizam mais cedo do que os usuários do Nexus. Falhas na atualização de blocos durante uma OTA não resultam mais em um dispositivo que não inicializa; até que a nova imagem do sistema seja inicializada com sucesso, o Android mantém a capacidade de retornar à imagem anterior do sistema em funcionamento.

Como o A/B afetou os tamanhos de partição do Pixel de 2016?

A tabela a seguir contém detalhes sobre a configuração A/B de envio versus a configuração não A/B testada internamente:

Tamanhos de partição de pixel A/B Não A/B
Bootloader 50*2 50
Bota 32*2 32
Recuperação 0 32
Cache 0 100
Rádio 70*2 70
Fornecedor 300*2 300
Sistema 2048*2 4096
Total 5000 4680

As atualizações A/B exigem um aumento de apenas 320 MiB em flash, com uma economia de 32 MiB com a remoção da partição de recuperação e outros 100 MiB preservados com a remoção da partição de cache. Isso equilibra o custo das partições B para o carregador de inicialização, a partição de inicialização e a partição de rádio. A partição do fornecedor dobrou de tamanho (a grande maioria do aumento de tamanho). A imagem do sistema A/B do Pixel tem metade do tamanho da imagem original do sistema não A/B.

Para as variantes Pixel A/B e não A/B testadas internamente (somente A/B enviado), o espaço usado diferia em apenas 320MiB. Em um dispositivo de 32 GiB, isso é pouco menos de 1%. Para um dispositivo de 16 GiB, isso seria menos de 2% e, para um dispositivo de 8 GiB, quase 4% (supondo que todos os três dispositivos tivessem a mesma imagem do sistema).

Por que você não usou o SquashFS?

Experimentamos o SquashFS, mas não conseguimos atingir o desempenho desejado para um dispositivo de última geração. Não usamos nem recomendamos o SquashFS para dispositivos portáteis.

Mais especificamente, o SquashFS forneceu cerca de 50% de economia de tamanho na partição do sistema, mas a grande maioria dos arquivos que compactaram bem foram os arquivos .odex pré-compilados. Esses arquivos tinham taxas de compactação muito altas (aproximando-se de 80%), mas a taxa de compactação para o restante da partição do sistema era muito menor. Além disso, o SquashFS no Android 7.0 levantou as seguintes preocupações de desempenho:

  • Pixel tem flash muito rápido em comparação com dispositivos anteriores, mas não um grande número de ciclos de CPU sobressalentes, portanto, ler menos bytes do flash, mas precisar de mais CPU para E/S, era um gargalo potencial.
  • As alterações de E/S que funcionam bem em um benchmark artificial executado em um sistema descarregado às vezes não funcionam bem em casos de uso do mundo real sob carga do mundo real (como criptografia no Nexus 6).
  • O benchmarking mostrou regressões de 85% em alguns lugares.

À medida que o SquashFS amadurece e adiciona recursos para reduzir o impacto da CPU (como uma lista de permissões de arquivos comumente acessados ​​que não devem ser compactados), continuaremos a avaliá-lo e oferecer recomendações aos fabricantes de dispositivos.

Como você reduziu pela metade o tamanho da partição do sistema sem o SquashFS?

Os aplicativos são armazenados em arquivos .apk, que na verdade são arquivos ZIP. Cada arquivo .apk contém um ou mais arquivos .dex contendo bytecode Dalvik portátil. Um arquivo .odex (.dex otimizado) fica separado do arquivo .apk e pode conter código de máquina específico para o dispositivo. Se um arquivo .odex estiver disponível, o Android poderá executar aplicativos em velocidades compiladas antecipadamente sem ter que esperar que o código seja compilado toda vez que o aplicativo for iniciado. Um arquivo .odex não é estritamente necessário: o Android pode realmente executar o código .dex diretamente por meio de interpretação ou compilação Just-In-Time (JIT), mas um arquivo .odex fornece a melhor combinação de velocidade de inicialização e velocidade de tempo de execução se espaço está disponível.

Exemplo: para o arquivoinstalled-files.txt de um Nexus 6P executando o Android 7.1 com um tamanho total de imagem do sistema de 2628MiB (2755792836 bytes), a divisão dos maiores contribuintes para o tamanho geral da imagem do sistema por tipo de arquivo é a seguinte:

.odex 1391770312 bytes 50,5%
.apk 846878259 bytes 30,7%
.so (código C/C++ nativo) 202162479 bytes 7,3%
arquivos .oat/imagens .art 163892188 bytes 5,9%
Fontes 38952361 bytes 1,4%
dados de localidade icu 27468687 bytes 0,9%

Esses números também são semelhantes para outros dispositivos, portanto, em dispositivos Nexus/Pixel, os arquivos .odex ocupam aproximadamente metade da partição do sistema. Isso significava que poderíamos continuar a usar o ext4, mas gravar os arquivos .odex na partição B na fábrica e copiá-los para /data na primeira inicialização. O armazenamento real usado com ext4 A/B é idêntico ao SquashFS A/B, porque se tivéssemos usado SquashFS teríamos enviado os arquivos .odex pré-optados em system_a em vez de system_b.

Copiar arquivos .odex para /data não significa que o espaço salvo em /system é perdido em /data?

Não exatamente. No Pixel, a maior parte do espaço ocupado pelos arquivos .odex é para aplicativos, que normalmente existem em /data . Esses aplicativos recebem atualizações do Google Play, portanto, os arquivos .apk e .odex na imagem do sistema não são usados ​​durante a maior parte da vida útil do dispositivo. Esses arquivos podem ser totalmente excluídos e substituídos por pequenos arquivos .odex orientados por perfil quando o usuário realmente usa cada aplicativo (assim não exigindo espaço para aplicativos que o usuário não usa). Para obter detalhes, consulte a palestra do Google I/O 2016 The Evolution of Art .

A comparação é difícil por algumas razões principais:

  • Os aplicativos atualizados pelo Google Play sempre tiveram seus arquivos .odex em /data assim que receberam a primeira atualização.
  • Os aplicativos que o usuário não executa não precisam de um arquivo .odex.
  • A compilação orientada por perfil gera arquivos .odex menores do que a compilação antecipada (porque a primeira otimiza apenas o código de desempenho crítico).

Para obter detalhes sobre as opções de ajuste disponíveis para OEMs, consulte Configurando o ART .

Não existem duas cópias dos arquivos .odex em /data?

É um pouco mais complicado... Depois que a nova imagem do sistema foi escrita, a nova versão do dex2oat é executada nos novos arquivos .dex para gerar os novos arquivos .odex. Isso ocorre enquanto o sistema antigo ainda está em execução, portanto, os arquivos .odex antigos e novos estão em /data ao mesmo tempo.

O código em OtaDexoptService ( frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptService.java ) chama getAvailableSpace antes de otimizar cada pacote para evitar o preenchimento excessivo de /data . Observe que disponível aqui ainda é conservador: é a quantidade de espaço restante antes de atingir o limite normal de pouco espaço do sistema (medido como porcentagem e contagem de bytes). Portanto, se /data estiver cheio, não haverá duas cópias de cada arquivo .odex. O mesmo código também tem um BULK_DELETE_THRESHOLD: Se o dispositivo chegar tão perto de preencher o espaço disponível (como descrito acima), os arquivos .odex pertencentes aos aplicativos que não são usados ​​são removidos. Esse é outro caso sem duas cópias de cada arquivo .odex.

No pior caso, em que /data está completamente cheio, a atualização espera até que o dispositivo seja reinicializado no novo sistema e não precise mais dos arquivos .odex do sistema antigo. O PackageManager lida com isso: ( frameworks/base/+/master/services/core/java/com/android/server/pm/PackageManagerService.java#7215 ). Após a inicialização bem-sucedida do novo sistema, installd ( frameworks/native/+/master/cmds/installd/dexopt.cpp#2422 ) pode remover os arquivos .odex que foram usados ​​pelo sistema antigo, retornando o dispositivo ao estado estável onde há apenas uma cópia.

Portanto, embora seja possível que /data contenha duas cópias de todos os arquivos .odex, (a) isso é temporário e (b) ocorre apenas se você tiver bastante espaço livre em /data qualquer maneira. Exceto durante uma atualização, há apenas uma cópia. E como parte dos recursos gerais de robustez do ART, ele nunca preencherá /data com arquivos .odex de qualquer maneira (porque isso também seria um problema em um sistema não A/B).

Toda essa escrita/cópia não aumenta o desgaste do flash?

Apenas uma pequena parte do flash é reescrita: uma atualização completa do sistema Pixel grava cerca de 2,3 GiB. (Os aplicativos também são recompilados, mas isso também vale para não A/B.) Tradicionalmente, OTAs completos baseados em blocos gravavam uma quantidade semelhante de dados, portanto, as taxas de desgaste do flash devem ser semelhantes.

A atualização de duas partições do sistema aumenta o tempo de atualização de fábrica?

Não. O pixel não aumentou o tamanho da imagem do sistema (apenas dividiu o espaço em duas partições).

Manter os arquivos .odex em B não torna a reinicialização lenta após a redefinição dos dados de fábrica?

Sim. Se você realmente usou um dispositivo, fez uma OTA e executou uma redefinição de dados de fábrica, a primeira reinicialização será mais lenta do que seria de outra forma (1m40s vs 40s em um Pixel XL) porque os arquivos .odex serão perdidos de B após o primeiro OTA e, portanto, não pode ser copiado para /data . Essa é a troca.

A redefinição de dados de fábrica deve ser uma operação rara quando comparada à inicialização normal, portanto, o tempo gasto é menos importante. (Isso não afeta os usuários ou revisores que obtêm seus dispositivos de fábrica, porque nesse caso a partição B está disponível.) O uso do compilador JIT significa que não precisamos recompilar tudo , então não é tão ruim quanto você pode pensar. Também é possível marcar aplicativos como exigindo compilação antecipada usando coreApp="true" no manifesto: ( frameworks/base/+/master/packages/SystemUI/AndroidManifest.xml#23 ). Isso é usado atualmente pelo system_server porque não é permitido JIT por motivos de segurança.

Manter arquivos .odex em /data em vez de /system torna a reinicialização lenta após um OTA?

Não. Conforme explicado acima, o novo dex2oat é executado enquanto a imagem do sistema antigo ainda está em execução para gerar os arquivos que serão necessários para o novo sistema. A atualização não é considerada disponível até que o trabalho seja feito.

Podemos (devemos) enviar um dispositivo A/B de 32 GiB? 16GiB? 8 GiB?

32GiB funciona bem como foi comprovado no Pixel, e 320MiB de 16GiB significa uma redução de 2%. Da mesma forma, 320MiB de 8GiB uma redução de 4%. Obviamente, A/B não seria a escolha recomendada em dispositivos com 4GiB, pois a sobrecarga de 320MiB é quase 10% do espaço total disponível.

O AVB2.0 requer OTAs A/B?

Não. A inicialização verificada do Android sempre exigiu atualizações baseadas em blocos, mas não necessariamente atualizações A/B.

As OTAs A/B requerem AVB2.0?

Não.

Os OTAs A/B quebram a proteção contra reversão do AVB2.0?

Não. Há alguma confusão aqui porque se um sistema A/B falhar ao inicializar na nova imagem do sistema, ele (após um certo número de tentativas determinado pelo seu bootloader) reverterá automaticamente para a imagem "anterior" do sistema. O ponto-chave aqui, porém, é que "anterior" no sentido A/B ainda é a imagem "atual" do sistema. Assim que o dispositivo inicializa com êxito uma nova imagem, a proteção contra reversão é ativada e garante que você não possa voltar. Mas até que você realmente inicialize com sucesso a nova imagem, a proteção contra reversão não a considera como a imagem atual do sistema.

Se você estiver instalando uma atualização enquanto o sistema está em execução, isso não é lento?

Com atualizações não A/B, o objetivo é instalar a atualização o mais rápido possível porque o usuário está esperando e não pode usar seu dispositivo enquanto a atualização é aplicada. Com atualizações A/B, o oposto é verdadeiro; como o usuário ainda está usando seu dispositivo, o objetivo é o menor impacto possível, portanto, a atualização é deliberadamente lenta. Por meio da lógica no cliente de atualização do sistema Java (que para o Google é GmsCore, o pacote principal fornecido pelo GMS), o Android também tenta escolher um horário em que os usuários não estejam usando seus dispositivos. A plataforma suporta pausar/retomar a atualização, e o cliente pode usar isso para pausar a atualização se o usuário começar a usar o dispositivo e retomá-lo quando o dispositivo estiver ocioso novamente.

Há duas fases ao fazer uma OTA, mostradas claramente na interface do usuário como Etapa 1 de 2 e Etapa 2 de 2 na barra de progresso. A etapa 1 corresponde à gravação dos blocos de dados, enquanto a etapa 2 é a pré-compilação dos arquivos .dex. Essas duas fases são bastante diferentes em termos de impacto no desempenho. A primeira fase é a E/S simples. Isso requer pouco em termos de recursos (RAM, CPU, E/S) porque está apenas copiando lentamente os blocos.

A segunda fase executa o dex2oat para pré-compilar a nova imagem do sistema. Isso obviamente tem limites menos claros em seus requisitos porque compila aplicativos reais. E obviamente há muito mais trabalho envolvido na compilação de um aplicativo grande e complexo do que em um aplicativo pequeno e simples; enquanto na fase 1 não há blocos de disco maiores ou mais complexos que outros.

O processo é semelhante a quando o Google Play instala uma atualização de aplicativo em segundo plano antes de mostrar a notificação de atualização dos 5 aplicativos , como vem sendo feito há anos.

E se um usuário estiver realmente esperando a atualização?

A implementação atual no GmsCore não faz distinção entre atualizações em segundo plano e atualizações iniciadas pelo usuário, mas pode fazer isso no futuro. No caso em que o usuário solicitou explicitamente a instalação da atualização ou está observando a tela de progresso da atualização, priorizaremos o trabalho de atualização supondo que ele esteja aguardando ativamente a conclusão.

O que acontece se houver uma falha ao aplicar uma atualização?

Com atualizações não A/B, se uma atualização não fosse aplicada, o usuário geralmente ficava com um dispositivo inutilizável. A única exceção era se a falha ocorresse antes mesmo de um aplicativo ser iniciado (porque o pacote falhou na verificação, digamos). Com atualizações A/B, uma falha ao aplicar uma atualização não afeta o sistema em execução no momento. A atualização pode simplesmente ser repetida mais tarde.

Quais sistemas em um chip (SoCs) suportam A/B?

A partir de 15/03/2017, temos as seguintes informações:

Android 7.xe anteriores Android 8.xe posterior
Qualcomm Dependendo das solicitações do OEM Todos os chipsets terão suporte
Mediatek Dependendo das solicitações do OEM Todos os chipsets terão suporte

Para obter detalhes sobre horários, verifique com seus contatos do SoC. Para SoCs não listados acima, entre em contato diretamente com seu SoC.