O formato de contêiner Android Pony EXpress (APEX) foi introduzido no Android 10 e é usada no fluxo de instalação para sistemas de nível inferior módulos. Esse formato facilita as atualizações de componentes do sistema que não se encaixam para o modelo de aplicativo Android padrão. Alguns exemplos de componentes são nativos serviços e bibliotecas, camadas de abstração de hardware (HALs), ambiente de execução (ART) e bibliotecas de classes.
O termo "APEX" também podem se referir a um arquivo APEX.
Contexto
Embora o Android ofereça suporte a atualizações de módulos que se encaixam no app padrão (por exemplo, serviços, atividades) por meio de aplicativos instaladores de pacote (como o app Google Play Store), usando um modelo semelhante para componentes de SO de nível inferior tem as seguintes desvantagens:
- Módulos baseados em APK não podem ser usados no início da sequência de inicialização. O pacote é o repositório central de informações sobre aplicativos e só pode ser iniciado pelo gerenciador de atividades, que fica pronto em um estágio posterior do o procedimento de inicialização.
- O formato APK (especialmente o manifesto) foi projetado para apps Android e os módulos do sistema nem sempre são adequados.
Design
Esta seção descreve o design de alto nível do formato de arquivo APEX e as Gerenciador APEX, que é um serviço que gerencia arquivos APEX.
Para mais informações sobre por que esse design para APEX foi selecionado, consulte Alternativas consideradas no desenvolvimento de APEX.
Formato APEX
Esse é o formato de um arquivo APEX.
Figura 1. Formato de arquivo APEX
No nível superior, um arquivo APEX é um arquivo zip no qual os arquivos são armazenados não compactado e localizado em limites de 4 KB.
Os quatro arquivos em um arquivo APEX são:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
O arquivo apex_manifest.json
contém o nome do pacote e a versão, que
identificar um arquivo APEX. Esta é uma
ApexManifest
buffer de protocolo no formato JSON.
O arquivo AndroidManifest.xml
permite que o arquivo APEX use ferramentas relacionadas ao APK e
como ADB, PackageManager e aplicativos de instalação de pacotes (como
Play Store). Por exemplo, o arquivo APEX pode usar uma ferramenta atual, como aapt
para inspecionar metadados básicos do arquivo. O arquivo contém o nome do pacote e
informações de versão. Essas informações geralmente também estão disponíveis em
apex_manifest.json
:
Recomendamos usar apex_manifest.json
em vez de AndroidManifest.xml
para novos códigos
sistemas que usam APEX. AndroidManifest.xml
pode conter informações adicionais
informações de segmentação que podem ser usadas pelas ferramentas existentes de publicação de apps.
apex_payload.img
é uma imagem do sistema de arquivos ext4 com suporte de dm-verity. A imagem
é montado no ambiente de execução por um dispositivo de loopback. Especificamente, a árvore hash e
bloco de metadados são criados usando a biblioteca libavb
. O payload do sistema de arquivos
não é analisado (porque a imagem deve ser montada no lugar). Arquivos regulares são
incluído no arquivo apex_payload.img
.
apex_pubkey
é a chave pública usada para assinar a imagem do sistema de arquivos. No ambiente de execução,
Essa chave garante que o APEX baixado seja assinado com a mesma entidade
que assina o mesmo APEX nas partições integradas.
Diretrizes de nomenclatura APEX
Para ajudar a evitar conflitos de nomenclatura entre novos APEXs à medida que a plataforma avança, use as seguintes diretrizes de nomenclatura:
com.android.*
- Reservado para APEXs do AOSP. Não é exclusivo de nenhuma empresa ou dispositivo.
com.<companyname>.*
- Reservado para uma empresa. Potencialmente usado por vários dispositivos desse de uma empresa.
com.<companyname>.<devicename>.*
- Reservado para APEXs exclusivos de um dispositivo específico (ou subconjunto de dispositivos).
Gerenciador APEX
O gerenciador APEX (ou apexd
) é um processo nativo autônomo responsável por:
verificar, instalar e desinstalar arquivos APEX. Esse processo é iniciado
está pronta no início da sequência de inicialização. Os arquivos APEX normalmente são pré-instalados em
o dispositivo em /system/apex
. Por padrão, o gerenciador APEX usa essas
pacotes se nenhuma atualização estiver disponível.
A sequência de atualização de um APEX usa o Classe PackageManager e é o seguinte.
- Um arquivo APEX é transferido por download por meio de um aplicativo instalador de pacote, ADB ou outro fonte.
- O gerenciador de pacotes inicia o procedimento de instalação. Ao reconhecer que o arquivo for um APEX, o gerenciador de pacotes transfere o controle para o APEX de projeto.
- O gerenciador APEX verifica o arquivo APEX.
- Se o arquivo APEX for verificado, o banco de dados interno do gerenciador APEX será atualizado para refletir que o arquivo APEX é ativado na próxima inicialização.
- O solicitante de instalação recebe uma transmissão após o pacote bem-sucedido verificação.
- Para continuar a instalação, reinicie o sistema.
Na próxima inicialização, o gerenciador APEX inicia, lê o banco de dados interno e faz o seguinte para cada arquivo APEX listado:
- Verifica o arquivo APEX.
- Cria um dispositivo de loopback a partir do arquivo APEX.
- Cria um dispositivo de bloco mapeador de dispositivo sobre o dispositivo de loopback.
- Monta o dispositivo de bloco mapeador do dispositivo em um caminho exclusivo (por exemplo,
/apex/name@ver
).
Quando todos os arquivos APEX listados no banco de dados interno estiverem montados, o APEX O gerenciador oferece um serviço de vinculação para que outros componentes do sistema consultem informações sobre os arquivos APEX instalados. Por exemplo, o outro sistema podem consultar a lista de arquivos APEX instalados no dispositivo ou consultar caminho exato onde um APEX específico está montado, para que os arquivos possam ser acessados.
Arquivos APEX são arquivos APK
Os arquivos APEX são arquivos APK válidos porque são arquivos zip assinados (usando o
esquema de assinatura de APK) contendo um arquivo AndroidManifest.xml
. Isso permite que o APEX
para usar a infraestrutura de arquivos APK, como um app instalador de pacote,
o utilitário de assinatura e o gerenciador de pacotes.
O arquivo AndroidManifest.xml
dentro de um arquivo APEX é mínimo, consistindo nos
pacote name
, versionCode
e opcionais targetSdkVersion
, minSdkVersion
,
e maxSdkVersion
para uma segmentação refinada. Essas informações permitem que o APEX
arquivos a serem enviados por canais existentes, como aplicativos de instalação de pacotes e
ADB.
Tipos de arquivo compatíveis
O formato APEX oferece suporte aos seguintes tipos de arquivo:
- Bibliotecas compartilhadas nativas
- Executáveis nativos
- Arquivos JAR
- Arquivos de dados
- Arquivos de configuração
Isso não significa que o APEX possa atualizar todos esses tipos de arquivo. Se um arquivo pode ser atualizado depende da plataforma e da estabilidade das definições quais são as interfaces para os tipos de arquivos.
Opções de assinatura
Os arquivos APEX são assinados de duas maneiras. Primeiro, o apex_payload.img
(especificamente,
(o descritor vbmeta anexado a apex_payload.img
) é assinado com uma chave.
Em seguida, todo o APEX é assinado usando o
Esquema de assinatura de APK v3: Duas chaves diferentes são usadas
nesse processo.
No lado do dispositivo, uma chave pública correspondente à chave privada usada para assinar o descritor vbmeta está instalado. O gerenciador APEX usa a chave pública para verificar os APEXs que precisam ser instalados. Cada APEX deve ser assinado com chaves diferentes e é aplicada tanto no build quanto no ambiente de execução.
APEX em partições integradas
Os arquivos APEX podem estar localizados em partições integradas, como /system
. A
já está acima de dm-verity, então os arquivos APEX são montados diretamente
no dispositivo de loopback.
Se um APEX estiver presente em uma partição integrada, ele pode ser atualizado
fornecendo um pacote APEX com o mesmo nome de pacote e um número maior ou igual
ao código de versão. O novo APEX é armazenado em /data
e, assim como os APKs, os
a versão recém-instalada oculta a versão já presente no sistema
partição. Mas, ao contrário dos APKs, a versão recém-instalada do APEX tem apenas
ativado após a reinicialização.
Requisitos do kernel
Para oferecer suporte a módulos de linha principal APEX em um dispositivo Android, os recursos são necessários: o driver de loopback e o dm-verity. O retorno monta a imagem do sistema de arquivos em um módulo APEX e o dm-verity verifica módulo APEX.
O desempenho do driver de loopback e do dm-verity é importante para alcançar bom desempenho do sistema ao usar módulos APEX.
Versões compatíveis do kernel
Os módulos de linha principal APEX são compatíveis com dispositivos que usam as versões 4.4 ou 4.4 do kernel mais alto. Novos dispositivos lançados com o Android 10 ou mais recente precisa usar o kernel versão 4.9 ou superior para oferecer suporte a módulos APEX.
Patches de kernel necessários
Os patches de kernel necessários para oferecer suporte a módulos APEX estão incluídos no árvore comum do Android. Para que os patches sejam compatíveis com APEX, use a versão mais recente da árvore comum do Android.
Kernel versão 4.4
Esta versão só é compatível com dispositivos que fizeram upgrade do Android 9 para o
Android 10 e querem oferecer suporte a módulos APEX. Para conseguir
os patches necessários, uma mesclagem da ramificação android-4.4
é fortemente
recomendado. Esta é uma lista dos patches individuais necessários
para a versão 4.4 do kernel.
- UPSTREAM: loop: adicione ioctl para alterar o tamanho lógico do bloco (4.4).
- BACKPORT: bloco/loop: definir hw_sectors (4.4).
- UPSTREAM: loop: adicione LOOP_SET_BLOCK_SIZE ao ioctl de compatibilidade (4.4).
- ANDROID: mnt: corrigir next_descendent (4.4).
- ANDROID: mnt: a remontagem deve ser propagada para escravos dos escravos (4.4).
- ANDROID: mnt: propagar a remontagem corretamente (4.4).
- Reverter "ANDROID: dm verity: adicionar tamanho mínimo de pré-busca" (4.4).
- UPSTREAM: loop: descarta caches se offset ou block_size forem alterados (4.4).
Versões do kernel 4.9/4.14/4.19
Para conseguir os patches necessários para as versões 4.9/4.14/4.19 do kernel, faça a mesclagem da
a ramificação android-common
.
Opções de configuração do kernel necessárias
A lista a seguir mostra os requisitos de configuração básica para dar suporte Módulos APEX que foram introduzidos no Android 10. Os itens com um asterisco (*) são requisitos do Android 9 e versões anteriores.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
Requisitos de parâmetro de linha de comando do kernel
Para oferecer suporte a APEX, garanta que os parâmetros de linha de comando do kernel atendam aos seguintes requisitos:
loop.max_loop
NÃO pode ser definido- O valor de
loop.max_part
precisa ser menor ou igual a 8
Criar um APEX
Esta seção descreve como criar um APEX usando o sistema de build do Android.
Veja a seguir um exemplo de Android.bp
para um APEX chamado apex.test
.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
Exemplo de apex_manifest.json
:
{
"name": "com.android.example.apex",
"version": 1
}
Exemplo de file_contexts
:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
Tipos de arquivo e locais no APEX
Tipo de arquivo | Local no APEX |
---|---|
Bibliotecas compartilhadas | /lib e /lib64 (/lib/arm de
grupo traduzido em x86) |
Executáveis | /bin |
Bibliotecas Java | /javalib |
Pré-versões | /etc |
Dependências transitivas
Os arquivos APEX incluem automaticamente dependências transitivas de bibliotecas compartilhadas nativas
ou executáveis. Por exemplo, se libFoo
depender de libBar
, as duas bibliotecas serão
incluído quando apenas libFoo
está listado na propriedade native_shared_libs
.
Lidar com várias ABIs
Instalar a propriedade native_shared_libs
para as contas primária e secundária
Interfaces binárias de aplicativo (ABIs, na sigla em inglês) do dispositivo. Se um APEX segmentar dispositivos
com uma única ABI (ou seja, somente 32 ou 64 bits), somente bibliotecas com a
ABI correspondente estejam instaladas.
Instale a propriedade binaries
apenas para a ABI principal do dispositivo, como
descritas abaixo:
- Se o dispositivo tiver apenas 32 bits, somente a variante de 32 bits do binário será instalado.
- Se o dispositivo tiver somente 64 bits, somente a variante de 64 bits do binário será instalado.
Para adicionar um controle refinado sobre as ABIs de binários e bibliotecas nativos,
use o método
multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
propriedades.
first
: corresponde à ABI principal do dispositivo. Esse é o padrão para binários.lib32
: corresponde à ABI de 32 bits do dispositivo, se compatível.lib64
: corresponde à ABI de 64 bits do dispositivo, com suporte.prefer32
: corresponde à ABI de 32 bits do dispositivo, se compatível. Se o ABI de 32 bits não é compatível, corresponde à ABI de 64 bits.both
: corresponde às duas ABIs. Esse é o padrão paranative_shared_libraries
:
As propriedades java
, libraries
e prebuilts
não dependem da ABI.
Este exemplo é para um dispositivo que oferece suporte a 32/64 e não prefere 32:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
assinatura vbmeta
Assine cada APEX com chaves diferentes. Quando uma nova chave for necessária, crie uma
par de chaves públicas/privadas e criar um módulo apex_key
. Use a propriedade key
para
assinar o APEX usando a chave. A chave pública é incluída automaticamente
APEX com o nome avb_pubkey
.
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
No exemplo acima, o nome da chave pública (foo
) torna-se o ID da
de dados. O ID da chave usada para assinar um APEX está escrito no APEX. No ambiente de execução,
O apexd
verifica o APEX usando uma chave pública com o mesmo ID no dispositivo.
Assinatura APEX
Assine APEXs da mesma forma que você assina APKs. assinar APEXs duas vezes; uma vez para
minisistema de arquivos (arquivo apex_payload.img
) e uma vez para o arquivo inteiro.
Para assinar um APEX no nível do arquivo, defina a propriedade certificate
em um dos
de três maneiras:
- Não definido: se nenhum valor for definido, o APEX será assinado com o certificado localizado
às
PRODUCT_DEFAULT_DEV_CERTIFICATE
. Se nenhuma flag for definida, o caminho padrão parabuild/target/product/security/testkey
. <name>
: o APEX é assinado com o certificado<name>
no mesmo comoPRODUCT_DEFAULT_DEV_CERTIFICATE
.:<name>
: o APEX é assinado com o certificado definido pelo Módulo Soong chamado<name>
. O módulo de certificado pode ser definido como segue.
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
Instalar um APEX
Para instalar um APEX, use o ADB.
adb install apex_file_name
adb reboot
Se supportsRebootlessUpdate
estiver definido como true
no apex_manifest.json
e o
o APEX instalado não é usado (por exemplo, os serviços
for interrompido), um novo APEX poderá ser instalado sem precisar ser reiniciado com o
--force-non-staged
.
adb install --force-non-staged apex_file_name
Usar um APEX
Após a reinicialização, o APEX é montado no /apex/<apex_name>@<version>
diretório. Várias versões do mesmo APEX podem ser montadas ao mesmo tempo.
Entre os caminhos de montagem, aquele que corresponde à versão mais recente é
montado na vinculação em /apex/<apex_name>
.
Os clientes podem usar o caminho ativado de vinculação para ler ou executar arquivos do APEX.
Os APEXs normalmente são usados da seguinte forma:
- Um OEM ou ODM pré-carrega um APEX em
/system/apex
quando o dispositivo é enviados. - Os arquivos no APEX são acessados pelo caminho
/apex/<apex_name>/
. - Quando uma versão atualizada do APEX é instalada em
/data/apex
, o caminho aponta para o novo APEX após a reinicialização.
Atualizar um serviço com um APEX
Para atualizar um serviço usando um APEX:
Marque o serviço na partição do sistema como atualizável. Adicionar a opção
updatable
à definição do serviço./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
Crie um novo arquivo
.rc
para o serviço atualizado. Usar a opçãooverride
redefinir o serviço atual./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
As definições de serviço só podem ser definidas no arquivo .rc
de um APEX. Ação
não são suportados em APEXs.
Se um serviço marcado como atualizável começar antes da ativação dos APEXs, o é adiado até que a ativação dos APEXs seja concluída.
Configurar o sistema para oferecer suporte a atualizações APEX
Defina a propriedade do sistema a seguir como true
para oferecer suporte a atualizações de arquivos APEX.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
ou apenas
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
APEX nivelado
Em dispositivos legados, às vezes é impossível ou inviável atualizar
para dar suporte total ao APEX. Por exemplo, o kernel pode ter sido criado
sem CONFIG_BLK_DEV_LOOP=Y
, que é crucial para montar o sistema de arquivos
imagem em um APEX.
APEX nivelado é um APEX especialmente criado que pode ser ativado em dispositivos com
um kernel legado. Arquivos em um APEX nivelado são instalados diretamente em um diretório
na partição integrada. Por exemplo, lib/libFoo.so
em um APEX nivelado
O app my.apex
está instalado no /system/apex/my.apex/lib/libFoo.so
.
A ativação de um APEX nivelado não envolve o dispositivo de loop. Toda a
o diretório /system/apex/my.apex
está diretamente vinculado a /apex/name@ver
.
Não é possível atualizar APEXs nivelados com o download de versões atualizadas dos APEXs da rede porque os APEXs baixados não podem ser simplificados. APEXs nivelados só podem ser atualizados por um OTA normal.
O APEX nivelado é a configuração padrão. Isso significa que todos Por padrão, os APEXs são nivelados, a menos que você configure explicitamente seu dispositivo para construir APEXs não nivelados para suportar atualizações de APEX (como explicado acima).
Misturar APEXs achatados e não nivelados em um dispositivo NÃO é
suporte. Os APEXs em um dispositivo precisam ser todos não nivelados ou todos nivelados.
Isso é especialmente importante ao enviar modelos APEX pré-assinados para
projetos como o Mainline. APEXs que não são pré-assinados (ou seja, criados a partir de
a origem) também não devem ser nivelados e assinados com as chaves adequadas. A
dispositivo deve herdar de updatable_apex.mk
, conforme explicado em
Como atualizar um serviço com um APEX
APEXs compactados
O Android 12 e versões mais recentes têm compactação APEX para reduzindo o impacto no armazenamento de pacotes APEX atualizáveis. Após a atualização O APEX está instalado, embora sua versão pré-instalada não seja mais usada, ele ainda ocupa a mesma quantidade de espaço. O espaço ocupado permanece indisponível.
A compactação APEX minimiza o impacto no armazenamento usando um conjunto altamente compactado
dos arquivos APEX em partições somente leitura (como a partição /system
). Android
12 e posteriores usam um algoritmo de compactação de zip DEFLATE.
A compactação não otimiza o seguinte:
Inicializar APEXs que precisam ser montados bem no início da inicialização sequência.
APEXs não atualizáveis. A compactação só é útil se uma versão atualizada de um APEX estiver instalada na partição
/data
. Uma lista completa de APEXs atualizáveis está disponível na Componentes modulares do sistema página.APEXs de bibliotecas compartilhadas dinâmicas. Como o
apexd
sempre ativa as duas versões do esses APEXs (pré-instalados e atualizados), a compactação deles não agrega valor.
Formato de arquivo APEX compactado
Esse é o formato de um arquivo APEX compactado.
Figura 2. Formato de arquivo APEX compactado
No nível superior, um arquivo APEX compactado é um arquivo zip que contém o arquivo arquivo apex em forma desinfetada com um nível de compactação de 9, e com outros arquivos armazenados sem compactação.
Quatro arquivos compreendem um arquivo APEX:
original_apex
: esvaziado com o nível de compactação de 9 Esse é o arquivo APEX original e descompactado.apex_manifest.pb
: somente armazenadosAndroidManifest.xml
: somente armazenadosapex_pubkey
: somente armazenados
Os arquivos apex_manifest.pb
, AndroidManifest.xml
e apex_pubkey
são
cópias dos arquivos correspondentes em original_apex
.
Compilar APEX compactado
Um APEX compactado pode ser criado usando a ferramenta apex_compression_tool.py
localizada em
system/apex/tools
.
Vários parâmetros relacionados à compactação APEX estão disponíveis no sistema de build.
No Android.bp
, se um arquivo APEX é compactável ou não é controlado pelo
Propriedade compressible
:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
Uma flag de produto PRODUCT_COMPRESSED_APEX
controla se uma imagem do sistema é criada
da fonte deve conter arquivos APEX compactados.
Para experimentação local, você pode forçar um build a compactar APEXs configurando
OVERRIDE_PRODUCT_COMPRESSED_APEX=
para true
.
Os arquivos APEX compactados gerados pelo sistema de build têm a extensão .capex
.
A extensão facilita a distinção entre compactado e descompactado
de um arquivo APEX.
Algoritmos de compactação compatíveis
O Android 12 só oferece suporte à compactação deflate-zip.
Ativar um arquivo APEX compactado durante a inicialização
Antes que um APEX compactado possa ser ativado, o arquivo original_apex
dentro dele
descompactado no diretório /data/apex/decompressed
. O resultado
O arquivo APEX descompactado tem um link físico com o diretório /data/apex/active
.
Considere o exemplo a seguir como uma ilustração do processo descrito acima.
Considere /system/apex/com.android.foo.capex
como um APEX compactado
ativado, com o versionCode 37.
- O arquivo
original_apex
dentro de/system/apex/com.android.foo.capex
é descompactado em/data/apex/decompressed/com.android.foo@37.apex
. restorecon /data/apex/decompressed/com.android.foo@37.apex
é realizado para e verificar se ele tem um rótulo SELinux correto.- As verificações são realizadas
/data/apex/decompressed/com.android.foo@37.apex
para garantir a validade:apexd
verifica a chave pública agrupada/data/apex/decompressed/com.android.foo@37.apex
para verificar se é igual ao empacotado em/system/apex/com.android.foo.capex
. - O arquivo
/data/apex/decompressed/com.android.foo@37.apex
tem um link físico para diretório/data/apex/active/com.android.foo@37.apex
. - A lógica de ativação normal para arquivos APEX descompactados é executada
/data/apex/active/com.android.foo@37.apex
:
Interação com OTA
Arquivos APEX compactados têm implicações na entrega e no aplicativo por OTA. Como uma atualização OTA pode conter um arquivo APEX compactado com um nível de versão superior do que o que está ativo em um dispositivo, uma certa quantidade de espaço livre deve ser reservada antes de reiniciar o dispositivo para aplicar uma atualização OTA.
Para oferecer suporte ao sistema OTA, o apexd
expõe estas duas APIs de vinculação:
calculateSizeForCompressedApex
: calcula o tamanho necessário para descompactar Arquivos APEX em um pacote OTA. Isso pode ser usado para verificar se um dispositivo espaço suficiente antes que um OTA seja baixado.reserveSpaceForCompressedApex
: reserva espaço no disco para uso futuro porapexd
para descompactar arquivos APEX compactados dentro do pacote OTA.
No caso de uma atualização OTA A/B, o apexd
tenta descompactar na
em segundo plano como parte da rotina OTA pós-instalação. Se a descompactação falhar,
O apexd
executa a descompactação durante a inicialização que aplica a OTA
atualizar.
Alternativas consideradas no desenvolvimento de APEX
Aqui estão algumas opções que o AOSP considerou ao projetar o arquivo APEX formato e por que eles foram incluídos ou excluídos.
Sistemas regulares de gerenciamento de pacotes
As distribuições do Linux têm sistemas de gerenciamento de pacotes, como dpkg
e rpm
,
que são poderosas, maduras e robustas. No entanto, elas não estavam
adotadas para APEX porque não podem proteger os pacotes após
e instalação. A verificação é executada somente quando os pacotes estão sendo instalados.
Os invasores podem violar a integridade dos pacotes instalados sem serem notados. Isso é
uma regressão para Android em que todos os componentes do sistema foram armazenados em modo
sistemas de arquivos cuja integridade é protegida por dm-verity para cada E/S. Qualquer um
adulteração de componentes do sistema deve ser proibida ou ser detectável
que a inicialização do dispositivo pode ser recusada se ele for comprometido.
dm-crypt para integridade
Os arquivos em um contêiner APEX são de partições incorporadas (por exemplo, a
/system
) que são protegidas por dm-verity, em que qualquer modificação
os arquivos serão proibidos mesmo depois que as partições forem montadas. Para fornecer
mesmo nível de segurança para os arquivos, todos os arquivos em um APEX são armazenados em um
imagem do sistema pareada com uma árvore de hash e um descritor vbmeta. Sem
dm-verity, um APEX na partição /data
está vulnerável a ataques não intencionais
modificações feitas depois que ele é verificado e instalado.
Na verdade, a partição /data
também é protegida por camadas de criptografia, como:
dm-crypt. Embora isso forneça certo nível de proteção contra adulterações, sua
O objetivo principal é a privacidade, e não a integridade. Quando um invasor tem acesso
/data
, não pode haver mais proteções, e isso novamente é uma
de regressão em comparação com todos os componentes do sistema na partição /system
.
A árvore de hash dentro de um arquivo APEX, junto com dm-verity, fornece os mesmos
nível de proteção de conteúdo.
Redirecionar caminhos de /system para /apex
Arquivos de componentes do sistema empacotados em um APEX são acessíveis por novos caminhos, como
/apex/<name>/lib/libfoo.so
: Quando os arquivos faziam parte de /system
elas eram acessíveis por caminhos como /system/lib/libfoo.so
. Um
de um arquivo APEX (outros arquivos APEX ou a plataforma) deve usar a nova
caminhos de rede. Talvez seja necessário atualizar o código existente como resultado da mudança do caminho.
Embora uma forma de evitar a alteração do caminho seja sobrepor o conteúdo do arquivo em uma
APEX na partição /system
, a equipe do Android decidiu não sobrepor
arquivos na partição /system
, pois isso pode afetar o desempenho da
número de arquivos sendo sobrepostos (possivelmente até mesmo empilhados um após o outro)
aumentou.
Outra opção era invadir funções de acesso a arquivos, como open
, stat
e
readlink
, para que os caminhos que começassem com /system
fossem redirecionados ao
caminhos correspondentes em /apex
. A equipe do Android descartou essa opção
porque é inviável alterar todas as funções que aceitam caminhos.
Por exemplo, alguns apps vinculam estaticamente o Bionic, que implementa as funções.
Nesses casos, esses apps não são redirecionados.