添加新设备

使用此页面中的信息为您的设备和产品创建 makefile 文件。

每个新的 Android 模块都必须有一个配置文件,以使用模块元数据、编译时依赖项和打包说明来指导构建系统。Android 使用 Soong 构建系统。如需详细了解 Android 构建系统,请参阅构建 Android

了解构建层

构建层次结构包括与设备的物理构成相对应的抽象层。下表介绍了这些层。每一层都以上一层为基础,呈一对多的关系。例如,一个架构可以有多个板,而每个板可以有多个产品。您可以将给定层中的元素定义为同一层中元素的专门化,这样可以避免复制并简化维护。

示例 说明
产品 myProduct、myProduct_eu、myProduct_eu_fr、j2、sdk 产品层定义了出货产品的特性规格,例如要构建的模块、支持的语言区域以及各种语言区域的配置。换句话说,这是整体产品的名称。产品特定的变量在产品定义 makefile 文件中定义。产品可以继承自其他产品定义,从而简化维护。一种常见的方法是创建一个包含适用于所有产品的功能的基础产品,然后基于该基础产品创建产品变体。例如,仅无线装置(CDMA 与 GSM)不同的两个产品可以继承自不定义无线装置的同一基础产品。
板/设备 marlin、blueline、coral 板/设备层代表设备上塑料的物理层(即设备的工业设计)。此层还代表产品的裸原理图。其中包括板上的外围设备及其配置。使用的名称只是不同板/设备配置的代码。
架构 arm、x86、arm64、x86_64 架构层描述了处理器配置和在板上运行的应用程序二进制接口 (ABI)。

使用构建变体

在为特定产品构建时,对最终发布版本进行微小的变更是很有用的。在模块定义中,模块可以使用 LOCAL_MODULE_TAGS 指定标记,标记可以是 optional(默认)、debugeng 的一个或多个值。

如果模块未指定标记(通过 LOCAL_MODULE_TAGS),则其标记默认为 optional。仅当产品配置使用 PRODUCT_PACKAGES 要求可选模块时,才会安装该模块。

以下是当前定义的构建变体。

变体 说明
eng 这是默认风格。
  • 安装标记为 engdebug 的模块。
  • 除了标记的模块外,还根据产品定义文件安装模块。
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • 默认启用 adb
user 旨在成为最终发布版本的变体。
  • 安装标记为 user 的模块。
  • 除了标记的模块外,还根据产品定义文件安装模块。
  • ro.secure=1
  • ro.debuggable=0
  • 默认停用 adb
userdebug user 相同,但有以下例外情况
  • 还安装标记为 debug 的模块。
  • ro.debuggable=1
  • 默认启用 adb

userdebug 指南

在测试中运行 userdebug 构建版本有助于设备开发者了解开发中版本的性能和功耗。为了保持 user 和 userdebug 构建版本之间的一致性,并在用于调试的构建版本中实现可靠的指标,设备开发者应遵循以下指南

  • userdebug 定义为启用了 root 访问权限的用户版本,但以下情况除外
    • 仅限 userdebug 的应用,这些应用仅在用户按需运行时运行
    • 仅在空闲维护期间(充电/充满电时)运行的操作,例如使用 dex2oatd 而不是 dex2oat 进行后台编译
  • 请勿包含默认情况下根据构建类型启用/停用的功能。不鼓励开发者使用任何会影响电池续航时间的日志记录形式,例如调试日志记录或堆转储。
  • userdebug 中默认启用的任何调试功能都应明确定义,并与参与该项目的所有开发者共享。您应仅在有限的时间内启用调试功能,直到您尝试调试的问题得到解决为止。

使用资源叠加层自定义构建

Android 构建系统使用资源叠加层在构建时自定义产品。资源叠加层指定应用于默认资源之上的资源文件。要使用资源叠加层,请修改项目构建文件以将 PRODUCT_PACKAGE_OVERLAYS 设置为相对于顶层目录的路径。当构建系统搜索资源时,该路径将成为与当前根目录一起搜索的影子根目录。

