Imagem do sistema compartilhada

Esta página apresenta vários mecanismos que os OEMs Android podem usar para ter uma imagem do sistema compartilhada (SSI) em todas as linhas de produtos. Ele também propõe um procedimento para basear uma SSI de propriedade de um OEM em uma imagem genérica do sistema (GSI) criada pelo AOSP.

Contexto

O framework do Android Open Source Project (AOSP) está em conformidade com a arquitetura Mainline para manter a compatibilidade com versões anteriores de implementações de fornecedores. Por exemplo, uma imagem genérica do sistema (GSI) criada com fontes do AOSP do Android 10 pode ser executada em qualquer dispositivo compatível com o Treble que use o Android 8 ou versões mais recentes.

Para isso, o Mainline divide o Android em duas partes distintas: a implementação do fornecedor específica do hardware e o framework genérico do SO Android. Cada componente é instalado em uma partição separada: a partição do fornecedor para software específico do hardware e a partição do sistema para o SO genérico. Uma interface com controle de versão, chamada de interface do fornecedor (VINTF), é aplicada entre elas. Esse sistema de particionamento permite que os OEMs modifiquem a partição do sistema sem afetar a partição do fornecedor e vice-versa.

Historicamente, os fornecedores de SoC e OEMs modificavam muito a versão do framework do Android enviada em dispositivos de consumo. Para mais detalhes, consulte Ciclo de vida de uma versão do Android. Como essas extensões de framework raramente eram projetadas com compatibilidade com versões anteriores em mente, as modificações específicas do dispositivo aumentavam muito a complexidade e o custo financeiro de upgrades subsequentes do SO. No Android 10 (nível da API 29) e versões anteriores, o ecossistema não tinha uma arquitetura clara e padronizada que permitisse aos parceiros criar extensões modulares para o framework do Android.

Nesta página, descrevemos como fornecedores de SoC e OEMs podem criar uma imagem do sistema compartilhada (SSI, na sigla em inglês). Uma SSI é uma imagem de framework unificada criada com base em fontes do SO Android que pode ser reutilizada em vários dispositivos. Ao manter uma compatibilidade limpa com versões anteriores e implementações de fornecedores por meio dessa arquitetura particionada, uma SSI reduz significativamente o custo e a complexidade das atualizações do SO Android.

Para detalhes da implementação, consulte Etapas sugeridas para SSI baseada em GSI. As etapas são modulares. Dependendo da sua arquitetura, você pode implementar etapas específicas (como Etapa 1: herdar generic_system.mk para imagem do sistema OEM (GSI do OEM)) em vez de todas as etapas.

Visão geral do SSI

Com o SSI, os componentes de software específicos do produto e as extensões do OEM são colocados em uma nova partição /product. Os componentes na partição /product usam uma interface bem definida e estável para interagir com os componentes na partição /system. Os OEMs podem criar uma SSI ou ter um pequeno número de SSIs para uso em vários SKUs de dispositivos. Quando uma nova versão do SO Android é lançada, os OEMs investem apenas uma vez na atualização das SSIs para a versão mais recente do Android. Eles podem reutilizar as SSIs para atualizar vários dispositivos sem atualizar a partição /product.

Os OEMs e fornecedores de SoC podem criar SSIs que incluem recursos e modificações personalizadas. Os mecanismos e as práticas recomendadas fornecidos nesta página são destinados aos OEMs para alcançar estas metas principais:

  • Reutilize o SSI em várias SKUs de dispositivos.
  • Atualize o sistema Android com as extensões modulares para facilitar os upgrades do SO.

A ideia principal de separar componentes específicos do produto na partição do produto é semelhante à separação de componentes específicos do SoC na partição do fornecedor pelo Mainline. Uma interface de produto (semelhante ao VINTF) permite a comunicação entre a SSI e a partição do produto. Em relação ao SSI, o termo componentes descreve todos os recursos, binários, textos e bibliotecas instalados em imagens, que se tornam partições.

Partições em torno da SSI

A Figura 1 mostra partições em torno da SSI e as interfaces versionadas nas partições e políticas nas interfaces. Esta seção explica cada uma das partições e interfaces em detalhes.

