Adicionando um novo dispositivo

Use as informações nesta página para criar os makefiles para seu dispositivo e produto.

Cada novo módulo Android deve ter um arquivo de configuração para direcionar o sistema de compilação com metadados do módulo, dependências de tempo de compilação e instruções de empacotamento. O Android usa o sistema de compilação Soong . Consulte Compilando o Android para obter mais informações sobre o sistema de compilação do Android.

Entendendo as camadas de construção

A hierarquia de construção inclui as camadas de abstração que correspondem à composição física de um dispositivo. Essas camadas são descritas na tabela abaixo. Cada camada se relaciona com a que está acima dela em um relacionamento de um para muitos. Por exemplo, uma arquitetura pode ter mais de uma placa e cada placa pode ter mais de um produto. Você pode definir um elemento em uma determinada camada como uma especialização de um elemento na mesma camada, o que elimina a cópia e simplifica a manutenção.

Camada Exemplo Descrição
produtos meuProduto, meuProduto_eu, meuProduto_eu_fr, j2, sdk A camada do produto define a especificação do recurso de um produto de envio, como os módulos a serem construídos, os códigos de idioma suportados e a configuração para vários códigos de idioma. Em outras palavras, este é o nome do produto geral. As variáveis ​​específicas do produto são definidas nos makefiles de definição do produto. Um produto pode herdar de outras definições de produto, o que simplifica a manutenção. Um método comum é criar um produto base que contém recursos que se aplicam a todos os produtos e, em seguida, criar variantes de produto com base nesse produto base. Por exemplo, dois produtos que diferem apenas por seus rádios (CDMA versus GSM) podem herdar do mesmo produto base que não define um rádio.
Placa/dispositivo marlim, linha azul, coral A camada da placa/dispositivo representa a camada física de plástico no dispositivo (ou seja, o design industrial do dispositivo). Esta camada também representa os esquemas simples de um produto. Isso inclui os periféricos da placa e sua configuração. Os nomes usados ​​são apenas códigos para diferentes configurações de placa/dispositivo.
Arco braço, x86, braço64, x86_64 A camada de arquitetura descreve a configuração do processador e a interface binária do aplicativo (ABI) em execução na placa.

Como usar variantes de compilação

Ao compilar para um produto específico, é útil ter pequenas variações na compilação da versão final. Em uma definição de módulo, o módulo pode especificar tags com LOCAL_MODULE_TAGS , que podem ser um ou mais valores de optional (default), debug e eng .

Se um módulo não especificar uma tag (por LOCAL_MODULE_TAGS ), sua tag padrão será optional . Um módulo opcional é instalado somente se for exigido pela configuração do produto com PRODUCT_PACKAGES .

Estas são as variantes de compilação atualmente definidas.

Variante Descrição
eng Este é o sabor padrão.
  • Instala módulos marcados com eng ou debug .
  • Instala os módulos de acordo com os arquivos de definição do produto, além dos módulos marcados.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb está habilitado por padrão.
user A variante destinada a ser os bits de lançamento final.
  • Instala módulos marcados com user .
  • Instala os módulos de acordo com os arquivos de definição do produto, além dos módulos marcados.
  • ro.secure=1
  • ro.debuggable=0
  • adb está desabilitado por padrão.
userdebug O mesmo que user , com estas exceções:
  • Também instala módulos marcados com debug .
  • ro.debuggable=1
  • adb está habilitado por padrão.

Diretrizes para userdebug

