O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Formato de arquivo APEX

O formato de contêiner Android Pony EXpress (APEX) foi introduzido no Android 10 e é usado no fluxo de instalação para módulos de sistema de nível inferior. Este formato facilita as atualizações de componentes do sistema que não se encaixam no modelo de aplicativo Android padrão. Alguns componentes são exemplo serviços nativos e bibliotecas, camadas de captação de hardware ( HALs ), de tempo de execução ( ART ), e bibliotecas de classes.

O termo "APEX" também pode se referir a um arquivo APEX.

Fundo

Embora o Android suporte atualizações de módulos que se encaixam no modelo de aplicativo padrão (por exemplo, serviços, atividades) por meio de aplicativos instaladores de pacote (como o aplicativo Google Play Store), usar um modelo semelhante para componentes de sistema operacional 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 gerenciador de pacotes é o repositório central de informações sobre os aplicativos e só pode ser iniciado a partir do gerenciador de atividades, que fica pronto em uma etapa posterior do procedimento de boot.
  • O formato APK (particularmente o manifesto) é projetado para aplicativos Android e os módulos do sistema nem sempre são adequados.

Projeto

Esta seção descreve o design de alto nível do formato de arquivo APEX e do gerenciador APEX, que é um serviço que gerencia arquivos APEX.

Para mais informações sobre por que este projeto para APEX foi selecionado, consulte Alternativas considerados no desenvolvimento de APEX .

Formato APEX

Este é o formato de um arquivo APEX.

Formato de arquivo APEX

Formato de arquivo Figura 1. APEX

No nível superior, um arquivo APEX é um arquivo zip no qual os arquivos são armazenados descompactados e localizados 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 apex_manifest.json arquivo contém o nome do pacote e versão, que identificam um arquivo APEX.

O AndroidManifest.xml arquivo permite que o arquivo APEX de usar ferramentas APK-relacionados e infra-estrutura como ADB, PackageManager e aplicativos do instalador do pacote (como Play Store). Por exemplo, o arquivo APEX pode usar uma ferramenta existente, como aapt para inspecionar metadados básicos a partir do arquivo. O arquivo contém o nome do pacote e informações sobre a versão. Esta informação é geralmente também disponível em apex_manifest.json .

apex_manifest.json é recomendado sobre AndroidManifest.xml para novo código e sistemas que lidam com a APEX. AndroidManifest.xml pode conter informações segmentação adicional que pode ser usado pelas ferramentas de publicação aplicativo existentes.

apex_payload.img é uma imagem ext4 sistema de arquivos apoiados por dm-verdade. A imagem é montada em tempo de execução por meio de um dispositivo de loopback. Especificamente, a árvore de hash e bloco de metadados são criados usando o libavb biblioteca. A carga do sistema de arquivos não é analisada (porque a imagem deve ser montada no local). Arquivos regulares estão incluídos dentro do apex_payload.img arquivo.

apex_pubkey é a chave pública usada para assinar a imagem do sistema de arquivos. No tempo 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.

Gerente APEX

O gerente APEX (ou apexd ) é um processo nativo autônomo responsável por verificar, instalar e desinstalar os arquivos APEX. Este processo é iniciado e está pronto no início da sequência de inicialização. Arquivos APEX são normalmente pré-instalado no dispositivo em /system/apex . O gerenciador APEX padroniza para usar esses pacotes se nenhuma atualização estiver disponível.

A sequência de actualização de uma APEX utiliza a classe PackageManager e é como se segue.

  1. Um arquivo APEX é baixado por meio de um aplicativo instalador de pacote, ADB ou outra fonte.
  2. O gerenciador de pacotes inicia o procedimento de instalação. Ao reconhecer que o arquivo é um APEX, o gerenciador de pacotes transfere o controle para o gerenciador do APEX.
  3. O gerenciador APEX verifica o arquivo APEX.
  4. Se o arquivo APEX for verificado, o banco de dados interno do gerenciador APEX é atualizado para refletir que o arquivo APEX será ativado na próxima inicialização.
  5. O solicitante da instalação recebe uma transmissão após a verificação bem-sucedida do pacote.
  6. Para continuar a instalação, o sistema deve ser reinicializado.
  7. Na próxima inicialização, o gerenciador APEX inicia, lê o banco de dados interno e faz o seguinte para cada arquivo APEX listado:

    1. Verifica o arquivo APEX.
    2. Cria um dispositivo de loopback a partir do arquivo APEX.
    3. Cria um dispositivo de bloco mapeador de dispositivo na parte superior do dispositivo de loopback.
    4. Monta o dispositivo de bloco mapeador de dispositivo para um caminho único (por exemplo, /apex/ name @ ver ).