Partições e interfaces ao redor do diagrama de blocos de SSI

Figura 1. Partições e interfaces relacionadas ao SSI.

Imagens e partições

As informações nesta seção distinguem os termos imagem e partição.

  • Uma imagem é uma parte conceitual do software que pode ser atualizada de forma independente.
  • Uma partição é um local de armazenamento físico que pode ser atualizado de forma independente.

As seções na Figura 1 são definidas da seguinte maneira:

  • SSI:uma imagem comum a um OEM que pode existir em vários dispositivos. Ela não tem componentes específicos de hardware ou produto. Tudo em uma determinada SSI é, por definição, compartilhado entre todos os dispositivos que usam essa SSI. A SSI é composta por uma única imagem /system ou por um /system e as partições /system_ext.

  • Imagem do produto:uma coleção de componentes específicos do produto ou dispositivo que representam personalizações e extensões do OEM para o SO Android. Coloque componentes específicos do SoC na partição /vendor. Os fornecedores de SoC também podem usar a partição /product para componentes adequados, como os independentes de SoC. Por exemplo, se um fornecedor de SoC fornecer um componente independente de SoC aos clientes OEM (que é opcional para envio com o produto), o fornecedor de SoC poderá colocar esse componente na imagem do produto. O local de um componente é determinado pela finalidade dele, não pela propriedade.

  • Imagem do fornecedor:uma coleção de componentes específicos do SoC.

  • Imagem do ODM:uma coleção de componentes específicos da placa que não são fornecidos pelo SoC. Normalmente, o fornecedor do SoC é proprietário da imagem do fornecedor, enquanto o fabricante do dispositivo é proprietário da imagem do ODM. Quando não há uma partição /odm separada, as imagens do fornecedor do SoC e do ODM são mescladas na partição /vendor.

A partição /system_ext

A partição /system_ext é opcional. Use essa partição para recursos e extensões personalizados que estão fortemente acoplados a componentes baseados no AOSP. Essa partição é considerada a extensão específica do OEM para a partição /system, sem uma interface definida nas duas partições. Os componentes na partição /system_ext podem fazer chamadas de API particulares para a partição /system, e os componentes na partição /system podem fazer chamadas de API particulares para a partição /system_ext.

Como as duas partições têm acoplamento rígido, elas são atualizadas juntas quando uma nova versão do Android é lançada. Uma partição /system_ext criada para a versão anterior do Android não precisa ser compatível com a partição /system na próxima versão do Android.

Para instalar um módulo na partição /system_ext, adicione system_ext_specific: true ao arquivo Android.bp. Em dispositivos que não têm uma partição /system_ext, instale esses módulos no subdiretório ./system_ext na partição /system.

Histórico:o objetivo original do projeto da partição /system_ext era colocar todos os componentes específicos do OEM, comuns ou não, na partição /product. No entanto, movê-los todos de uma vez não era viável, especialmente quando alguns componentes tinham um acoplamento rígido com a partição /system. Para mover um componente com acoplamento rígido para a partição /product, a interface do produto precisa ser estendida. Isso muitas vezes exigia que o próprio componente fosse refatorado extensivamente, o que consome muito tempo e esforço. A partição /system_ext começou como um lugar para hospedar temporariamente os componentes que não estão prontos para serem movidos para a partição /product. O objetivo da SSI era eliminar a partição /system_ext.

No entanto, a partição /system_ext é útil para manter a partição /system o mais próximo possível do AOSP. Com o SSI, a maior parte do esforço de upgrade é gasta nos componentes das partições /system e /system_ext. Quando a imagem do sistema é criada com fontes o mais semelhantes possível às do AOSP, você pode concentrar o esforço de upgrade na imagem system_ext.

Interfaces entre imagens