A execução de builds de userdebug em testes ajuda os desenvolvedores de dispositivos a entender o desempenho e o poder das versões em desenvolvimento. Para manter a consistência entre as compilações do usuário e do userdebug e para obter métricas confiáveis ​​nas compilações usadas para depuração, os desenvolvedores de dispositivos devem seguir estas diretrizes:

  • userdebug é definido como uma compilação de usuário com acesso root habilitado, exceto:
    • aplicativos somente de depuração do usuário que são executados apenas sob demanda pelo usuário
    • Operações que são executadas apenas durante a manutenção ociosa (no carregador/carregado totalmente), como usar dex2oatd versus dex2oat para compilações em segundo plano
  • Não inclua recursos habilitados/desabilitados por padrão com base no tipo de compilação. Os desenvolvedores são desencorajados a usar qualquer forma de registro que afete a vida útil da bateria, como registro de depuração ou despejo de heap.
  • Quaisquer recursos de depuração habilitados por padrão no userdebug devem ser claramente definidos e compartilhados com todos os desenvolvedores que trabalham no projeto. Você deve habilitar os recursos de depuração apenas por tempo limitado até que o problema que você está tentando depurar seja resolvido.

Personalizando a compilação com sobreposições de recursos

O sistema de compilação do Android usa sobreposições de recursos para personalizar um produto no momento da compilação. As sobreposições de recursos especificam arquivos de recursos que são aplicados sobre os padrões. Para usar sobreposições de recursos, modifique o arquivo de compilação do projeto para definir PRODUCT_PACKAGE_OVERLAYS como um caminho relativo ao seu diretório de nível superior. Esse caminho se torna uma raiz sombra pesquisada junto com a raiz atual quando o sistema de compilação pesquisa recursos.

As configurações personalizadas mais comuns estão contidas no arquivo frameworks/base/core/res/res/values/config.xml .

Para configurar uma sobreposição de recurso neste arquivo, adicione o diretório de sobreposição ao arquivo de compilação do projeto usando um dos seguintes:

PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay

ou

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

Em seguida, adicione um arquivo de sobreposição ao diretório, por exemplo:

vendor/foobar/overlay/frameworks/base/core/res/res/values/config.xml

Quaisquer strings ou matrizes de strings encontradas no arquivo config.xml de sobreposição substituem aquelas encontradas no arquivo original.

Construindo um produto

Você pode organizar os arquivos de origem do seu dispositivo de várias maneiras. Aqui está uma breve descrição de uma maneira de organizar uma implementação do Pixel.

Pixel é implementado com uma configuração de dispositivo principal chamada marlin . A partir dessa configuração de dispositivo, um produto é criado com um makefile de definição de produto que declara informações específicas do produto sobre o dispositivo, como nome e modelo. Você pode ver o diretório device/google/marlin para ver como tudo isso está configurado.

Escrevendo makefiles de produtos

As etapas a seguir descrevem como configurar os makefiles do produto de maneira semelhante à da linha de produtos Pixel:

  1. Crie um diretório device/ <company-name> / <device-name> para seu produto. Por exemplo, device/google/marlin . Este diretório conterá o código-fonte do seu dispositivo junto com os makefiles para construí-los.
  2. Crie um makefile device.mk que declare os arquivos e módulos necessários para o dispositivo. Para obter um exemplo, consulte device/google/marlin/device-marlin.mk .
  3. Crie um makefile de definição de produto para criar um produto específico com base no dispositivo. O seguinte makefile foi retirado de device/google/marlin/aosp_marlin.mk como exemplo. Observe que o produto herda dos arquivos device/google/marlin/device-marlin.mk e vendor/google/marlin/device-vendor-marlin.mk por meio do makefile, ao mesmo tempo em que declara as informações específicas do produto, como nome, marca, e modelo.
    # Inherit from the common Open Source product configuration
    $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
    
    PRODUCT_NAME := aosp_marlin
    PRODUCT_DEVICE := marlin
    PRODUCT_BRAND := Android
    PRODUCT_MODEL := AOSP on msm8996
    PRODUCT_MANUFACTURER := Google
    PRODUCT_RESTRICT_VENDOR_FILES := true
    
    PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin
    
    $(call inherit-product, device/google/marlin/device-marlin.mk)
    $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk)
    
    PRODUCT_PACKAGES += \
        Launcher3QuickStep \
        WallpaperPicker
    

    Consulte Configurando variáveis ​​de definição de produto para variáveis ​​adicionais específicas do produto que você pode adicionar aos seus makefiles.

  4. Crie um arquivo AndroidProducts.mk que aponte para os makefiles do produto. Neste exemplo, apenas o makefile de definição do produto é necessário. O exemplo abaixo é de device/google/marlin/AndroidProducts.mk (que contém marlin, o Pixel, e sailfish, o Pixel XL, que compartilhou a maioria das configurações):
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. Crie um makefile BoardConfig.mk que contenha configurações específicas da placa. Para obter um exemplo, consulte device/google/marlin/BoardConfig.mk .
  6. Somente para Android 9 e versões anteriores , crie um arquivo vendorsetup.sh para adicionar seu produto (uma "combinação de almoço") à versão juntamente com uma variante de versão separada por um traço. Por exemplo:
    add_lunch_combo <product-name>-userdebug
    
  7. Neste ponto, você pode criar mais variantes de produtos com base no mesmo dispositivo.