Quando todos os arquivos APEX listados no banco de dados interno são montados, o gerenciador APEX fornece um serviço de fichário para outros componentes do sistema para consultar informações sobre os arquivos APEX instalados. Por exemplo, os outros componentes do sistema podem consultar a lista de arquivos APEX instalados no dispositivo ou consultar o caminho exato onde um APEX específico está montado, para que os arquivos possam ser acessados.

Os arquivos APEX são arquivos APK

Arquivos APEX são arquivos APK válidos porque eles estão assinado zip arquivos (usando o esquema de assinatura APK) contendo um AndroidManifest.xml arquivo. Isso permite que os arquivos APEX usem a infraestrutura para arquivos APK, como um aplicativo instalador de pacote, o utilitário de assinatura e o gerenciador de pacotes.

O AndroidManifest.xml arquivo dentro de um arquivo APEX é mínima, consistindo no pacote de name , versionCode , e opcional targetSdkVersion , minSdkVersion e maxSdkVersion para granulação fina-alvo. Essas informações permitem que os arquivos APEX sejam entregues por meio de canais existentes, como aplicativos instaladores de pacotes e ADB.

Tipos de arquivo suportados

O formato APEX oferece suporte a estes tipos de arquivo:

  • Bibliotecas nativas compartilhadas
  • Executáveis ​​nativos
  • Arquivos JAR
  • Arquivos de dados
  • Arquivos de configuração

Isso não significa que o APEX pode atualizar todos esses tipos de arquivo. Se um tipo de arquivo pode ser atualizado depende da plataforma e quão estáveis ​​são as definições das interfaces para os tipos de arquivos.

Assinando

Os arquivos APEX são assinados de duas maneiras. Primeiro, o apex_payload.img (especificamente, o descritor vbmeta anexado ao apex_payload.img ) arquivo é assinado com uma chave. Então, toda a APEX é assinado usando a v3 APK esquema de assinatura . Duas chaves diferentes são usadas neste processo.

No lado do dispositivo, uma chave pública correspondente à chave privada usada para assinar o descritor vbmeta é instalada. O gerenciador APEX usa a chave pública para verificar os APEXs cuja instalação é solicitada. Cada APEX deve ser assinado com chaves diferentes e é aplicado no tempo de construção e no tempo de execução.

APEX em partições integradas

Arquivos APEX pode ser localizado no built-in partições como /system . A partição já está acima do dm-verity, então os arquivos APEX são montados diretamente no dispositivo de loopback.

Se um APEX estiver presente em uma partição embutida, o APEX pode ser atualizado fornecendo um pacote APEX com o mesmo nome de pacote e um código de versão maior ou igual. O novo APEX é armazenado em /data e, semelhante a APKs, as sombras versão recém-instalado a versão já presentes na partição built-in. Mas, ao contrário dos APKs, a versão recém-instalada do APEX só é ativada após a reinicialização.

Requisitos de kernel

Para oferecer suporte aos módulos principais do APEX em um dispositivo Android, os seguintes recursos do kernel do Linux são necessários: o driver de loopback e dm-verity. O driver de loopback monta a imagem do sistema de arquivos em um módulo APEX e o dm-verity verifica o módulo APEX.

O desempenho do driver de loopback e do dm-verity é importante para obter um bom desempenho do sistema ao usar módulos APEX.

Versões de kernel com suporte

Os módulos principais do APEX são suportados em dispositivos que usam as versões do kernel 4.4 ou superior. Novos dispositivos lançados com Android 10 ou superior devem usar o kernel versão 4.9 ou superior para oferecer suporte aos módulos APEX.

Patches de kernel necessários

Os patches de kernel necessários para dar suporte aos módulos APEX estão incluídos na árvore comum do Android. Para obter os patches para suportar APEX, use a versão mais recente da árvore comum do Android.

Kernel versão 4.4