最常用的自定义设置包含在文件 frameworks/base/core/res/res/values/config.xml 中。

要在该文件上设置资源叠加层,请使用以下方法之一将叠加层目录添加到项目构建文件

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

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

然后,将叠加层文件添加到该目录,例如

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

在叠加层 config.xml 文件中找到的任何字符串或字符串数组都会替换原始文件中找到的字符串或字符串数组。

构建产品

您可以采用多种不同的方式来组织设备的源文件。以下是组织 Pixel 实现的一种方式的简要说明。

Pixel 通过名为 marlin 的主设备配置来实现。通过此设备配置,使用产品定义 Makefile 文件创建产品,该文件声明有关设备的特定于产品的信息,例如名称和型号。您可以查看 device/google/marlin 目录,了解所有这些是如何设置的。

编写产品 Makefile 文件

以下步骤介绍了如何以类似于 Pixel 产品线的方式设置产品 Makefile 文件

  1. 为您的产品创建一个 device/<公司名称>/<设备名称> 目录。例如,device/google/marlin。此目录将包含您设备的源代码以及用于构建它们的文件。
  2. 创建一个 device.mk Makefile 文件,该文件声明设备所需的文件和模块。有关示例,请参阅 device/google/marlin/device-marlin.mk
  3. 创建一个产品定义 Makefile 文件,以基于设备创建特定产品。以下 Makefile 文件取自 device/google/marlin/aosp_marlin.mk 作为示例。请注意,产品通过 Makefile 文件继承自 device/google/marlin/device-marlin.mkvendor/google/marlin/device-vendor-marlin.mk 文件,同时还声明了特定于产品的信息,例如名称、品牌和型号。
    # 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
    

    如需了解您可以添加到 Makefile 文件的其他产品特定变量,请参阅设置产品定义变量

  4. 创建一个 AndroidProducts.mk 文件,该文件指向产品的 Makefile 文件。在本示例中,只需要产品定义 Makefile 文件。以下示例来自 device/google/marlin/AndroidProducts.mk(其中包含 marlin(Pixel)和 sailfish(Pixel XL),它们共享大部分配置)
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. 创建一个 BoardConfig.mk Makefile 文件,其中包含特定于板的配置。有关示例,请参阅 device/google/marlin/BoardConfig.mk
  6. 仅适用于 Android 9 及更低版本,创建一个 vendorsetup.sh 文件,以将您的产品(“lunch combo”)以及用破折号分隔的构建变体添加到构建中。例如
    add_lunch_combo <product-name>-userdebug
    
  7. 此时,您可以基于同一设备创建更多产品变体。

设置产品定义变量

产品特定的变量在产品的 Makefile 文件中定义。下表显示了产品定义文件中维护的一些变量。

变量 说明 示例
PRODUCT_AAPT_CONFIG 创建软件包时要使用的 aapt 配置。
PRODUCT_BRAND 软件为其自定义的品牌(例如,运营商)。
PRODUCT_CHARACTERISTICS aapt 特性,允许向软件包添加特定于变体的资源。 tabletnosdcard
PRODUCT_COPY_FILES 类似于 source_path:destination_path 的单词列表。构建此产品时,源路径中的文件应复制到目标路径。复制步骤的规则在 config/makefile 中定义。
PRODUCT_DEVICE 工业设计的名称。这也是板名称,构建系统使用它来查找 BoardConfig.mk tuna
PRODUCT_LOCALES 以空格分隔的两个字母语言代码、两个字母国家/地区代码对的列表,用于描述用户的多个设置,例如 UI 语言以及时间、日期和货币格式。在 PRODUCT_LOCALES 中列出的第一个语言区域用作产品的默认语言区域。 en_GBde_DEes_ESfr_CA
PRODUCT_MANUFACTURER 制造商的名称。 acme
PRODUCT_MODEL 最终产品的最终用户可见名称。
PRODUCT_NAME 整体产品的最终用户可见名称。显示在设置 > 关于屏幕中。
PRODUCT_OTA_PUBLIC_KEYS 产品的无线下载 (OTA) 公钥列表。
PRODUCT_PACKAGES 要安装的 APK 和模块的列表。 日历联系人
PRODUCT_PACKAGE_OVERLAYS 指示是使用默认资源还是添加任何产品特定叠加层。 vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES 系统分区的格式为 "key=value" 的系统属性分配列表。其他分区的系统属性可以通过 PRODUCT_<PARTITION>_PROPERTIES 设置,例如供应商分区的 PRODUCT_VENDOR_PROPERTIES。支持的分区名称:SYSTEMVENDORODMSYSTEM_EXTPRODUCT