Como definir variáveis ​​de definição de produto

As variáveis ​​específicas do produto são definidas no makefile do produto. A tabela mostra algumas das variáveis ​​mantidas em um arquivo de definição de produto.

Variável Descrição Exemplo
PRODUCT_AAPT_CONFIG configurações do aapt para usar ao criar pacotes.
PRODUCT_BRAND A marca (por exemplo, operadora) para a qual o software é personalizado, se houver.
PRODUCT_CHARACTERISTICS características do aapt para permitir a adição de recursos específicos de variantes a um pacote. tablet , nosdcard
PRODUCT_COPY_FILES Lista de palavras como source_path:destination_path . O arquivo no caminho de origem deve ser copiado para o caminho de destino ao construir este produto. As regras para as etapas de cópia são definidas em config/makefile .
PRODUCT_DEVICE Nome do desenho industrial. Este também é o nome da placa, e o sistema de compilação o utiliza para localizar BoardConfig.mk . tuna
PRODUCT_LOCALES Uma lista separada por espaços de código de idioma de duas letras, pares de códigos de país de duas letras que descrevem várias configurações para o usuário, como o idioma da interface do usuário e a formatação de hora, data e moeda. A primeira localidade listada em PRODUCT_LOCALES é usada como localidade padrão do produto. en_GB , de_DE , es_ES , fr_CA
PRODUCT_MANUFACTURER Nome do fabricante. acme
PRODUCT_MODEL Nome do produto final visível ao usuário final.
PRODUCT_NAME Nome visível ao usuário final para o produto geral. Aparece na tela Configurações > Sobre .
PRODUCT_OTA_PUBLIC_KEYS Lista de chaves públicas OTA (over-the-air) para o produto.
PRODUCT_PACKAGES Lista dos APKs e módulos a serem instalados. Contatos do calendário
PRODUCT_PACKAGE_OVERLAYS Indica se deve usar recursos padrão ou adicionar sobreposições específicas do produto. vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES Lista das atribuições de propriedades do sistema no formato "key=value" para a partição do sistema. As propriedades do sistema para outras partições podem ser definidas por meio de PRODUCT_<PARTITION>_PROPERTIES como em PRODUCT_VENDOR_PROPERTIES para a partição do fornecedor. Nomes de partição suportados: SYSTEM , SYSTEM_EXT , ODM , VENDOR e PRODUCT .

Configurando o idioma padrão do sistema e o filtro de localidade

Use essas informações para configurar o idioma padrão e o filtro de localidade do sistema e, em seguida, habilite o filtro de localidade para um novo tipo de dispositivo.

Propriedades