Esta versão é compatível apenas com dispositivos atualizados do Android 9 para o Android 10 e que desejam oferecer suporte aos módulos APEX. Para obter os patches necessários, um baixo-merge do android-4.4 ramo é fortemente recomendado. A seguir está uma lista dos patches individuais necessários para a versão 4.4 do kernel.

  • UPSTREAM: loop: adicionar ioctl para alterar o tamanho de bloco lógico ( 4,4 )
  • Backport: bloco / loop: definidas hw_sectors ( 4,4 )
  • A MONTANTE: loop: Adicione LOOP_SET_BLOCK_SIZE em compat ioctl ( 4,4 )
  • Android: mnt: next_descendent Fix ( 4.4 )
  • Android: mnt: remount deve propagar para os escravos dos escravos ( 4.4 )
  • Android: mnt: Propagar remontar corretamente ( 4.4 )
  • Reverter "Android: dm verdade: adicionar tamanho mínimo de pré-busca" ( 4,4 )
  • A MONTANTE: loop: caches gota se compensar ou block_size são alterados ( 4,4 )

Versões do kernel 4.9 / 4.14 / 4.19

Para obter os patches necessários para versões do kernel 4.9 / 4.14 / 4.19, para baixo-merge do android-common ramo.

Opções de configuração do kernel necessárias

A lista a seguir mostra os requisitos básicos de configuração para suportar módulos APEX que foram introduzidos no Android 10. Os itens com um asterisco (*) são requisitos existentes do Android 9 e 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, certifique-se de que os parâmetros de linha de comando do kernel atendam aos seguintes requisitos:

  • loop.max_loop não deve ser definido
  • loop.max_part deve ser <= 8

Construindo um APEX

Esta seção descreve como construir um APEX usando o sistema de construção Android. O seguinte é um exemplo de Android.bp para uma 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",
}

apex_manifest.json exemplo:

{
  "name": "com.android.example.apex",
  "version": 1
}

file_contexts exemplo:

(/.*)?           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 Localização no APEX
Bibliotecas compartilhadas /lib e /lib64 ( /lib/arm de braço traduzido em x86)
Executáveis /bin
Bibliotecas Java /javalib
Pré-fabricados /etc

Dependências transitivas

Os arquivos APEX incluem automaticamente dependências transitivas de libs ou executáveis ​​compartilhados nativos. Por exemplo, se libFoo depende libBar , os dois libs são incluídos quando somente libFoo está listado na native_shared_libs propriedade.

Lidar com vários ABIs

Instalar o native_shared_libs propriedade para ambas as interfaces binários aplicação primárias e secundárias (ABIs) do dispositivo. Se um APEX for direcionado a dispositivos com uma única ABI (ou seja, apenas 32 bits ou apenas 64 bits), apenas as bibliotecas com a ABI correspondente serão instaladas.

Instalar o binaries propriedade só para o primário ABI do dispositivo, tal como descrito abaixo:

  • Se o dispositivo for apenas de 32 bits, apenas a variante de 32 bits do binário será instalada.
  • Se o dispositivo for apenas de 64 bits, apenas a variante de 64 bits do binário será instalada.

Para adicionar o controle de grão fino sobre os ABIs das bibliotecas nativas e binários, use o multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] Propriedades.

  • first : Corresponde ao primário ABI do dispositivo. Este é o padrão para binários.
  • lib32 : Corresponde a 32 bits ABI do dispositivo, se for apoiada.
  • lib64 : Corresponde a 64 bits ABI do dispositivo, ele suportado.
  • prefer32 : Corresponde a 32 bits ABI do dispositivo, se for apoiada. Se a ABI de 32 bits não for compatível, corresponda à ABI de 64 bits.
  • both : Jogos ambas ABIs. Este é o padrão para native_shared_libraries .

Os java , libraries , e prebuilts propriedades são ABI-agnóstico.

Este exemplo é para um dispositivo que suporta 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 é necessária, criar um par de chaves pública-privada e faça um apex_key módulo. Use a key propriedade para assinar o APEX com a tecla. A chave pública é automaticamente incluído no APEX com o nome avb_pubkey .

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_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 chave. O ID da chave usada para assinar um APEX é escrito no APEX. Em tempo de execução, apexd verifica a APEX usando uma chave pública com o mesmo ID no dispositivo.

