Perguntas frequentes

O Google usou A/B OTAs 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 fornecidos 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 fornecem uma melhor experiência do usuário ao fazer atualizações. As medições das 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 estão 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 antes dos usuários do Nexus. Falhas na atualização de blocos durante um 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 retém a capacidade de retornar à imagem do sistema de trabalho anterior.

Como o A/B afetou os tamanhos de partição do Pixel 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 requerem um aumento de apenas 320 MiB em flash, com uma economia de 32MiB com a remoção da partição de recuperação e outros 100MiB preservados com a remoção da partição de cache. Isso equilibra o custo das partições B para o bootloader, 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 diferiu em apenas 320MiB. Em um dispositivo de 32 GiB, isso é pouco menos de 1%. Para um dispositivo de 16GiB, isso seria inferior a 2% e, para um dispositivo de 8GiB, 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 obter o desempenho desejado para um dispositivo de última geração. Não usamos ou 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 esmagadora maioria dos arquivos bem compactados 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 do restante da partição do sistema era muito menor. Além disso, o SquashFS no Android 7.0 levantou as seguintes questões de desempenho:

  • O Pixel tem um flash muito rápido em comparação com os 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 possível gargalo.
  • 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 branca 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 tem dentro dele um ou mais arquivos .dex contendo bytecode Dalvik portátil. Um arquivo .odex (.dex otimizado) vive separadamente 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 de compilação antecipadas 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 arquivo-instalado.txt de um Nexus 6P executando o Android 7.1 com um tamanho total de imagem do sistema de 2.628 MiB (2.755.792.836 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 depois 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 o SquashFS, teríamos enviado os arquivos .odex pré-optados em system_a em vez de system_b.

Copiar arquivos .odex para /data significa que o espaço economizado 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 controlados por perfil quando o usuário realmente usa cada aplicativo (portanto, não requer 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 alguns motivos principais:

  • Os aplicativos atualizados pelo Google Play sempre tiveram seus arquivos .odex em /data assim que receberam sua 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 há 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/+/main/services/core/java/com/android/server/pm/OtaDexoptService.java ) chama getAvailableSpace antes de otimizar cada pacote para evitar o preenchimento excessivo /data . Observe que disponível aqui ainda é conservador: é a quantidade de espaço restante antes de atingir o limite de espaço baixo do sistema usual (medido como uma porcentagem e uma contagem de bytes). Portanto, se /data estiver cheio, não haverá duas cópias de cada arquivo .odex. O mesmo código também possui um BULK_DELETE_THRESHOLD: Se o dispositivo chegar tão perto de preencher o espaço disponível (como acabamos de descrever), os arquivos .odex pertencentes a aplicativos que não são usados ​​são removidos. Esse é outro caso sem duas cópias de cada arquivo .odex.

No pior caso, quando /data estiver completamente cheio, a atualização aguardará 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/+/main/services/core/java/com/android/server/pm/PackageManagerService.java#7215 ). Depois que o novo sistema for inicializado com sucesso, installd ( frameworks/native/+/main/cmds/installd/dexopt.cpp#2422 ) pode remover os arquivos .odex que foram usados ​​pelo sistema antigo, retornando o dispositivo de volta 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 . 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 é verdade para não-A/B.) Tradicionalmente, os OTAs completos baseados em blocos gravavam uma quantidade semelhante de dados, portanto, as taxas de desgaste do flash devem ser semelhantes.

O flash de duas partições do sistema aumenta o tempo de flash de fábrica?

Não. Pixel não aumentou no 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, pegou um 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 terão sido perdidos de B após o primeiro OTA e, portanto, não pode ser copiado para /data . Essa é a compensação.

A redefinição dos 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/+/main/packages/SystemUI/AndroidManifest.xml#23 ). Isso é usado atualmente pelo system_server porque não é permitido para JIT por motivos de segurança.

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

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 concluído.

Podemos (devemos) enviar um dispositivo A/B de 32GiB? 16 GiB? 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.

AVB2.0 requer A/B OTAs?

Não. O Android Verified Boot sempre exigiu atualizações baseadas em blocos, mas não necessariamente atualizações A/B.

Os 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 (depois de algumas tentativas determinadas pelo seu gerenciador de inicialização) reverterá automaticamente para a imagem do sistema "anterior". O ponto-chave aqui, porém, é que "anterior" no sentido A/B ainda é, na verdade, a imagem do sistema "atual". Assim que o dispositivo inicializa com sucesso uma nova imagem, a proteção contra reversão entra em ação e garante que você não possa voltar atrás. Mas até que você inicialize com sucesso a nova imagem, a proteção contra reversão não a considera 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 do 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á-la quando o dispositivo estiver ocioso novamente.

Existem 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 poucos recursos (RAM, CPU, E/S) porque está apenas copiando lentamente os blocos.

A segunda fase executa 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 5 aplicativos atualizados , como vem sendo feito há anos.

E se um usuário estiver realmente esperando pela 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á assistindo à tela de progresso da atualização, priorizaremos o trabalho de atualização supondo que ele esteja esperando ativamente que ela seja concluída.

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 ao verificar, por exemplo). Com atualizações A/B, uma falha na aplicação de 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 2017-03-15, temos a seguinte informação:

Android 7.x e anteriores Android 8.x e 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 detalhes sobre horários, verifique com seus contatos SoC. Para SoCs não listados acima, entre em contato diretamente com seu SoC.