O Android 11 desagrupa a partição product
, tornando-a
independente das partições system
e vendor
. Como parte dessas mudanças,
agora é possível controlar o acesso da partição product
a interfaces nativas
e Java, o que é semelhante ao funcionamento da aplicação de interfaces para
partições vendor
.
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 restrição permite:
- Módulos nativos na partição
product
que serão vinculados:- Estática ou dinamicamente a outros módulos na partição
product
que incluem bibliotecas estáticas, compartilhadas ou de cabeçalho. - Dinâmica para bibliotecas do VNDK na partição
system
.
- Estática ou dinamicamente a outros módulos na partição
- Bibliotecas JNI em APKs não agrupados na partição
product
para vincular a bibliotecas em/product/lib
ou/product/lib64
(além das bibliotecas do NDK).
A aplicação não permite outros links para partições diferentes da partição
product
.
Aplicação do tempo de build (Android.bp)
No Android 11, os módulos do sistema podem criar uma variante
de imagem de produto, além das variantes de imagem do núcleo e do fornecedor. Quando a aplicação
da interface nativa está ativada (PRODUCT_PRODUCT_VNDK_VERSION
é 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
nos 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
nos arquivosAndroid.bp
.As bibliotecas do VNDK precisam ter
product_available: true
nos arquivosAndroid.bp
para que os bináriosproduct
possam ser vinculados às bibliotecas do VNDK.
A tabela a seguir resume as propriedades Android.bp
usadas para criar variantes
de imagem.
Propriedades no Android.bp | Variantes criadas | |
---|---|---|
Antes da aplicação | Após a aplicação | |
padrão (nenhuma) | do núcleo(inclui /system , /system_ext e
/product ) |
núcleo
(inclui /system e /system_ext , mas não
/product ) |
system_ext_specific: true |
core | core |
product_specific: true |
core | produto |
vendor: true |
fornecedor | fornecedor |
vendor_available: true |
núcleo, fornecedor | núcleo, fornecedor |
product_available: true |
N/A | núcleo, produto |
vendor_available: true E product_available:
true |
N/A | core, 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 de regras no tempo de build (Android.mk)
Quando a aplicação de interface nativa está ativada, os módulos nativos instalados na
partição product
têm um tipo de link native:product
que pode se vincular apenas a
outros módulos native:product
ou native:vndk
. A tentativa de vincular a um
módulo diferente desses faz com que o sistema de build gere um erro de verificação de tipo
de link.
Aplicação no ambiente de execução
Quando a aplicação da interface nativa está ativada, a configuração do vinculador para o
vinculador bionic não permite que os processos do sistema usem bibliotecas product
,
criando uma seção product
para os processos product
que não podem ser vinculados a
bibliotecas fora da partição product
. No entanto, esses processos podem ser vinculados a
bibliotecas do VNDK. As tentativas de violar a configuração de vinculação do ambiente de execução fazem com que
o processo falhe e gere uma mensagem de erro CANNOT LINK EXECUTABLE
.
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 ativada, a aplicação permite ou proíbe o seguinte
acesso:
API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
API pública | |||||
@SystemApi | |||||
API @hide |
Como na partição vendor
, um app ou uma biblioteca Java na partição product
pode usar apenas APIs públicas e do sistema. Não é permitido vincular a uma biblioteca
que usa APIs ocultas. Essa restrição inclui vinculação no tempo de build
e reflexão no ambiente de execução.
Aplicação de regras no tempo de build
No tempo de build, o Make e o 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 apps na partição product
precisa
ser preenchido com current
, system_current
ou a versão numérica da API, e
o campo platform_apis
precisa estar vazio.
Aplicação no ambiente de execução
O ambiente de execução do Android verifica se os apps na partição product
não usam
APIs ocultas, incluindo a reflexão. Para mais detalhes, consulte Restrições para
interfaces
não SDK.
Ativar a aplicação de interfaces de produtos
Siga as etapas desta 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 defina a verificação de requisito de caminho de artefatos
no device.mk para impedir que módulos não do sistema sejam instalados
na partição system . |
N |
2 | Limpe a lista de permissões. | N |
3 | Aplicar interfaces nativas e identificar falhas de links no ambiente de execução (pode ser executada em paralelo com a aplicação do Java). | Y |
4 | Aplicar interfaces Java e verificar o comportamento do ambiente de execução (pode ser executado em paralelo com a aplicação nativa). | Y |
5 | Confira os comportamentos de execução. | Y |
6 | Atualização de device.mk com a aplicação de interface do produto. |
Y |
Etapa 1: criar o makefile e ativar a verificação de 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 de caminho de artefato. 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 build 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
, os arquivos de make fora de oem_system.mk
não podem incluir módulos instalados na
partição root
ou system
. Para incluir esses módulos, você precisa
defini-los no arquivo oem_system.mk
ou em um makefile incluído.
As tentativas de instalar módulos em caminhos não permitidos causam falhas de build. Para corrigir
falhas, 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 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
. Isso lista os módulos que podem ser instalados.
Etapa 2: esvaziar a lista de permissões
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
system
. Para esvaziar a lista de permissões, mova todos os módulos da lista para a
partição system_ext
ou product
ou adicione-os aos arquivos de criação system
. Essa
etapa é opcional, porque a definição de uma imagem system
comum não é necessária para
ativar a aplicação da interface do produto. No entanto, esvaziar a lista de permissões é
útil para definir o limite system
com system_ext
.
Etapa 3: aplicar interfaces nativas
Nesta etapa, você define PRODUCT_PRODUCT_VNDK_VERSION := current
e procura
erros de build e de execução e os resolve. Para verificar a inicialização e os registros do dispositivo
e encontrar e corrigir falhas de vinculação de execução:
Defina
PRODUCT_PRODUCT_VNDK_VERSION := current
.Crie o dispositivo e procure erros de build. É provável que você encontre alguns erros de build para 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_specific: true
. - Os módulos podem não ter a variante de produto necessária para os módulos
de produtos. Para corrigir, disponibilize esse módulo para a partição
product
definindoproduct_available: true
ou mova o módulo para a partiçãoproduct
definindoproduct_specific: true
.
- Qualquer módulo
Resolva os erros de build e verifique se o dispositivo foi criado.
Faça o flash da imagem e procure erros de execução na inicialização e nos registros do dispositivo.
- Se a tag
linker
de um registro de caso de teste mostrar uma mensagemCANNOT LINK EXECUTABLE
, o arquivo de make não tem uma dependência (e não foi capturada no tempo de build). - Para verificar isso no sistema de build, adicione a biblioteca necessária ao campo
shared_libs:
ourequired:
.
- Se a tag
Resolva as dependências ausentes usando as orientações acima.
Etapa 4: aplicar interfaces Java
Nesta etapa, você define PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
e encontra e corrige os erros de build resultantes. Procure dois tipos específicos de erros:
Erros de tipo de link. Esse erro indica que um app está vinculado a módulos Java com uma
sdk_version
mais ampla. Para corrigir, amplie osdk_version
do app ou restrinja 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. Esse erro indica que um símbolo não pode ser encontrado porque ele 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 do ambiente de execução
Nesta etapa, você verifica se os comportamentos do ambiente de execução estão como esperado. Para apps
depuráveis, é possível monitorar o uso de APIs ocultas por registro usando
StrictMode.detectNonSdkApiUsage
, que gera um registro quando o app usa uma
API oculta. Como alternativa, utilize a ferramenta de análise estática veridex para ver o tipo de uso (vinculação ou reflexão), o nível de restrição e a pilha de chamadas.
Sintaxe Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Exemplo de resultado da 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 detalhes sobre o uso do veridex, consulte Testar usando a ferramenta veridex.
Etapa 6: atualizar o device.mk
Depois de corrigir todas as falhas de build e ambiente de execução e verificar se os comportamentos
de execução estão conforme o esperado, defina o seguinte em device.mk
:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true