Imagem do sistema compartilhada do Android

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

Contexto

Com o Project Treble, o Android monolítico foi dividido em duas partes: a parte específica do hardware (a implementação do fornecedor) e a parte genérica do SO (o framework do Android OS). O software para cada um é instalado em uma partição separada: a partição do fornecedor para o software específico de hardware e a partição do sistema para o software de SO genérico. Uma interface com controle de versão, chamada de interface do fornecedor (VINTF, na sigla em inglês), é definida e aplicada nas duas partições. Ao usar esse sistema de particionamento, é possível modificar a partição do sistema sem modificar a do fornecedor e vice-versa.

Motivação

O código do framework lançado no AOSP é compatível com a arquitetura Treble e mantém a compatibilidade com versões anteriores de implementações de fornecedores. Por exemplo, uma imagem genérica do sistema criada com base nas fontes do AOSP do Android 10 pode ser executada em qualquer dispositivo compatível com o Treble que esteja executando o Android 8 ou mais recente. A versão do Android que é enviada em dispositivos de consumo é modificada por fornecedores de SoC e OEMs. Consulte O ciclo de uma versão do Android. Essas mudanças e extensões feitas no framework não foram escritas para manter a compatibilidade com versões anteriores, o que resultou em maior complexidade e custo mais alto em uma atualização do SO. Mudanças e modificações específicas do dispositivo aumentam o custo e a complexidade da atualização de uma versão do SO Android.

Antes do Android 11, não havia uma arquitetura clara que permitisse aos parceiros criar extensões modulares para o framework do SO Android. Este documento descreve as etapas que os fornecedores de SoC e OEMs podem seguir para criar uma SSI. Isso significa uma imagem criada com base nas origens do framework do SO Android para reutilização em vários dispositivos, para manter a compatibilidade com versões anteriores de implementações de fornecedores e para oferecer uma redução significativa na complexidade e no custo de upgrades do SO Android. Para saber as etapas específicas necessárias para criar uma SSI, consulte a seção Etapas sugeridas para SSIs baseadas em GSI e observe que você não precisa usar as quatro etapas. As etapas escolhidas (apenas a Etapa 1, por exemplo) dependem da sua implementação.

Visão geral da 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 escolher criar um 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 dos SSIs para a versão mais recente do Android. Eles podem reutilizar os SSIs para atualizar vários dispositivos sem atualizar a partição /product.

Os OEMs e os fornecedores de SoC criam SSIs que incluem todos os recursos e modificações personalizadas de que um OEM precisa. Os mecanismos e as práticas recomendadas fornecidos nesta página são destinados a OEMs para alcançar estes objetivos 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 à ideia do Treble de separar componentes específicos do SoC na partição do fornecedor. Uma interface de produto (semelhante ao VINTF) permite a comunicação entre a SSI e a partição do produto. Com relação à SSI, o termo "componentes" descreve todos os recursos, binários, textos, bibliotecas e assim por diante que são instalados em imagens, que se tornam partições.

Partições em torno do SSI

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

Partições e interfaces em torno do diagrama de blocos SSI

Figura 1. Partições e interfaces em torno da SSI

Imagens e partições

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

  • Uma imagem é um software conceitual que pode ser atualizado 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:a SSI é a imagem comum a um OEM e pode existir em vários dispositivos. Ele não tem componentes específicos de hardware ou de produto. Por definição, tudo em um determinado SSI é compartilhado entre todos os dispositivos que usam esse SSI. A SSI é composta por uma única imagem /system ou por uma /system e as partições /system_ext, como mostrado na Figura 1.

    • A partição /system contém componentes baseados no AOSP, enquanto /system_ext, quando implementado, contém extensões de fornecedores de OEM e SoC e componentes que estão intimamente acoplados aos componentes do AOSP. Por exemplo, uma biblioteca de framework Java do OEM que fornece APIs personalizadas para os apps do OEM se encaixa melhor na partição /system_ext do que na partição /system. O conteúdo das partições /system e /system_ext é criado com base em fontes do Android modificadas pelo OEM.

    • A partição /system_ext é opcional, mas é vantajoso usá-la para todos os recursos e extensões personalizados que estão intimamente acoplados a componentes baseados no AOSP. Essa distinção ajuda a identificar as mudanças que precisam ser feitas para mover esses componentes da partição /system_ext para a /product em um período.

  • Produto:uma coleção de componentes específicos do produto ou do 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 apropriados, como os independentes de SoC. Por exemplo, se um fornecedor de SoC fornecer um componente independente de SoC aos clientes OEM (que é opcional no envio com o produto), o fornecedor de SoC poderá colocar esse componente na imagem do produto. O local de um componente não é determinado pela propriedade, mas pelo propósito.

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

  • 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 de SoC e do ODM são mescladas na partição /vendor.

