Você pode usar o formato de arquivo APEX para empacotar e instalar módulos do SO Android de nível inferior. Ela permite criar e a instalação de componentes como bibliotecas e serviços nativos, implementações, firmware, arquivos de configuração etc.
Os APEXs do fornecedor são instalados automaticamente pelo sistema de build no /vendor
e ativado em tempo de execução por apexd
, assim como os APEXs em outros
partições diferentes.
Casos de uso
Modularização de imagens de fornecedores
As APIs APEX facilitam o agrupamento e a modularização naturais de recursos. em imagens de fornecedores.
Quando as imagens são criadas com a combinação de fornecedores independentes APEXs, os fabricantes de dispositivos podem escolher facilmente as implementações de fornecedores que queriam nos dispositivos deles. Os fabricantes podem até criar novo APEX de fornecedor se nenhum dos APEXs fornecidos atender às necessidades ou se o cliente tiver um hardware personalizado totalmente novo.
Por exemplo, um OEM pode optar por usar o Wi-Fi do AOSP no dispositivo. APEX de implementação, a implementação de Bluetooth SoC APEX e um OEM personalizado APEX de implementação de telefonia.
Sem APEXs de fornecedor, uma implementação com tantas dependências entre os componentes do fornecedor requerem coordenação e rastreamento cuidadosos. Ao encapsular todos os elementos (incluindo arquivos de configuração e bibliotecas extras) em APEXs com interfaces claramente definidas em qualquer ponto da comunicação entre recursos, o componentes diferentes se tornam intercambiáveis.
Iteração do desenvolvedor
Os APEXs de fornecedores ajudam os desenvolvedores a iterar mais rapidamente enquanto desenvolvem módulos de fornecedores, agrupando uma implementação completa de recursos, como a HAL de Wi-Fi, dentro de um fornecedor APEX Os desenvolvedores podem criar e enviar individualmente o APEX do fornecedor para teste em vez de recriar toda a imagem do fornecedor.
Isso simplifica e acelera o ciclo de iteração dos desenvolvedores que trabalhem principalmente em uma área de recursos e queiram iterar apenas nesse recurso. área
O agrupamento natural de uma área de recurso em um APEX também simplifica o processo de criar, enviar e testar alterações para essa área de recursos. Por exemplo: a reinstalação de um APEX atualiza automaticamente todas as bibliotecas agrupadas ou arquivos de configuração que o APEX inclui.
O agrupamento de uma área de recursos em um APEX também simplifica a depuração ou a reversão quando um comportamento inadequado do dispositivo. Por exemplo, se a telefonia não estiver funcionando um novo build, os desenvolvedores podem tentar instalar uma versão de telefonia mais antiga a implementação de APEX em um dispositivo (sem a necessidade de atualizar uma versão completa) e para verificar se o bom comportamento foi restaurado.
Exemplo de fluxo de trabalho:
# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w
# Test the device.
... testing ...
# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...
# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...
Exemplos
Noções básicas
Consulte a página principal do formato de arquivo APEX para consultar um APEX genérico. do dispositivo, incluindo requisitos do dispositivo, detalhes de formato do arquivo e etapas de instalação.
Em Android.bp
, definir a propriedade vendor: true
torna um módulo APEX um
fornecedora APEX.
apex {
..
vendor: true,
..
}
Binários e bibliotecas compartilhadas
Um APEX inclui dependências transitivas dentro do payload APEX, a menos que elas e têm interfaces estáveis.
As interfaces nativas estáveis para dependências APEX do fornecedor incluem cc_library
com
stubs
, ndk_library
ou llndk_library
. Essas dependências são excluídas do
empacotamento e as dependências são registradas no manifesto APEX. O manifesto é
processada por linkerconfig
para que as dependências nativas externas sejam
disponível no ambiente de execução.
Ao contrário dos APEXs na partição /system
, os APEXs do fornecedor normalmente são vinculados a uma
versão específica do VNDK. As bibliotecas VNDK garantem a estabilidade da ABI dentro do
para que possamos tratar as bibliotecas do VNDK como estáveis e reduzir o tamanho do
APEXs excluindo-os dos APEXs usando o use_vndk_as_stable
.
No snippet abaixo, o APEX contém os valores binários (my_service
) e
suas dependências não estáveis (arquivos *.so
). Ele não conterá bibliotecas VNDK,
mesmo quando my_service
é criado com bibliotecas VNDK, como libbase
. Em vez disso,
O ambiente de execução my_service
vai usar libbase
das bibliotecas VNDK fornecidas pelo
sistema.
apex {
..
vendor: true,
use_vndk_as_stable: true,
binaries: ["my_service"],
..
}
No snippet abaixo, o APEX contém a biblioteca compartilhada
my_standalone_lib
e qualquer uma das dependências não estáveis dele (conforme descrito acima).
apex {
..
vendor: true,
use_vndk_as_stable: true,
native_shared_libs: ["my_standalone_lib"],
..
}
Implementações de HAL
Para definir uma implementação da HAL, forneça os binários e as bibliotecas correspondentes dentro de um APEX de fornecedor semelhante aos seguintes exemplos:
Para encapsular totalmente a implementação da HAL, o APEX também deve especificar quaisquer fragmentos VINTF e scripts init relevantes.
Fragmentos VINTF
Fragmentos VINTF podem ser disponibilizados a partir de um APEX de fornecedor quando fragmentos estão localizados em
etc/vintf
do APEX.
Use a propriedade prebuilts
para incorporar os fragmentos VINTF no APEX.
apex {
..
vendor: true,
prebuilts: ["fragment.xml"],
..
}
prebuilt_etc {
name: "fragment.xml",
src: "fragment.xml",
sub_dir: "vintf",
}
Scripts de inicialização
Os APEXs podem incluir scripts init de duas formas: (A) por meio de um arquivo de texto pré-criado na
Payload APEX ou (B) um script init normal em /vendor/etc
. É possível definir
para o mesmo APEX.
Iniciar script em APEX:
prebuilt_etc {
name: "myinit.rc",
src: "myinit.rc"
}
apex {
..
vendor: true,
prebuilts: ["myinit.rc"],
..
}
Os scripts de inicialização em APEXs podem ter apenas definições de service
. Scripts de inicialização
em APEXs de fornecedores também podem ter diretivas on <property>
.
Tenha cuidado ao usar diretivas on
. Como os scripts init em APEXs
analisados e executados após a ativação dos APEXs, alguns eventos ou propriedades
não podem ser usadas. Use apex.all.ready=true
para disparar ações o mais cedo possível.
Firmware
Exemplo:
Incorpore firmware em um APEX do fornecedor com o tipo de módulo prebuilt_firmware
, conforme
segue.
prebuilt_firmware {
name: "my.bin",
src: "path_to_prebuilt_firmware",
vendor: true,
}
apex {
..
vendor: true,
prebuilts: ["my.bin"], // installed inside APEX as /etc/firmware/my.bin
..
}
Os módulos prebuilt_firmware
estão instalados no <apex name>/etc/firmware
do APEX. ueventd
verifica /apex/*/etc/firmware
diretórios para
módulos de firmware.
O file_contexts
do APEX precisa rotular todas as entradas de payload de firmware
corretamente para garantir que esses arquivos sejam acessíveis por ueventd
no momento da execução;
normalmente, o rótulo vendor_file
é suficiente. Exemplo:
(/.*)? u:object_r:vendor_file:s0
Módulos do kernel
Incorpore módulos do kernel em um APEX de fornecedor como módulos pré-criados, como mostrado a seguir.
prebuilt_etc {
name: "my.ko",
src: "my.ko",
vendor: true,
sub_dir: "modules"
}
apex {
..
vendor: true,
prebuilts: ["my.ko"], // installed inside APEX as /etc/modules/my.ko
..
}
O file_contexts
do APEX precisa rotular todas as entradas de payload do módulo do kernel
corretamente. Exemplo:
/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0
Os módulos do kernel precisam ser instalados explicitamente. O exemplo de script init abaixo
na partição do fornecedor mostra a instalação via insmod
:
my_init.rc
:
on early-boot
insmod /apex/myapex/etc/modules/my.ko
..
Sobreposições de recursos de tempo de execução
Exemplo:
Incorporar sobreposições de recursos de ambiente de execução em um APEX do fornecedor
usando a propriedade rros
.
runtime_resource_overlay {
name: "my_rro",
soc_specific: true,
}
apex {
..
vendor: true,
rros: ["my_rro"], // installed inside APEX as /overlay/my_rro.apk
..
}
Outros arquivos de configuração
Os APEXs de fornecedores oferecem suporte a vários outros arquivos de configuração normalmente encontrados no fornecedor. como pré-criados dentro de APEXs de fornecedores e muitos outros estão sendo adicionados.
Exemplos:
- XMLs de declaração de recursos
- Os sensores apresentam XMLs como pré-criados em um fornecedor de HAL de sensor APEX
- Arquivos de configuração de entrada
- Configurações da tela sensível ao toque como pré-criados em um fornecedor apenas de configuração APEX
Recursos extras de desenvolvimento
Seleção de APEX na inicialização
Exemplo:
Os desenvolvedores também podem instalar várias versões de APEXs de fornecedores que compartilham o
mesmo nome e chave APEX e, em seguida, escolher qual versão será ativada durante cada
inicial usando sysprops persistentes. Para alguns casos de uso de desenvolvedores, isso pode ser
mais simples do que instalar uma nova cópia do APEX usando adb install
.
Exemplos de casos de uso:
- Instalar três versões da APEX, fornecedora de HAL de Wi-Fi:as equipes de controle de qualidade podem fazer a execução manual. ou automatizados usando uma versão, depois reinicializar para outra versão e executar os testes novamente e comparar os resultados finais.
- Instale duas versões do APEX do fornecedor de HAL da câmera atual e experimental: os dogfooders podem usar a versão experimental sem fazer o download e instalar um arquivo adicional, para que possam retornar facilmente.
Durante a inicialização, o apexd
procura sysprops seguindo um formato específico para
ativar a versão correta do APEX.
Os formatos esperados da chave de propriedade são:
- Configuração de inicialização
- Usado para definir o valor padrão, em
BoardConfig.mk
. androidboot.vendor.apex.<apex name>
- Usado para definir o valor padrão, em
- sysprop persistente
- Usado para mudar o valor padrão, definido em um dispositivo já inicializado.
- Substitui o valor de bootconfig, se houver.
persist.vendor.apex.<apex name>
O valor da propriedade deve ser o nome do arquivo APEX, que deve ser ativado.
// Default version.
apex {
name: "com.oem.camera.hal.my_apex_default",
vendor: true,
..
}
// Non-default version.
apex {
name: "com.oem.camera.hal.my_apex_experimental",
vendor: true,
..
}
A versão padrão também deve ser configurada com o bootconfig
BoardConfig.mk
:
# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default
Após a inicialização do dispositivo, altere a versão ativada configurando o sysprop persistente:
$ adb root;
$ adb shell setprop \
persist.vendor.apex.com.oem.camera.hal \
com.oem.camera.hal.my_apex_experimental;
$ adb reboot;
Se o dispositivo oferecer suporte à atualização do bootconfig após a atualização (por exemplo, com os comandos fastboot
oem
), mudar a propriedade bootconfig dos multiinstalados
O APEX também altera a versão ativada na inicialização.
Para dispositivos de referência virtual baseados no Cuttlefish,
use o comando --extra_bootconfig_args
para definir a propriedade bootconfig
durante a inicialização. Exemplo:
launch_cvd --noresume \
--extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";