配置默认系统语言和区域设置过滤器

使用此信息配置默认语言和系统区域设置过滤器,然后为新的设备类型启用区域设置过滤器。

属性

使用专用系统属性配置默认语言和系统区域设置过滤器

  • ro.product.locale:用于设置默认区域设置。这最初设置为 PRODUCT_LOCALES 变量中的第一个区域设置;您可以覆盖该值。(如需了解详情,请参阅设置产品定义变量表。)
  • ro.localization.locale_filter:用于设置区域设置过滤器,使用应用于区域设置名称的正则表达式。例如
    • 包含性过滤器:^(de-AT|de-DE|en|uk).* - 仅允许德语(奥地利和德国变体)、所有英语变体和乌克兰语
    • 排除性过滤器:^(?!de-IT|es).* - 排除德语(意大利变体)和所有西班牙语变体。

启用区域设置过滤器

要启用过滤器,请设置 ro.localization.locale_filter 系统属性字符串值。

通过在工厂校准期间通过 oem/oem.prop 设置过滤器属性值和默认语言,您可以配置限制,而无需将过滤器烘焙到系统映像中。您可以通过将这些属性添加到如下所示的 PRODUCT_OEM_PROPERTIES 变量中,确保从 OEM 分区中选取这些属性

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

然后在生产中,实际值将写入 oem/oem.prop,以反映目标要求。使用这种方法,默认值在恢复出厂设置期间保留,因此初始设置看起来与用户的首次设置完全一样。

设置 ADB_VENDOR_KEYS 以通过 USB 连接

ADB_VENDOR_KEYS 环境变量使设备制造商能够通过 adb 访问可调试版本(-userdebug 和 -eng,但不是 -user),而无需手动授权。通常,adb 为每台客户端计算机生成唯一的 RSA 身份验证密钥,并将其发送到任何连接的设备。这是 adb 授权对话框中显示的 RSA 密钥。作为替代方案,您可以将已知密钥构建到系统映像中,并与 adb 客户端共享。这对于操作系统开发尤其对于测试非常有用,因为它避免了手动与 adb 授权对话框交互的需要。

要创建供应商密钥,一个人(通常是发布经理)应执行以下操作

  1. 使用 adb keygen 生成密钥对。对于 Google 设备,Google 会为每个新的操作系统版本生成一个新的密钥对。
  2. 将密钥对检入到源代码树中的某个位置。例如,Google 将它们存储在 vendor/google/security/adb/ 中。
  3. 设置构建变量 PRODUCT_ADB_KEYS 以指向您的密钥目录。Google 通过在密钥目录中添加一个 Android.mk 文件来实现此目的,该文件声明 PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub,这有助于确保我们记住为每个操作系统版本生成新的密钥对。

以下是 Google 在我们存储每个版本的已检入密钥对的目录中使用的 Makefile 文件

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

要使用这些供应商密钥,工程师只需设置 ADB_VENDOR_KEYS 环境变量,使其指向密钥对存储在其中的目录即可。这告诉 adb 首先尝试这些规范密钥,然后再回退到需要手动授权的生成的主机密钥。当 adb 无法连接到未经授权的设备时,如果尚未设置 ADB_VENDOR_KEYS,则错误消息将建议您设置它。