O Android 11 desmembra a partição product
, tornando-a independente das partições do system
e vendor
. Como parte dessas mudanças, agora é possível controlar o acesso da partição product
às interfaces nativas e Java (o que é semelhante ao modo como a imposição de interface funciona para partições vendor
).
Aplicando interfaces nativas
Para ativar a aplicação da interface nativa, defina PRODUCT_PRODUCT_VNDK_VERSION
como current
. (A versão é automaticamente definida como current
quando o nível da API de envio para o destino é superior a 29.) A aplicação permite:
- Módulos nativos na partição
product
para vincular:- Estática ou dinamicamente para outros módulos na partição
product
que incluem bibliotecas estáticas, compartilhadas ou de cabeçalho. - Dinamicamente para bibliotecas VNDK na partição
system
.
- Estática ou dinamicamente para outros módulos na partição
- Bibliotecas JNI em APKs desagregados na partição
product
para vincular a bibliotecas em/product/lib
ou/product/lib64
(isso é um acréscimo às bibliotecas NDK).
A aplicação não permite outros links para partições diferentes da partição product
.
Aplicação do tempo de compilação (Android.bp)
No Android 11, os módulos do sistema podem criar uma variante de imagem do produto, além das variantes de imagem principal e do fornecedor. Quando a aplicação da interface nativa está habilitada ( PRODUCT_PRODUCT_VNDK_VERSION
está definido como current
):
Os módulos nativos na partição
product
estão na variante do produto, e não na variante principal.Módulos com
product_available: true
em seus arquivosAndroid.bp
estão disponíveis para a variante do produto.Bibliotecas ou binários que especificam
product_specific: true
podem ser vinculados a outras bibliotecas que especificamproduct_specific: true
ouproduct_available: true
em seus arquivosAndroid.bp
.As bibliotecas VNDK devem ter
product_available: true
em seus arquivosAndroid.bp
para que os bináriosproduct
possam ser vinculados às bibliotecas 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) | essencial (inclui | essencial (inclui |
system_ext_specific: true | essencial | essencial |
product_specific: true | essencial | produtos |
vendor: true | fornecedor | fornecedor |
vendor_available: true | núcleo, fornecedor | núcleo, fornecedor |
product_available: true | N / D | produto principal |
vendor_available: true E product_available: true | N / D | núcleo, produto, fornecedor |
system_ext_specific: true E vendor_available: true | núcleo, fornecedor | núcleo, fornecedor |
product_specific: true E vendor_available: true | núcleo, fornecedor | produto, fornecedor |
Aplicação do tempo de compilação (Android.mk)
Quando a aplicação da interface nativa está ativada, os módulos nativos instalados na partição product
têm 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 quaisquer módulos diferentes 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 aplicação da interface nativa está habilitada, a configuração do vinculador para o vinculador biônico não permite que os processos do sistema usem bibliotecas product
, criando uma seção product
para os processos product
que não podem se vincular a bibliotecas fora da partição product
(no entanto, tais 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
.
Aplicando interfaces Java
Para ativar a aplicação da interface Java, configure PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
como true
. (O valor é automaticamente definido como true
quando o nível da API de envio para o destino é maior que 29.) Quando ativada, a imposição permite/desautoriza o seguinte acesso.
API | /sistema | /sistema_ext | /produtos | /fornecedor | /dados |
---|---|---|---|---|---|
API pública | |||||
@SystemApi | |||||
@ocultar API |
Assim como na partição vendor
, um aplicativo ou biblioteca Java na partição 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 construção e reflexão em tempo de execução.
Aplicação do tempo de construção
No momento da construção, Make e Soong verificam se os módulos Java na partição product
não usam APIs ocultas, verificando os campos platform_apis
e sdk_version
. O sdk_version
dos aplicativos na partição product
deve ser preenchido com a versão current
, system_current
ou numérica da API, e o campo platform_apis
deve estar vazio.
Aplicação de tempo de execução
O ambiente de execução do Android verifica se os aplicativos na partição product
não usam APIs ocultas, incluindo reflexão. Para obter detalhes, consulte Restrições em interfaces não SDK .
Habilitando a aplicação da interface do produto
Use as etapas nesta seção para ativar a aplicação da interface do produto.
Etapa | Tarefa | Obrigatório |
---|---|---|
1 | Defina seu próprio makefile do sistema que especifica os pacotes para a partição system e, em seguida, defina a verificação de requisitos do caminho dos artefatos no device.mk (para evitar que módulos que não sejam do sistema sejam instalados na partição system ). | N |
2 | Limpe a lista permitida. | N |
3 | Aplique interfaces nativas e identifique falhas de link de tempo de execução (pode ser executado em paralelo com a aplicação de Java). | S |
4 | Aplique interfaces Java e verifique o comportamento do tempo de execução (pode ser executado em paralelo com a aplicação nativa). | S |
5 | Verifique os comportamentos de tempo de execução. | S |
6 | Atualize device.mk com aplicação da interface do produto. | S |
Etapa 1: criar makefile e ativar a verificação do caminho do artefato
Nesta etapa, você define o makefile system
.
Crie um makefile que defina os pacotes para a partição
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çãosystem
e ative a verificação de requisitos do caminho do 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 evita que pacotes definidos em outros makefiles sejam instalados nos caminhos definidos em require-artifacts-in-path
e evita 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 de oem_system.mk
não podem incluir módulos instalados na root
ou na partição 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 interrupções na compilação. Para corrigir quebras, siga um destes procedimentos:
Opção 1: Incluir 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 no conjunto de caminhos em `require-artifacts-in-path.Opção 2: Instale módulos na partição
system_ext
ouproduct
(e não instale módulos na partiçãosystem
).Opção 3: adicione módulos ao
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Esta lista os módulos permitidos para serem instalados.
Passo 2: Esvazie a lista permitida
Nesta etapa, você deixa PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
vazio para que todos os dispositivos que compartilham oem_system.mk
também possam compartilhar uma única imagem system
. Para esvaziar a lista permitida, mova quaisquer módulos da lista para system_ext
ou partição product
ou adicione-os aos arquivos make system
. Esta etapa é opcional porque a definição de uma imagem system
comum não é necessária para permitir a aplicação da interface do produto. No entanto, esvaziar a lista permitida é útil para definir o limite system
com system_ext
.
Etapa 3: aplicar interfaces nativas
Nesta etapa, você define PRODUCT_PRODUCT_VNDK_VERSION := current
e, em seguida, procura erros de compilação e de tempo de execução e os resolve. Para verificar a inicialização e os registros do dispositivo e localizar e corrigir falhas de link de tempo de execução:
Definir
PRODUCT_PRODUCT_VNDK_VERSION := current
.Construa o dispositivo e procure erros de construção. É provável que você veja algumas quebras de compilação devido a variantes de produto ou variantes principais ausentes. 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 módulos de produto. Para corrigir, disponibilize esse módulo para a partição
product
definindoproduct_available: true
ou mova o módulo para a partição doproduct
definindoproduct_specific: true
.
- Qualquer módulo
Resolva erros de compilação e garanta que o dispositivo seja compilado com êxito.
Atualize a imagem e procure erros de tempo de execução na inicialização e nos registros do dispositivo.
- Se a tag
linker
de um log de caso de teste mostrar uma mensagemCANNOT LINK EXECUTABLE
, falta uma dependência no arquivo make (e não foi capturado no momento da construção). - Para verificá-lo no sistema de compilação, adicione a biblioteca necessária ao campo
shared_libs:
ourequired:
- Se a tag
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
, 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. Erro de exemplo: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ímbolos. 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. Erro de exemplo:
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: verifique 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 depuráveis, você pode monitorar o uso de API oculta por log usando StrictMode.detectNonSdkApiUsage
(que gera um log quando o aplicativo usa uma API oculta). Alternativamente, 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 Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Exemplo de resultado 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 de 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