Existem duas interfaces principais para imagens de fornecedores e produtos relacionadas à SSI:

  • Interface do fornecedor (VINTF):a VINTF é a interface para os componentes que residem nas imagens do fornecedor e do ODM. Os componentes nas imagens do produto e do sistema só podem interagir com as imagens do fornecedor e do ODM por meio dessa interface. Por exemplo, uma imagem do fornecedor não pode depender de uma parte particular da imagem do sistema e vice-versa. Isso é definido na arquitetura Treble (agora parte da arquitetura Mainline mais ampla), que divide as imagens em partições de sistema e de fornecedor. A interface é descrita usando os seguintes mecanismos:

    • HIDL (o HAL de passagem está disponível apenas para módulos system e system_ext)
    • AIDL estável
    • Configurações
      • API System Properties
      • API de esquema de arquivo de configuração
    • VNDK
    • APIs do SDK do Android
    • Biblioteca Java SDK
  • Interfaces de produto:a interface de produto é a interface entre a SSI e a imagem do produto. Definir uma interface estável separa os componentes do produto dos componentes do sistema em uma SSI.

Ativar SSI

Esta seção explica como oferecer suporte a SSI no Android 11 e em versões mais recentes.

Desagrupar componentes

Para separar a partição /product dos componentes do sistema, ela precisa ter a mesma política de aplicação da partição /vendor, que já foi separada com o Mainline./product

  • Interfaces integradas:os módulos integrados na partição /product precisam ser desvinculados das outras partições. As únicas dependências permitidas dos módulos de produto são algumas bibliotecas VNDK (incluindo LLNDK) da partição /system. As bibliotecas JNI de que os apps do produto dependem precisam ser bibliotecas do NDK.
  • Interfaces Java:os módulos Java (app) na partição /product não podem usar APIs ocultas porque são instáveis. Esses módulos precisam usar apenas APIs públicas e do sistema da partição /system e bibliotecas do SDK Java na partição /system ou /system_ext. É possível definir bibliotecas do SDK Java para APIs personalizadas.

Aplicar interfaces de produtos

Para garantir que a partição /product não seja agrupada, os OEMs podem fazer com que os dispositivos apliquem as interfaces de produto definindo PRODUCT_PRODUCT_VNDK_VERSION:= current para módulos integrados e PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true para módulos Java. Essas variáveis são definidas automaticamente se o PRODUCT_SHIPPING_API_LEVEL do dispositivo for maior ou igual a 30. Para informações detalhadas, consulte Aplicar interfaces de partição de produto.

Etapas sugeridas para SSI baseada em GSI

Partições sugeridas para SSI baseada em GSI

Figura 2. Partições sugeridas para SSI baseada em GSI.

Uma imagem genérica do sistema (GSI) é a imagem do sistema criada diretamente do AOSP. Ela é usada para os testes de conformidade (por exemplo, CTS no GSI) e como uma plataforma de referência que os desenvolvedores de apps podem usar para testar a compatibilidade dos apps quando não têm um dispositivo real executando a versão necessária do Android.

Os OEMs também podem usar a GSI para criar a SSI. Conforme explicado em Imagens e partições, a SSI consiste na imagem do sistema para os componentes definidos pelo AOSP e na imagem system_ext para os componentes definidos pelo OEM. Quando a GSI é usada como a imagem system, o OEM pode se concentrar na imagem system_ext para o upgrade.

Esta seção oferece orientações para OEMs que querem modularizar as personalizações nas partições /system_ext e /product ao usar uma imagem do sistema AOSP ou quase AOSP. Se os OEMs criarem a imagem do sistema com fontes AOSP, eles poderão substituir a imagem criada pela GSI fornecida pelo AOSP. No entanto, os OEMs não precisam chegar à etapa final (usar a GSI como ela é) de uma só vez.

Etapa 1: herdar generic_system.mk para a imagem do sistema OEM (GSI do OEM)

Ao herdar generic_system.mk (que era chamado de mainline_system.mk no Android 11 e renomeado para generic_system.mk no AOSP), a imagem do sistema (GSI do OEM ) inclui todos os arquivos que a GSI do AOSP tem. Esses arquivos podem ser modificados por OEMs para que a GSI do OEM contenha os arquivos proprietários do OEM, além dos arquivos GSI do AOSP.

Herança de "generic_system.mk" para imagem do sistema OEM

Figura 3. Herde generic_system.mk para a imagem do sistema do OEM.

