O Android 11 separa a partição do product
, tornando-a independente das partições do system
e do vendor
. Como parte dessas mudanças, agora você pode controlar o acesso da partição do product
às interfaces nativas e Java (que é semelhante à forma como a imposição de interface funciona para partições de vendor
).
Como aplicar interfaces nativas
Para ativar a aplicação da interface nativa, defina PRODUCT_PRODUCT_VNDK_VERSION
como current
. (A versão é definida automaticamente como current
quando o nível da API de envio para o destino é maior que 29.) A imposição permite:
- Módulos nativos na partição do
product
para vincular:- Estaticamente ou dinamicamente para outros módulos na partição do
product
que incluem bibliotecas estáticas, compartilhadas ou de cabeçalho. - Dinamicamente para bibliotecas VNDK na partição do
system
.
- Estaticamente ou dinamicamente para outros módulos na partição do
- Bibliotecas JNI em APKs desagregados na partição do
product
para vincular a bibliotecas em/product/lib
ou/product/lib64
(além das bibliotecas do NDK).
A imposição não permite outros links para partições além da partição do product
.
Aplicação do tempo de compilação (Android.bp)
No Android 11, os módulos do sistema podem criar uma variante da imagem do produto, além das variantes da imagem principal e do fornecedor. Quando a aplicação de interface nativa está habilitada ( PRODUCT_PRODUCT_VNDK_VERSION
está definido como current
):
Os módulos nativos na partição do
product
estão na variante do produto em vez da variante principal.Módulos com
vendor_available: true
em seus arquivosAndroid.bp
estão disponíveis para a variante do produto e a variante do fornecedor.Bibliotecas ou binários que especificam
product_specific: true
podem vincular a outras bibliotecas que especificamproduct_specific: true
ouvendor_available: true
em seus arquivosAndroid.bp
.As bibliotecas do VNDK devem ter
vendor_available: true
em seus arquivosAndroid.bp
para que os binários doproduct
possam ser vinculados às bibliotecas do VNDK.
A tabela a seguir resume as propriedades Android.bp
usadas para criar variantes de imagem.
Propriedades em Android.bp | Variantes criadas | |
---|---|---|
Antes da aplicação | Após a aplicação | |
padrão (nenhum) | testemunho (inclui | testemunho (inclui |
system_ext_specific: true | testemunho | testemunho |
product_specific: true | testemunho | produtos |
vendor: true | fornecedor | fornecedor |
vendor_available: true | núcleo, fornecedor | núcleo, produto, fornecedor |
system_ext_specific: true AND vendor_available: true | núcleo, fornecedor | núcleo, produto, fornecedor |
product_specific: true AND vendor_available: true | núcleo, fornecedor | produto, vendedor |
Aplicação do tempo de compilação (Android.mk)
Quando a imposição de interface nativa está ativada, os módulos nativos instalados na partição do product
possuem um tipo de link native:product
que pode ser vinculado apenas a outros módulos native:product
ou native:vndk
. A tentativa de vincular a qualquer módulo diferente desses faz com que o sistema de compilação gere um erro de verificação de tipo de link.
Aplicação de tempo de execução
Quando a imposição de interface nativa está habilitada, a configuração do vinculador para o vinculador biônico não permite que os processos do sistema usem bibliotecas de product
, criando uma seção de product
para os processos de product
que não podem vincular a bibliotecas fora da partição do product
(no entanto, esses processos podem link para bibliotecas VNDK). As tentativas de violar a configuração do link de tempo de execução fazem com que o processo falhe e gere uma mensagem de erro CANNOT LINK EXECUTABLE
.
Como aplicar interfaces Java
Para ativar a aplicação da interface Java, defina PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
como true
. (O valor é definido automaticamente como true
quando o nível da API de envio para o destino é maior que 29.) Quando ativado, a imposição permite/não permite o acesso a seguir.
API | /sistema | /system_ext | /produtos | /fornecedor | /dados |
---|---|---|---|---|---|
API pública | |||||
@SystemApi | |||||
@hide API |
Assim como na partição do vendor
, um aplicativo ou uma biblioteca Java na partição do product
pode usar apenas APIs públicas e de sistema; não é permitido vincular a uma biblioteca que usa APIs ocultas. Essa restrição inclui vinculação em tempo de compilação e reflexão em tempo de execução.
Execução do tempo de construção
No momento da compilação, Make e Soong verificam se os módulos Java na partição do product
não usam APIs ocultas verificando os campos platform_apis
e sdk_version
. O sdk_version
dos aplicativos na partição do product
deve ser preenchido com current
, system_current
ou numeric version da API, e o campo platform_apis
deve estar vazio.
Aplicação de tempo de execução
O tempo de execução do Android verifica se os aplicativos na partição do product
não usam APIs ocultas, incluindo reflexão. Para obter detalhes, consulte Restrições em interfaces não SDK .
Como ativar a aplicação da interface do produto
Use as etapas nesta seção para ativar a aplicação da interface do produto.
Degrau | Tarefa | Requeridos |
---|---|---|
1 | Defina seu próprio makefile do sistema que especifica os pacotes para a partição do system e, em seguida, defina a verificação do requisito do caminho dos artefatos no device.mk (para evitar que módulos que não sejam do sistema sejam instalados na partição do system ). | N |
2 | Limpe a lista permitida. | N |
3 | Imponha interfaces nativas e identifique falhas de link de tempo de execução (pode ser executado em paralelo com a imposição de Java). | S |
4 | Imponha interfaces Java e verifique o comportamento do tempo de execução (pode ser executado em paralelo com a imposição nativa). | S |
5 | Verifique os comportamentos de tempo de execução. | S |
6 | Atualize device.mk com a aplicação da interface do produto. | S |
Etapa 1: criar makefile e habilitar a verificação do caminho do artefato
Nesta etapa, você define o makefile do system
.
Crie um makefile que defina os pacotes para a partição do
system
. Por exemplo, crie um arquivooem_system.mk
com o seguinte:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)
No arquivo
device.mk
, herde o makefile comum para a partição dosystem
e ative a verificação de requisitos de caminho de artefato. Por exemplo:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
Sobre os requisitos do caminho do artefato
Quando PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
é definido como true
ou strict
, o sistema de compilação impede que pacotes definidos em outros makefiles sejam instalados nos caminhos definidos em require-artifacts-in-path
e impede que pacotes definidos no makefile atual instalem artefatos fora dos caminhos definidos em require-artifacts-in-path
.
No exemplo acima, com PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
definido como strict
, makefiles fora oem_system.mk
não podem incluir módulos instalados na partição root
ou do system
. Para incluir esses módulos, você deve defini-los no próprio arquivo oem_system.mk
ou em um makefile incluído. As tentativas de instalar módulos em caminhos não permitidos causam quebras de compilação. Para corrigir quebras, siga um destes procedimentos:
Opção 1: inclua o módulo do sistema nos makefiles incluídos em
oem_system.mk
. Isso faz com que o requisito do caminho do artefato seja atendido (já que os módulos agora existem em um makefile incluído) e, portanto, permite a instalação do conjunto de caminhos em `require-artifacts-in-path.Opção 2: instale módulos na partição
system_ext
ou doproduct
(e não instale módulos na partição dosystem
).Opção 3: adicionar módulos ao
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Esta lista os módulos permitidos a serem instalados.
Etapa 2: esvazie a lista de permitidos
Nesta etapa, você deixa o PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
vazio para que todos os dispositivos que compartilham oem_system.mk
também possam compartilhar uma única imagem do system
. Para esvaziar a lista permitida, mova qualquer módulo na lista para a partição system_ext
ou do product
ou adicione-os aos arquivos de criação do system
. Esta etapa é opcional porque a definição de uma imagem de system
comum não é necessária para habilitar a aplicação da interface do produto. No entanto, esvaziar a lista permitida é útil para definir o limite do system
com system_ext
.
Etapa 3: aplicar interfaces nativas
Nesta etapa, você define PRODUCT_PRODUCT_VNDK_VERSION := current
, depois procura erros de compilação e tempo de execução e os resolve. Para verificar a inicialização e os logs do dispositivo e localizar e corrigir falhas de link de tempo de execução:
Defina
PRODUCT_PRODUCT_VNDK_VERSION := current
.Compile o dispositivo e procure por erros de compilação. É provável que você veja algumas quebras de compilação para variantes de produtos ausentes ou variantes principais. As pausas comuns incluem:
- Qualquer módulo
hidl_interface
que tenhaproduct_specific: true
não estará disponível para módulos do sistema. Para corrigir, substituaproduct_specific: true
porsystem_ext_specfic: true
. - Os módulos podem não ter a variante de produto necessária para os módulos de produto. Para corrigir, disponibilize esse módulo para a partição do
product
configurandovendor_available: true
ou mova o módulo para a partição doproduct
configurandoproduct_specific: true
.
- Qualquer módulo
Resolva os erros de compilação e assegure-se de que o dispositivo seja compilado com êxito.
Atualize a imagem e procure erros de tempo de execução na inicialização e nos logs do dispositivo.
- Se a tag do
linker
de um log de caso de teste mostrar uma mensagemCANNOT LINK EXECUTABLE
, o arquivo make não possui uma dependência (e não foi capturado no momento da compilação). - Para verificá-lo no sistema de compilação, inclua a biblioteca necessária no campo
shared_libs:
ourequired:
- Se a tag do
Resolva as dependências ausentes usando as orientações fornecidas acima.
Etapa 4: aplicar interfaces Java
Nesta etapa, você define PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
e, em seguida, localiza e corrige os erros de compilação resultantes. Procure dois tipos específicos de erros:
Erros de tipo de link. Este erro indica que um aplicativo está vinculado a módulos Java que possuem um
sdk_version
mais amplo. Para corrigir, você pode ampliar osdk_version
do aplicativo ou restringir osdk_version
da biblioteca. Exemplo de erro:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
Erros de símbolo. Este erro indica que um símbolo não pode ser encontrado porque está em uma API oculta. Para corrigir, use uma API visível (não oculta) ou encontre uma alternativa. Exemplo de erro:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
Etapa 5: verificar os comportamentos de tempo de execução
Nesta etapa, você verifica se os comportamentos de tempo de execução estão conforme o esperado. Para aplicativos que são depuráveis, você pode monitorar o uso de API oculta registrando usando StrictMode.detectNonSdkApiUsage
(que gera um log quando o aplicativo usa uma API oculta). Como alternativa, você pode usar a ferramenta de análise estática veridex para obter o tipo de uso (vinculação ou reflexão), nível de restrição e pilha de chamadas.
Sintaxe do Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Exemplo de resultado do veridex:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
Para obter detalhes sobre o uso do veridex, consulte Testar usando a ferramenta veridex .
Etapa 6: atualizar device.mk
Depois de corrigir todas as falhas de compilação e tempo de execução e verificar se os comportamentos de tempo de execução são os esperados, defina o seguinte em device.mk
:
-
PRODUCT_PRODUCT_VNDK_VERSION := current
-
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true