Assinatura de ZIP

Assine APEXes da mesma forma que você assina APKs. Assine APEXes duas vezes; uma vez para o sistema de arquivos mini ( apex_payload.img arquivo) e uma vez para todo o arquivo.

Para assinar um APEX no nível de arquivo, defina o certificate propriedade em uma destas três maneiras:

  • Não colocado: Se nenhum valor for definido, o APEX é assinado com o certificado localizado na PRODUCT_DEFAULT_DEV_CERTIFICATE . Se nenhum sinalizador é definido, os padrões caminho para a build/target/product/security/testkey .
  • <name> : O APEX é assinado com a <name> certificado no mesmo diretório que PRODUCT_DEFAULT_DEV_CERTIFICATE .
  • :<name> : O APEX é assinado com o certificado que é definida 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)
}

Instalando um APEX

Para instalar um APEX, use ADB.

adb install apex_file_name
adb reboot

Usando um APEX

Após a reinicialização, o APEX é montada na /apex/<apex_name>@<version> diretório. Várias versões do mesmo APEX podem ser montadas ao mesmo tempo. Entre os caminhos de montagem, o que corresponde à versão mais recente é bind-montado em /apex/<apex_name> .

Os clientes podem usar o caminho montado por ligação para ler ou executar arquivos do APEX.

APEXes são normalmente usados ​​da seguinte maneira:

  1. Um pré-cargas OEM ou ODM um APEX sob /system/apex quando o dispositivo é fornecido.
  2. Arquivos no APEX são acessados via o /apex/<apex_name>/ caminho.
  3. Quando uma versão atualizada da APEX está instalado em /data/apex , os pontos caminho para a nova APEX após a reinicialização.

Atualizando um serviço com um APEX

Para atualizar um serviço usando um APEX:

  1. Marque o serviço na partição do sistema como atualizável. Adicione a opção updatable para a definição de serviço.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Criar um novo .rc arquivo para o serviço atualizado. Use o override opção para redefinir o serviço existente.

    /apex/my.apex@1/etc/init.rc:
    
    service myservice /apex/my.apex@1/bin/myservice
        class core
        user system
        ...
        override
    

Definições de serviço só pode ser definido no .rc arquivo de um APEX. Os gatilhos de ação não são compatíveis com APEX.

Se um serviço marcado como atualizável começar antes dos APEXes serem ativados, o início será atrasado até que a ativação dos APEXes seja concluída.

Configurando o sistema para suportar atualizações APEX

Defina a seguinte propriedade do sistema de true para suportar 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 aplainado

Para dispositivos legados, às vezes é impossível ou inviável atualizar o kernel antigo para dar suporte total ao APEX. Por exemplo, o kernel pode ter sido construído sem CONFIG_BLK_DEV_LOOP=Y , que é crucial para a montagem da imagem do sistema de arquivos dentro de um APEX.

APEX nivelado é um APEX especialmente desenvolvido que pode ser ativado em dispositivos com um kernel legado. Os arquivos em um APEX nivelado são instalados diretamente em um diretório na partição interna. Por exemplo, lib/libFoo.so em uma achatada APEX my.apex é instalado para /system/apex/my.apex/lib/libFoo.so .

Ativar um APEX nivelado não envolve o dispositivo de loop. Em todo o diretório /system/apex/my.apex está diretamente bind-montado /apex/name@ver .

APEXes nivelados não podem ser atualizados baixando versões atualizadas dos APEXes da rede porque os APEXes baixados não podem ser nivelados. APEXs nivelados podem ser atualizados apenas por meio de um OTA regular.

APEX nivelado é a configuração padrão. Isso significa que todos os APEXs são, por padrão, nivelados, a menos que você configure explicitamente seu dispositivo para construir APEXes não nivelados para oferecer suporte a atualizações APEX (conforme explicado acima).

A mistura de APEXs achatados e não achatados em um dispositivo NÃO é suportada. APEXes em um dispositivo devem ser todos não achatados ou todos achatados. Isso é especialmente importante ao enviar pré-compilados APEX pré-assinados para projetos como Mainline. APEXes que não são predefinidos (ou seja, criados a partir da fonte) também devem ser não nivelados e assinados com as chaves adequadas. O dispositivo deve herdar de updatable_apex.mk conforme explicado em Atualização de um serviço com uma APEX .