Etapa 2: fazer com que a GSI do OEM tenha a mesma lista de arquivos da GSI do AOSP

A GSI do OEM não pode ter outros arquivos nesta etapa. Portanto, mova os arquivos proprietários do OEM para as partições system_ext ou product.

Mover arquivos adicionados para fora da GSI do OEM

Figura 4. Mova os arquivos adicionados para fora da GSI do OEM.

Etapa 3: definir uma lista de permissões para limitar os arquivos modificados na GSI do OEM

Para verificar os arquivos modificados, os OEMs podem usar a ferramenta compare_images e comparar a GSI do AOSP com a GSI do OEM. Extraia a GSI do AOSP da meta de inicialização do AOSP generic_system_*.

Ao executar a ferramenta compare_images periodicamente com o parâmetro allowlist, é possível monitorar as diferenças fora da lista permitida. Isso evita outras modificações na GSI do OEM.

Defina uma lista de permissões para reduzir a lista de arquivos modificados na GSI do OEM

Figura 5. Defina uma lista de permissões para reduzir a lista de arquivos modificados na GSI do OEM.

Etapa 4: fazer com que a GSI do OEM tenha os mesmos binários da GSI do AOSP

A limpeza da lista de permissões permite que os OEMs usem a GSI do AOSP como imagem do sistema para os próprios produtos. Para limpar a lista de permissões, os OEMs podem abandonar as mudanças na GSI do OEM ou fazer o upstream das mudanças para o AOSP para que a GSI do AOSP inclua as mudanças.

Fazer com que a GSI do OEM tenha os mesmos binários da GSI do AOSP

Figura 6. Faça com que a GSI do OEM tenha os mesmos binários da GSI do AOSP.

Definir SSI

Os OEMs podem usar as orientações a seguir para definir a SSI.

Proteger a partição /system no tempo de build

Para evitar mudanças específicas do produto na partição /system e definir a GSI do OEM, os OEMs podem usar uma macro de makefile chamada require-artifacts-in-path para impedir qualquer declaração de módulos do sistema depois que a macro for chamada. Consulte o exemplo em Etapa 1: criar makefile e ativar a verificação do caminho do artefato.

Os OEMs podem definir uma lista para permitir que módulos específicos do produto sejam instalados temporariamente na partição /system. No entanto, a lista precisa estar vazia para tornar a GSI do OEM comum a todos os produtos dele. Esse processo é para definir a GSI do OEM e pode ser independente das etapas da GSI do AOSP.

Tornar a partição /system_ext comum

A partição /system_ext pode variar entre dispositivos porque pode ter módulos específicos do dispositivo e agrupados pelo sistema. Como o SSI consiste em partições /system e /system_ext, as diferenças na partição /system_ext impedem que os OEMs definam um SSI. Os OEMs podem ter a própria SSI e compartilhá-la entre vários dispositivos removendo as diferenças e tornando a partição /system_ext comum.

Nesta seção, apresentamos recomendações para tornar a partição /system_ext comum.

Expor APIs ocultas na partição do sistema

Muitos apps específicos de produtos não podem ser instalados na partição de produtos porque usam APIs ocultas, que são proibidas nessa partição. Para mover apps específicos do dispositivo para a partição de produto, remova o uso de APIs ocultas.

A maneira recomendada de remover APIs ocultas dos apps é encontrar APIs públicas ou do sistema alternativas para substituí-las. Se não houver APIs para substituir as ocultas, os OEMs poderão contribuir com o AOSP para definir as novas APIs do sistema para os dispositivos deles.

Como alternativa, os OEMs podem definir APIs personalizadas criando a própria biblioteca do SDK Java na partição /system_ext. Essa biblioteca pode usar APIs ocultas na partição do sistema e fornecer as APIs aos apps na partição do produto ou do fornecedor. Os OEMs precisam congelar as APIs voltadas ao produto para compatibilidade com versões anteriores.

Substituir a desativação de apps específicos de SKU

O Android 16 descontinuou e removeu o mecanismo legado para desativar seletivamente APKs com base na SKU de hardware usando sobreposições de recursos do framework (config_disableApksUnlessMatchedSku_apk_list e config_disableApkUnlessMatchedSku_skus_list). Para mais detalhes, consulte aosp/3444399.

