Adicionar um novo dispositivo

Use as informações nesta página para criar 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 Construindo o Android para obter mais informações sobre o sistema de compilação do Android.

Entenda 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 aquela acima em um relacionamento 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 de produto define a especificação de recursos de um produto enviado, como os módulos a serem construídos, localidades suportadas e configuração para diversas localidades. Em outras palavras, este é o nome do produto geral. Variáveis ​​específicas do produto são definidas em makefiles de definição de produto. Um produto pode herdar definições de outros produtos, o que simplifica a manutenção. Um método comum é criar um produto base que contenha 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 em seus rádios (CDMA versus GSM) podem herdar o mesmo produto base que não define um rádio.
Placa/dispositivo marlim, linha azul, coral A camada placa/dispositivo representa a camada física de plástico do dispositivo (ou seja, o design industrial do dispositivo). Esta camada também representa os esquemas básicos de um produto. Isso inclui os periféricos da placa e sua configuração. Os nomes usados ​​são meramente 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.

Use variantes de compilação

Ao construir para um produto específico, é útil ter pequenas variações na 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 (padrão), debug e eng .

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

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

Variante Descrição
eng Este é o sabor padrão.
  • Instala módulos marcados com eng ou debug .
  • Instala 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 pretendia ser os bits finais do lançamento.
  • Instala módulos marcados com user .
  • Instala 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 compilações userdebug em testes ajuda os desenvolvedores de dispositivos a compreender o desempenho e o poder das versões em desenvolvimento. Para manter a consistência entre as compilações user e userdebug e para obter métricas confiáveis ​​em 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 userdebug que são executados apenas sob demanda do usuário
    • Operações que são executadas apenas durante a manutenção ociosa (no carregador/totalmente carregado), 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 build. Os desenvolvedores são desencorajados de 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 ativar os recursos de depuração apenas por tempo limitado até que o problema que você está tentando depurar seja resolvido.

Personalize a construçã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 buildfile 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 procura recursos.

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

Para configurar uma sobreposição de recursos neste arquivo, adicione o diretório de sobreposição ao buildfile 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 sequências ou matrizes de sequências encontradas no arquivo config.xml de sobreposição substituem aquelas encontradas no arquivo original.

Construa um produto

Você pode organizar os arquivos de origem do seu dispositivo de muitas maneiras diferentes. 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 visualizar o diretório device/google/marlin para ver como tudo isso está configurado.

Escreva makefiles de produtos

As etapas a seguir descrevem como configurar makefiles de produtos de maneira semelhante à 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. Por 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 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 podem ser incluídas em 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 compartilhava a maior parte 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. Por 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") ao build junto com uma variante de build 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.

Definir variáveis ​​de definição de produto

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 aapt para usar ao criar pacotes.
PRODUCT_BRAND A marca (por exemplo, operadora) para a qual o software é personalizado.
PRODUCT_CHARACTERISTICS características aapt para permitir a adição de recursos específicos de variante 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ódigos de idioma de duas letras e pares de códigos de país de duas letras que descrevem diversas configurações para o usuário, como o idioma da interface do usuário e a formatação de hora, data e moeda. O primeiro código de idioma listado em PRODUCT_LOCALES é usado como código de idioma padrão do produto. en_GB , de_DE , es_ES , fr_CA
PRODUCT_MANUFACTURER Nome do fabricante. acme
PRODUCT_MODEL Nome visível para o usuário final do produto final.
PRODUCT_NAME Nome visível para o usuário final do produto geral. Aparece na tela Configurações > Sobre .
PRODUCT_OTA_PUBLIC_KEYS Lista de chaves públicas over-the-air (OTA) para o produto.
PRODUCT_PACKAGES Lista de APKs e módulos para instalar. Contatos do calendário
PRODUCT_PACKAGE_OVERLAYS Indica se serão usados ​​recursos padrão ou se serão adicionadas 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 configuradas por meio de PRODUCT_<PARTITION>_PROPERTIES como em PRODUCT_VENDOR_PROPERTIES para a partição do fornecedor. Nomes de partição suportados: SYSTEM , VENDOR , ODM , SYSTEM_EXT e PRODUCT .

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

Use estas informações para configurar o idioma padrão e o filtro de localidade do sistema e, em seguida, ative 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. Inicialmente, isso é definido como o primeiro código do idioma 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 aos 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 inglesas do inglês e ucraniano
    • Filtro exclusivo: ^(?!de-IT|es).* - exclui alemão (variante da Itália) e todas as variantes do espanhol.

Habilite o filtro de localidade

Para ativar o filtro, configure o valor da sequência 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 obtidas 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 alvo. Com esta abordagem, os valores padrão são mantidos 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.

Defina ADB_VENDOR_KEYS para conectar via USB

A variável de ambiente ADB_VENDOR_KEYS permite que os fabricantes de dispositivos acessem compilações depuráveis ​​(-userdebug e -eng, mas não -user) por meio de 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 desenvolvimento de sistema operacional e especialmente para testes porque 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 lançamento) 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 da árvore de origem. O Google os armazena em vendor/google/security/adb/ , por exemplo.
  3. Defina a variável de construçã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 sistema operacional.

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 só precisa 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 adb para tentar essas chaves canônicas primeiro, antes de voltar para a chave do host gerada que requer autorização manual. Quando adb não consegue se conectar a um dispositivo não autorizado, a mensagem de erro irá sugerir que você defina ADB_VENDOR_KEYS se ainda não estiver definido.