Configure o idioma padrão e o filtro de localidade do sistema usando propriedades de sistema dedicadas:

  • ro.product.locale : para definir a localidade padrão. Isso é definido inicialmente para a primeira localidade na variável PRODUCT_LOCALES ; você pode substituir esse valor. (Para obter mais informações, consulte a tabela Configurando variáveis ​​de definição de produto .)
  • ro.localization.locale_filter : para definir um filtro de localidade, usando uma expressão regular aplicada a nomes de localidade. Por exemplo:
    • Filtro inclusivo: ^(de-AT|de-DE|en|uk).* - permite apenas alemão (variantes da Áustria e Alemanha), todas as variantes em inglês do inglês e ucraniano
    • Filtro exclusivo: ^(?!de-IT|es).* - exclui alemão (variante Itália) e todas as variantes de espanhol.

Habilitando o filtro de localidade

Para ativar o filtro, defina o valor da cadeia de caracteres da propriedade do sistema ro.localization.locale_filter .

Ao definir o valor da propriedade do filtro e o idioma padrão por meio de oem/oem.prop durante a calibração de fábrica, você pode configurar restrições sem inserir o filtro na imagem do sistema. Você garante que essas propriedades sejam selecionadas da partição OEM adicionando-as à variável PRODUCT_OEM_PROPERTIES conforme indicado abaixo:

# Delegation for OEM customization
PRODUCT_OEM_PROPERTIES += \
    ro.product.locale \
    ro.localization.locale_filter

Então, na produção, os valores reais são gravados em oem/oem.prop , para refletir os requisitos de destino. Com essa abordagem, os valores padrão são retidos durante a redefinição de fábrica, de modo que as configurações iniciais pareçam exatamente como uma primeira configuração para o usuário.

Configurando ADB_VENDOR_KEYS para conectar via USB

A variável de ambiente ADB_VENDOR_KEYS permite que fabricantes de dispositivos acessem compilações depuráveis ​​(-userdebug e -eng, mas não -user) sobre adb sem autorização manual. Normalmente, o adb gera uma chave de autenticação RSA exclusiva para cada computador cliente, que será enviada para qualquer dispositivo conectado. Esta é a chave RSA mostrada na caixa de diálogo de autorização do adb. Como alternativa, você pode criar chaves conhecidas na imagem do sistema e compartilhá-las com o cliente adb. Isso é útil para o desenvolvimento do SO e especialmente para testes, pois evita a necessidade de interagir manualmente com a caixa de diálogo de autorização do adb.

Para criar chaves de fornecedor, uma pessoa (geralmente um gerente de versão) deve:

  1. Gere um par de chaves usando adb keygen . Para dispositivos Google, o Google gera um novo par de chaves para cada nova versão do sistema operacional.
  2. Verifique os pares de chaves, em algum lugar na árvore de origem. O Google os armazena em vendor/google/security/adb/ , por exemplo.
  3. Defina a variável de compilação PRODUCT_ADB_KEYS para apontar para seu diretório de chaves. O Google faz isso adicionando um arquivo Android.mk no diretório de chaves que diz PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub , o que ajuda a garantir que nos lembremos de gerar um novo par de chaves para cada versão do SO.

Aqui está o makefile que o Google usa no diretório onde armazenamos nossos pares de chaves com check-in para cada versão:

PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub

ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),)
  $(warning ========================)
  $(warning The adb key for this release)
  $(warning )
  $(warning   $(PRODUCT_ADB_KEYS))
  $(warning )
  $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk)
  $(warning has changed and a new adb key needs to be generated.)
  $(warning )
  $(warning Please run the following commands to create a new key:)
  $(warning )
  $(warning   make -j8 adb)
  $(warning   LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS)))
  $(warning )
  $(warning and upload/review/submit the changes)
  $(warning ========================)
  $(error done)
endif

Para usar essas chaves de fornecedor, um engenheiro precisa apenas definir a variável de ambiente ADB_VENDOR_KEYS para apontar para o diretório no qual os pares de chaves estão armazenados. Isso diz ao adb para tentar essas chaves canônicas primeiro, antes de retornar à chave do host gerada que requer autorização manual. Quando o adb não puder se conectar a um dispositivo não autorizado, a mensagem de erro sugerirá que você defina ADB_VENDOR_KEYS se ainda não estiver definido.