Esta página descreve as mudanças adicionadas ao AOSP para reduzir mudanças desnecessárias de arquivos entre builds. Os implementadores de dispositivos que mantêm os próprios sistemas de compilação podem usar essas informações como um guia para reduzir o tamanho das atualizações over the air (OTA).
Às vezes, as atualizações OTA do Android contêm arquivos alterados que não correspondem às mudanças no código. Na verdade, eles são artefatos do sistema de build. Isso ocorre quando o mesmo código, criado em diferentes vezes, de diferentes diretórios ou máquinas, produz um grande número de . Esses arquivos em excesso aumentam o tamanho de um patch OTA e dificultam a determinação qual código mudou.
Para tornar o conteúdo de uma OTA mais transparente, o AOSP inclui mudanças do sistema de build projetadas para reduzir o tamanho dos patches OTA. Mudanças desnecessárias nos arquivos entre builds foram eliminados, e apenas arquivos relacionados a patches são contidos nas atualizações OTA. O AOSP também inclui uma ferramenta de comparação de builds, que filtra recursos comuns relacionados ao build do arquivo de build para oferecer uma comparação mais limpa do arquivo de compilação e uma Ferramenta de mapeamento de blocos, que ajuda a manter a alocação de blocos consistentes.
Um sistema de build pode criar patches desnecessariamente grandes de várias maneiras. Para mitigar isso, em No Android 8.0 e versões mais recentes, novos recursos foram implementados para reduzir o tamanho do patch para cada diferença de arquivos. As melhorias que reduziram os tamanhos dos pacotes de atualização OTA incluem o seguinte:
-
O uso do ZSTD, um algoritmo de compactação sem perdas de finalidade genérica para
imagens em atualizações de dispositivo não A/B. O ZSTD pode ser personalizado para
taxas de compactação aumentando o nível de compactação. O nível de compressão é definido durante o OTA
hora de geração e pode ser definido passando a sinalização
--vabc_compression_param=zstd,$COMPRESSION_LEVEL
-
Aumentar o tamanho da janela de compactação usada durante o OTA. O tamanho máximo da janela de compactação
podem ser definidas personalizando o parâmetro de build no arquivo
.mk
de um dispositivo. Isso é definida comoPRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
- Uso da recompressão do Puffin, uma ferramenta determinista de aplicação de patches para redução que lida com as funções de compactação e diferença para a geração de atualizações OTA A/B.
-
Alterações no uso da ferramenta de geração de delta, por exemplo, a forma como os
bsdiff
é usada para compactar patches. No Android 9 e versões mais recentes, absdiff
seleciona o algoritmo de compactação que fornece os melhores resultados de compactação para um patch. -
Melhorias no
update_engine
resultou em menos memória consumida quando patches são aplicados para atualizações A/B de dispositivos.
As seções a seguir discutem vários problemas que afetam os tamanhos das atualizações OTA, as soluções delas e exemplos de implementação no AOSP.
Ordem dos arquivos
Problema: os sistemas de arquivos não garantem a ordem dos arquivos quando solicitam uma lista de
arquivos em um diretório, embora normalmente seja o mesmo para o mesmo checkout. Ferramentas como
ls
classifica os resultados por padrão, mas a função curinga usada por comandos como
find
e make
não ordenam. Antes de usar essas ferramentas, você deve classificar
das saídas.
Solução: quando você usa ferramentas como find
e
make
com a função de caractere curinga, classifique a saída desses comandos antes de usar
para resolvê-los com rapidez. Ao usar $(wildcard)
ou $(shell find)
em
Android.mk
, classifique-os também. Algumas ferramentas, como Java, ordenam as entradas, então
antes de classificar os arquivos, verifique se a ferramenta que você está usando ainda não fez isso.
Exemplos:muitas instâncias foram corrigidas no sistema de build principal usando a
integrada all-*-files-under
, que inclui
all-cpp-files-under
(porque várias definições foram espalhadas em outros makefiles).
Para mais detalhes, consulte:
- https://android.googlesource.com/platform/build/+/4d66adfd0e6d599d8502007e4ea9aaf82e95569f
- https://android.googlesource.com/platform/build/+/379f9f9cec4fe1c66b6d60a6c19fecb81b9eb410
- https://android.googlesource.com/platform/build/+/7c3e3f8314eec2c053012dd97d2ae649ebeb5653
- https://android.googlesource.com/platform/build/+/5c64b4e81c1331cab56d8a8c201f26bb263b630c
Diretório do build
Problema: alterar o diretório no qual os itens são criados pode causar
binários sejam diferentes. A maioria dos caminhos no build do Android são relativos.
__FILE__
em C/C++ não é um problema. No entanto, os símbolos de depuração codificam
por padrão, e o .note.gnu.build-id
é gerado a partir do hash
binário pré-retirado, portanto será alterado se os símbolos de depuração mudarem.
Solução:o AOSP agora faz com que os caminhos de depuração sejam relativos. Para mais detalhes, consulte o CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02.
Carimbos de data/hora
Problema:os carimbos de data/hora na saída do build resultam em mudanças desnecessárias no arquivo. Isso provavelmente vai acontecer nos seguintes locais:
__DATE__/__TIME__/__TIMESTAMP__
no código C ou C++.- Carimbos de data/hora incorporados em arquivos baseados em ZIP.
Soluções/exemplos:para remover carimbos de data/hora da saída da compilação, use as instruções fornecidas abaixo __DATE__/__TIME__/__TIMESTAMP__ em C/C++ e Carimbos de data/hora incorporados nos arquivos.
__DATE__/__TIME__/__TIMESTAMP__ em C/C++
Essas macros sempre produzem saídas diferentes para builds diferentes, portanto, não as use. Aqui algumas opções para eliminar essas macros:
- Remova-os. Para ver um exemplo, consulte https://android.googlesource.com/platform/system/core/+/30622bbb209db187f6851e4cf0cdaa147c2fca9f.
- Para identificar exclusivamente o binário em execução, leia o build-id do cabeçalho ELF.
-
Para saber quando o SO foi criado, leia
ro.build.date
. Isso funciona para tudo, exceto builds incrementais, que podem não atualizar essa data). Para ver um exemplo, consulte para https://android.googlesource.com/platform/external/libchrome/+/8b7977ebef84f6b3a3896cd13b4aeacbfa1e0f84
Carimbos de data/hora incorporados em arquivos (zip, jar)
O Android 7.0 corrigiu o problema de carimbos de data/hora incorporados em arquivos ZIP adicionando
-X
para todos os usos do comando zip
. Isso removeu o UID/GID do
e o carimbo de data/hora Unix estendido do arquivo ZIP.
Uma nova ferramenta, ziptime
, localizada em
/platform/build/+/main/tools/ziptime/
) redefine os carimbos de data/hora normais nos cabeçalhos zip. Para mais detalhes, consulte
Arquivo README.
A ferramenta signapk
define carimbos de data/hora para os arquivos APK que podem variar dependendo do
fuso horário do servidor. Para mais detalhes, consulte o CL
https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.
A ferramenta signapk
define carimbos de data/hora para os arquivos APK que podem variar dependendo do
fuso horário do servidor. Para mais detalhes, consulte o CL
https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.
Strings de versão
Problema:as strings da versão do APK geralmente tinham o BUILD_NUMBER
anexado
às versões fixadas no código. Mesmo que nada mais tenha mudado em um APK, como resultado, o APK
ainda seria diferente.
Solução:remova o número da versão da string da versão do APK.
Exemplos:
- https://android.googlesource.com/platform/packages/apps/Camera2/+/5e0f4cf699a4c7c95e2c38ae3babe6f20c258d27
- https://android.googlesource.com/platform/build/+/d75d893da8f97a5c7781142aaa7a16cf1dbb669c
Ativar a computação de verdade no dispositivo
Se dm-verity estiver ativado no dispositivo, as ferramentas OTA escolherão automaticamente a configuração da verificação e ativar a computação de verdade no dispositivo. Isso permite que os blocos de verdade sejam calculados no Android. em vez de serem armazenados como bytes brutos no pacote OTA. Os blocos Verity podem usar com aproximadamente 16 MB para uma partição de 2 GB.
No entanto, computar a verdade no dispositivo pode levar muito tempo. Especificamente, o Encaminhar
O código de correção de erro pode levar muito tempo. Em dispositivos Pixel, esse número tende a levar até 10
minutos. Em dispositivos mais simples, isso pode demorar mais. Se você quiser desativar a versão no dispositivo
computação, mas ainda ativar dm-verity, é possível fazer isso passando
--disable_fec_computation
à ferramenta ota_from_target_files
quando
para gerar uma atualização OTA. Essa flag desativa a computação de verdade no dispositivo durante atualizações OTA.
Diminui o tempo de instalação do OTA, mas aumenta o tamanho do pacote do OTA. Caso seu dispositivo não
tiverem o dm-verity ativado, transmitir essa sinalização não terá efeito.
Ferramentas de build consistentes
Problema: as ferramentas que geram arquivos instalados precisam ser consistentes (um determinado entrada deve sempre produzir a mesma saída).
Soluções/exemplos:foram necessárias alterações nas seguintes ferramentas de compilação:
- Criador do arquivo AVISO. O criador do arquivo AVISO foi alterado para criar coleções de NOTÍCIAS reproduzíveis. Consulte o CL: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64
- Kit Java para Android Compiler (Jack) O conjunto de ferramentas Jack exigia uma atualização para lidar com mudanças ocasionais na ordem do construtor gerado. Acessadores determinísticos para construtores foram adicionados ao conjunto de ferramentas: https://android.googlesource.com/Dataset/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b.
- Compilador ART AOT (dex2oat): O binário do compilador ART recebeu uma atualização que adicionou uma opção para criar uma imagem determinista: https://android.googlesource.com/platform/art/+/ace0dc1dd5480ad458e622085e51583653853fb9.
-
O arquivo libpac.so (V8). Cada build cria uma
/system/lib/libpac.so
, porque o snapshot do V8 muda para cada build. A solução foi remover o snapshot: https://android.googlesource.com/platform/external/v8/+/e537f38c36600fd0f3026adba6b3f4cbcee1fb29. - Arquivos pré-dexopt do aplicativo (.odex). Os arquivos pré-dexopt (.odex) continha padding não inicializado em sistemas de 64 bits. Isso foi corrigido: https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029.
Usar a ferramenta de diferenças de build
Para os casos em que não é possível eliminar mudanças em arquivos relacionadas ao build, o AOSP inclui uma
ferramenta de diferença de build,
target_files_diff.py
para usar na comparação de dois pacotes de arquivos. Essa ferramenta realiza uma diferença recursiva entre dois
builds, excluindo alterações de arquivo comuns relacionadas a builds, como
- Mudanças esperadas na saída do build (por exemplo, devido a uma mudança no número do build).
- Mudanças devido a problemas conhecidos no sistema de build atual.
Para usar a ferramenta de diferenças de build, execute o seguinte comando:
target_files_diff.py dir1 dir2
dir1
e dir2
são diretórios de base que contêm o destino extraído
de configuração para cada build.
Manter a alocação de blocos consistente
Embora o conteúdo de um determinado arquivo permaneça o mesmo entre dois builds, os blocos reais que contêm os dados podem ter mudado. Como resultado, o atualizador deve executar E/S desnecessária para mover os blocos para uma atualização OTA.
Em uma atualização OTA A/B virtual, uma E/S desnecessária pode aumentar muito o espaço de armazenamento necessário para armazenar o snapshot copy-on-write. Em uma atualização OTA não A/B, mover os blocos por uma A atualização OTA contribui para o tempo de atualização, já que há mais E/S devido a movimentos de blocos.
Para resolver esse problema, no Android 7.0, o Google estendeu a ferramenta make_ext4fs
para
mantendo a alocação de blocos consistente entre builds. A ferramenta make_ext4fs
aceita
uma sinalização -d base_fs
opcional que tenta alocar arquivos para os mesmos blocos
ao gerar uma imagem ext4
. Você pode extrair os arquivos de mapeamento de blocos (como
os arquivos de mapa base_fs
) dos arquivos de destino de um build anterior ZIP. Para cada
ext4
, há um arquivo .map
na
diretório IMAGES
(por exemplo, IMAGES/system.map
corresponde ao
system
). Esses base_fs
arquivos podem ser incluídos no check-in e
especificado por PRODUCT_<partition>_BASE_FS_PATH
, como neste exemplo:
PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map
Embora isso não ajude a reduzir o tamanho geral do pacote OTA, ele melhora a atualização OTA desempenho reduzindo a quantidade de E/S. Para atualizações A/B virtuais, ele reduz drasticamente o espaço de armazenamento necessário para aplicar o OTA.
Evitar a atualização de apps
Além de minimizar as diferenças de build, você pode reduzir o tamanho das atualizações OTA excluindo atualizações para apps que recebem atualizações nas app stores. Os APKs geralmente compõem uma parte significativa várias partições em um dispositivo. Incluindo as versões mais recentes dos aplicativos que são atualizados por aplicativo as lojas em uma atualização OTA podem ter um grande impacto nos pacotes OTA e fornecer aos usuários benefício. No momento em que os usuários recebem um pacote OTA, eles podem já ter o app atualizado ou uma versão ainda mais recente, recebida diretamente das app stores.