Interfaces entre imagens

Há duas interfaces principais para imagens de fornecedores e produtos em torno do SSI:

  • Interface do fornecedor (VINTF, na sigla em inglês): a VINTF é a interface para os componentes que residem no fornecedor e nas imagens 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 privada da imagem do sistema e vice-versa. Isso foi originalmente definido no Project Treble, que dividiu as imagens em partições do sistema e do fornecedor. A interface é descrita usando os seguintes mecanismos:

    • HIDL: a HAL de passagem só está disponível para módulos system e system_ext.
    • AIDL estável
    • Configurações
      • API de propriedades do sistema
      • API Config File Schema
    • VNDK (link em inglês)
    • APIs do SDK do Android
    • Biblioteca de SDK do Java
  • Interfaces do produto:a interface do produto é a interface entre a SSI e a imagem do produto. A definição de uma interface estável desepara os componentes do produto dos componentes do sistema em um SSI. A interface do produto requer as mesmas interfaces estáveis que o VINTF. No entanto, apenas as APIs do VNDK e do SDK do Android são aplicadas a dispositivos lançados com o Android 11 (e versões mais recentes).

Ativar a SSI no Android 11

Esta seção explica como usar os novos recursos em vigor para oferecer suporte a SSI no Android 11.

A partição /system_ext

A partição /system_ext foi introduzida no Android 11 como uma partição opcional. É o local para componentes que não são do AOSP que têm acoplamento rígido com os componentes definidos pelo AOSP na partição /system. A partição /system_ext é considerada a extensão específica do OEM para a partição /system, sem uma interface definida entre as duas partições. Os componentes na partição /system_ext podem fazer chamadas de API particulares na partição /system, e os componentes na partição /system podem fazer chamadas de API particulares na partição /system_ext.

Como as duas partições são estritamente acopladas, 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. Para 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

Confira um pouco da história da partição /system_ext. O objetivo do design era colocar todos os componentes específicos do OEM, independentemente de serem comuns, na partição /product. No entanto, movê-los todos de uma só vez não era viável, principalmente quando alguns componentes tinham um acoplamento estreito com a partição /system. Para mover um componente acoplado à partição /product, a interface do produto precisa ser estendida. Isso geralmente exigia que o componente fosse refatorado extensivamente, o que consome muito tempo e esforço. A partição /system_ext começou como um local 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óxima possível do AOSP. Com o SSI, a maior parte do esforço de upgrade é gasta nos componentes nas partições /system e /system_ext. Quando a imagem do sistema é criada com base em fontes o mais semelhantes possível às do AOSP, você pode concentrar o esforço de upgrade na imagem system_ext.

Desagrupar componentes das partições /system e /system_ext na partição /product

O Android 9 introduziu uma partição /product vinculada à partição /system. Os módulos na partição /product usam os recursos do sistema sem nenhuma restrição e vice versa. Para permitir a SSI no Android 10, os componentes do produto são divididos em as partições /system_ext e /product. A partição /system_ext não precisa aderir às restrições de uso de componentes do sistema que a partição /product tinha no Android 9. A partir do Android 10, a partição /product precisa ser desempacotada da partição /system e usar interfaces estáveis das partições /system e /system_ext.

O objetivo principal da partição /system_ext é estender os recursos do sistema, em vez de instalar módulos de produtos agrupados, conforme descrito na seção /system_ext partition. Para fazer isso, desempacote os módulos específicos do produto e os mova para a partição /product. A divisão dos módulos específicos do produto torna o /system_ext comum para os dispositivos. Para mais detalhes, consulte Como tornar a partição /system_ext comum.

Para desagrupar a partição /product dos componentes do sistema, a partição /product precisa ter a mesma política de aplicação que a partição /vendor que já estava desagrupada do Projeto Treble.