A substituição recomendada é usar a configuração do sistema install-in-user-type em diretórios específicos da SKU. Essa abordagem impede que o pacote seja instalado para qualquer usuário em uma SKU específica, em vez de apenas desativá-lo após a instalação.

  1. Inclua todos os APKs (o superconjunto de todos os apps possíveis para todas as SKUs na imagem do sistema), geralmente na partição /product.

  2. Verifique se o SKU do dispositivo está definido corretamente na propriedade do sistema ro.boot.hardware.sku (usada pelo sistema para identificar o SKU do dispositivo na inicialização).

  3. Crie subdiretórios sysconfig específicos da SKU em /product/etc/sysconfig/ usando a convenção de nomenclatura sku_<SKU_NAME>. O sistema carrega automaticamente as configurações do diretório que corresponde à propriedade ro.boot.hardware.sku. Exemplo de caminho: /product/etc/sysconfig/sku_basic_model/.

  4. Configure a prevenção de instalação de apps. Dentro do diretório específico da SKU, crie um arquivo de configuração XML (por exemplo, disabled_apps.xml) e use a tag <do-not-install-in> para excluir pacotes específicos.

Exemplo de XML (/product/etc/sysconfig/sku_basic_model/disabled_apps.xml):

<?xml version="1.0" encoding="utf-8"?>
<config>
    <!-- Prevents this package from being installed for ANY user on this SKU -->
    <install-in-user-type package="com.example.premium.feature.app" >
        <do-not-install-in user-type="FULL" />
        <do-not-install-in user-type="SYSTEM" />
    </install-in-user-type>
</config>

Confira uma comparação dos dois métodos:

Recurso Android 15 e versões anteriores Android 16 e versões mais recentes
Método de configuração Sobreposições de recursos do framework Arquivos XML SystemConfig
Localização da lógica config.xml (sobreposição de recursos) /product/etc/sysconfig/sku_<name>/
Resultado Desativa o app usando o PackageManager. Impede a instalação de apps para o usuário.
Robustez Pode ser reativado pelos serviços do sistema O pacote nunca é instalado para o usuário.

Para casos que exigem um controle mais granular (ou seja, desativar um app que normalmente é instalado por padrão em todas as SKUs), o Android também oferece suporte a tags disabled-in-sku e enabled-in-sku-override em sysconfig:

  • <disabled-in-sku package="com.example.app" /> desativa o app globalmente.

  • <enabled-in-sku-override package="com.example.app" /> reativa o app para uma SKU específica quando colocado no diretório sku_<name> correspondente.

Definir RRO em vez de usar sobreposição de recursos estática

Uma sobreposição de recursos estáticos manipula os pacotes sobrepostos. No entanto, isso pode impedir a definição de um SSI. Portanto, verifique se as propriedades do RRO estão ativadas e definidas corretamente. Ao definir as propriedades da seguinte forma, os OEMs podem ter todas as sobreposições geradas automaticamente como RROs.

PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty

Se uma configuração detalhada for necessária, defina um RRO manualmente em vez de depender de um gerado automaticamente. Para informações detalhadas, consulte Mudar o valor dos recursos de um app durante a execução. Os OEMs também podem definir RROs condicionais que dependem das propriedades do sistema usando os atributos android:requiredSystemPropertyName e android:requiredSystemPropertyValue.

Perguntas frequentes

Confira abaixo as perguntas frequentes sobre a SSI.

Posso definir várias SSIs?

Isso depende da similaridade e das características dos dispositivos (ou do grupo de dispositivos). Os OEMs podem tentar tornar a partição system_ext comum, conforme descrito em Tornar a partição system_ext comum. Se um grupo de dispositivos tiver muitas diferenças, é melhor definir várias SSIs.

Posso remover módulos de generic_system.mk que conflitam com minha implementação?

Não. A GSI tem um conjunto mínimo de módulos inicializáveis e testáveis. Se você acha que um módulo não é essencial, registre um bug para atualizar o arquivo generic_system.mk.