APEXs comprimidos

O Android 12 e posterior apresentam compactação APEX para reduzir o impacto do armazenamento de pacotes APEX atualizáveis. Depois que uma atualização para um APEX é instalada, embora sua versão pré-instalada não seja mais usada, ele ainda ocupa a mesma quantidade de espaço. Esse espaço ocupado permanece indisponível.

Compressão APEX minimiza este impacto de armazenamento por meio de um conjunto de ficheiros de altamente comprimido APEX em partições só de leitura (tais como o /system partição). O Android 12 e posterior usa um algoritmo de compactação DEFLATE zip.

A compactação não fornece otimização para o seguinte:

  • Bootstrap APEXes que precisam ser montados bem no início da sequência de boot.

  • APEXs não atualizáveis. A compressão é apenas benéfico se uma versão atualizada de um APEX está instalado no /data partição. Uma lista completa dos ápices atualizáveis está disponível no Modular System Components página.

  • APEXes de bibliotecas compartilhadas dinâmicas. Desde apexd sempre ativa ambas as versões desses ápices (pré-instalado e atualizado), compactá-los não agrega valor.

Formato de arquivo APEX compactado

Este é o formato de um arquivo APEX compactado.

Diagram shows the format of a compressed APEX file

Formato de arquivo Figura 2. Comprimido APEX

No nível superior, um arquivo APEX compactado é um arquivo zip que contém o arquivo apex original na forma esvaziada com um nível de compactação de 9 e com outros arquivos armazenados descompactados.

Quatro arquivos constituem um arquivo APEX:

  • original_apex : deflacionado com nível de compressão de 9 Este é o original, sem compressão de arquivos APEX .
  • apex_manifest.pb : somente armazenados
  • AndroidManifest.xml : somente armazenados
  • apex_pubkey : somente armazenados

O apex_manifest.pb , AndroidManifest.xml , e apex_pubkey arquivos são cópias de seus arquivos correspondentes em original_apex .

Construindo APEX compactado

Compressed APEX pode ser construído usando o apex_compression_tool.py ferramenta localizada no system/apex/tools .

Vários parâmetros relacionados à compactação APEX estão disponíveis no sistema de compilação.

Em Android.bp se um arquivo APEX é compressível é controlada pelo compressible propriedade:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

A PRODUCT_COMPRESSED_APEX controles bandeira produto se uma imagem do sistema integrado de origem deve conter arquivos compactados APEX.

Para experimentação local você pode forçar uma compilação de ápices compressa definindo OVERRIDE_PRODUCT_COMPRESSED_APEX= a true .

Compressed APEX arquivos gerados pelo sistema de compilação tem o .capex extensão. A extensão torna mais fácil distinguir entre as versões compactadas e não compactadas de um arquivo APEX.

Algoritmos de compressão suportados

O Android 12 só oferece suporte à compactação deflate-zip.

Ativando um arquivo APEX compactado durante a inicialização

Antes de um APEX comprimido pode ser ativado, o original_apex arquivo dentro é descomprimido na /data/apex/decompressed de diretório. O arquivo APEX descomprimido resultante é hard-vinculado à /data/apex/active diretório.

Considere o exemplo a seguir como uma ilustração do processo descrito acima.

Considere /system/apex/com.android.foo.capex como um APEX comprimido a ser activado, com versionCode 37.

  1. O original_apex arquivo dentro /system/apex/com.android.foo.capex é descomprimido em /data/apex/decompressed/com.android.foo@37.apex .
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex é realizada para verificar se ele tem um rótulo SELinux correto.
  3. Verificação verificações são executadas em /data/apex/decompressed/com.android.foo@37.apex para garantir a sua validade: apexd verifica a chave pública agrupados em /data/apex/decompressed/com.android.foo@37.apex para verificar se ele é igual ao fornecido no /system/apex/com.android.foo.capex .
  4. O /data/apex/decompressed/com.android.foo@37.apex arquivo é hard-ligado ao /data/apex/active/com.android.foo@37.apex diretório.
  5. A lógica de ativação regular para arquivos APEX sem compressão é realizada em /data/apex/active/com.android.foo@37.apex .

Interação com OTA