A partir do Android 11, as interfaces nativas e Java para a partição /product são aplicadas conforme descrito abaixo. Para mais informações, consulte Aplicação de interfaces de Partição de produtos.

  • Interfaces nativas:os módulos nativos na partição /product precisam ser desempacotados das outras partições. As únicas dependências permitidas dos módulos de produto são algumas bibliotecas do VNDK (incluindo o 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 elas são instáveis. Esses módulos só podem usar APIs públicas e do sistema da partição /system e bibliotecas do SDK do Java na partição /system ou /system_ext. É possível definir bibliotecas do SDK para Java para APIs personalizadas.

Etapas sugeridas para a SSI baseada em GSI

Partições sugeridas para SSI com base em GSI

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

Uma imagem genérica do sistema (GSI) é a imagem do sistema criada diretamente do AOSP. Ele é usado para os testes de compliance do Treble (por exemplo, CTS-on-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 com a versão necessária do Android.

Os OEMs também podem usar o GSI para criar o SSI. Conforme explicado em Imagens e partições, o 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 um guia para OEMs que querem modularizar as personalizações nas partições /system_ext e /product ao usar uma imagem do sistema AOSP ou semelhante. Se os OEMs criarem a imagem do sistema com base em fontes do AOSP, eles poderão substituir essa imagem pela GSI fornecida pelo AOSP. No entanto, os OEMs não precisam chegar à etapa final (usando o GSI como está) de uma só vez.

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

Ao herdar generic_system.mk (que foi chamado de mainline_system.mk no Android 11 e renomeado como 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 pelos OEMs para que o GSI do OEM possa conter os arquivos proprietários do OEM, além dos arquivos GSI do AOSP. No entanto, os OEMs não têm permissão para modificar o arquivo generic_system.mk.

Herdar "generic_system.mk" para a imagem do sistema OEM

Figura 3. Herdar 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 com a GSI do AOSP

O GSI do OEM não pode ter arquivos adicionais nesta fase. Os arquivos proprietários do OEM precisam ser movidos para as partições system_ext ou product.

Mover arquivos adicionados para fora do GSI do OEM

Figura 4. Mover arquivos adicionados para fora do GSI do OEM

Etapa 3. Definir uma lista de permissões para limitar os arquivos modificados no 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. Receba o GSI do AOSP do destino de lançamento 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 a necessidade de outras modificações na GSI do OEM.

Definir uma lista de permissões para reduzir a lista de arquivos modificados no GSI do OEM

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

Etapa 4. Fazer com que a GSI do OEM tenha os mesmos binários que a GSI do AOSP

A limpeza da lista de permissões permite que os OEMs usem o GSI do AOSP como a 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 no AOSP para que a GSI inclua as mudanças.

Tornar a GSI do OEM com os mesmos binários da GSI do AOSP

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

Definir SSI para OEMs

Proteger a partição /system no momento da compilação

Para evitar mudanças específicas do produto na partição /system e definir a GSI do OEM, os OEMs podem usar uma macro do makefile chamada require-artifacts-in-path para evitar qualquer declaração de módulos do sistema após a chamada da macro. Consulte o exemplo de como criar um makefile e ativar a verificação de caminho de artefato.

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

Aplicar interfaces de produtos

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

Tornar a partição /system_ext comum

A partição /system_ext pode ser diferente entre os dispositivos, porque pode ter módulos agrupados pelo sistema específicos. Como a SSI consiste em partições /system e /system_ext, as diferenças na partição /system_ext impedem que os OEMs definam uma SSI. Os OEMs podem ter a própria SSI e compartilhar essa SSI entre vários dispositivos removendo quaisquer diferenças e tornando a partição /system_ext comum.

Esta seção oferece recomendações para tornar a partição /system_ext comum.

Expor APIs ocultas na partição do sistema

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

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

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

Incluir o superconjunto de todos os APKs e pular algumas instalações de pacotes para cada dispositivo

Alguns pacotes que vêm com o sistema não são comuns em todos os dispositivos. Descompactar esses módulos de APK para movê-los para o produto ou a partição do fornecedor pode ser difícil. Como solução temporária, os OEMs podem fazer com que o SSI inclua todos os módulos e, em seguida, filtrar os indesejados usando uma propriedade SKU (ro.boot.hardware.sku). Para usar o filtro, os OEMs sobrepõem os recursos config_disableApkUnlessMatchedSku_skus_list e config_disableApksUnlessMatchedSku_apk_list do framework.

Para configurações mais precisas, declare um broadcast receiver que desative pacotes desnecessários. O broadcast receiver chama setApplicationEnabledSetting para desativar o pacote quando recebe a mensagem ACTION_BOOT_COMPLETED.

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

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 maneira, 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 uma RRO manualmente, em vez de depender de uma gerada automaticamente. Para informações detalhadas, consulte Sobreposições de recursos do ambiente de execução (RROs, na sigla em inglês). Os OEMs também podem definir RROs condicionais que dependem das propriedades do sistema usando os atributos android:requiredSystemPropertyName e android:requiredSystemPropertyValue.

Perguntas frequentes

Posso definir vários SSIs?

Isso depende da semelhança 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 Como tornar a partição system_ext comum. Se um grupo de dispositivos tiver muitas diferenças, será melhor definir vários SSIs.

Posso modificar o generic_system.mk (mainline_system.mk) para uma GSI OEM?

Não. Mas os OEMs podem definir um novo makefile para um GSI do OEM que herda o arquivo generic_system.mk e usar o novo makefile. Por exemplo, consulte Como aplicar interfaces de partição de produtos.

Posso remover módulos de general_system.mk que entram em conflito com minha implementação?

Não. O 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 no AOSP.