Os arquivos APEX compactados têm implicações na entrega e na aplicação OTA. Uma vez que uma atualização OTA pode conter um arquivo APEX compactado com um nível de versão superior ao que está ativo em um dispositivo, uma certa quantidade de espaço livre deve ser reservada antes que um dispositivo seja reinicializado para aplicar uma atualização OTA.

Para apoiar o sistema OTA, apexd expõe essas duas APIs pasta:

  • calculateSizeForCompressedApex - calcula o tamanho necessário para arquivos APEX descompactar em um pacote OTA. Isso pode ser usado para verificar se um dispositivo tem espaço suficiente antes que um OTA seja baixado.
  • reserveSpaceForCompressedApex - reserva espaço no disco para uso futuro por apexd para descomprimir arquivos APEX compactados dentro do pacote OTA.

No caso de uma actualização A / B OTA, apexd tentativas descompressão no fundo como parte da rotina postinstall OTA. Se descompressão falha, apexd realiza a descompressão durante a inicialização que aplica a atualização OTA.

Alternativas consideradas ao desenvolver APEX

Aqui estão algumas opções que o AOSP considerou ao projetar o formato de arquivo APEX e por que foram incluídas ou excluídas.

Sistemas regulares de gerenciamento de pacotes

Distribuições Linux têm sistemas de gestão de pacotes como o dpkg e rpm , que são poderosos, maduro e robusto. No entanto, eles não foram adotados para APEX porque não podem proteger os pacotes após a instalação. A verificação é realizada apenas quando os pacotes estão sendo instalados. Os invasores podem quebrar a integridade dos pacotes instalados, sem serem notados. Esta é uma regressão para Android em que todos os componentes do sistema foram armazenados em sistemas de arquivos somente leitura, cuja integridade é protegida pelo dm-verity para cada E / S. Qualquer violação dos componentes do sistema deve ser proibida ou detectável para que o dispositivo possa se recusar a inicializar, se comprometido.

dm-crypt para integridade

Os arquivos em um recipiente APEX são de embutido partições (por exemplo, o /system partição) que estão protegidos por dm-Verity, onde qualquer modificação dos ficheiros são proibidos mesmo depois de as partições são montados. Para fornecer o mesmo nível de segurança aos arquivos, todos os arquivos em um APEX são armazenados em uma imagem do sistema de arquivos que é emparelhada com uma árvore de hash e um descritor vbmeta. Sem dm-verdade, um APEX na /data partição é vulnerável a modificações não intencionais que são feitas depois de ter sido verificado e instalado.

Na verdade, o /data partição é também protegida por camadas de encriptação, tais como DM-cripta. Embora isso forneça algum nível de proteção contra adulteração, seu objetivo principal é a privacidade, não a integridade. Quando um atacante ganha acesso ao /data partição, não pode haver mais proteção, e isso de novo é uma regressão em relação a cada componente do sistema estar no /system partição. A árvore de hash dentro de um arquivo APEX junto com dm-verity fornece o mesmo nível de proteção de conteúdo.

Redirecionando caminhos de / sistema para / apex

Arquivos de componentes do sistema embalados em uma APEX são acessíveis através de novos caminhos como /apex/<name>/lib/libfoo.so . Quando os arquivos eram parte do /system partição, eles eram acessíveis através de caminhos, tais como /system/lib/libfoo.so . Um cliente de um arquivo APEX (outros arquivos APEX ou a plataforma) deve usar os novos caminhos. Pode ser necessário atualizar o código existente como resultado da alteração do caminho.

Embora uma forma de evitar a mudança caminho é para sobrepor o conteúdo do arquivo em um arquivo APEX para o /system partição, a equipe do Android não decidiu arquivos de sobreposição sobre o /system partição, porque isso poderia afetar o desempenho como o número de arquivos que estão sendo sobrepostos ( possivelmente até empilhados um após o outro) aumentou.

Outra opção era sequestrar funções de acesso a arquivos tais como open , stat , e readlink , de modo a que os caminhos que começam com o /system foram redireccionado para os seus caminhos correspondentes sob /apex . A equipe do Android descartou essa opção porque é inviável alterar todas as funções que aceitam caminhos. Por exemplo, alguns aplicativos vinculam estaticamente o Bionic, que implementa as funções. Nesses casos, esses aplicativos não são redirecionados.