Android 新增 device 配置介绍


1. 概述

本文档将会介绍如何新增一个设备和相应的 Makefile。每个新的 Android 模块都必须具有配置文件,以使用模块元数据、编译时依赖项和打包指令来指引构建系统。

2. 构建层

构建层次结构包括与设备的物理结构对应的抽象层。下表中介绍了这些层。每一层都与上一层存在一对多的关系。例如,一个架构可以有多个主板,一个主板可以有多个产品。可以将指定层中的某个元素定义为同一层中某个元素的特化元素,这样可以免去复制操作并简化维护工作。

示例 说明
产品 pioneer5_sdp、pioneer5_viop 产品名称
主板/设备 pioneer5、infinity7 主板代号/名称
架构 arm、x86、arm64 和 x86_64 主板上运行的处理器配置和应用二进制接口 (ABI)。

3. build 变体

在针对特定产品进行构建时,如果能在最终发布 build 的基础上有细微的变化,会非常有用。在模块定义中,模块可以通过 LOCAL_MODULE_TAGS 指定标记,这些标记可以是以下一个或多个值:optional(默认值)、debug , enguser

如果某个模块没有通过 LOCAL_MODULE_TAGS 指定标记,则其标记默认设置为 optional。仅当 PRODUCT_PACKAGES 的产品配置需要可选模块时,系统才会安装可选模块。

下面是当前定义的 build 变体。

变体 说明
eng 这是默认变种。安装带有 engdebug 标记的模块。除了带有标记的模块之外,还会根据产品定义文件安装相应模块。ro.secure=0ro.debuggable=1ro.kernel.android.checkjni=1, adb 默认处于启用状态。
user 打算作为最终发布版本的变体。安装带有 user 标记的模块。除了带有标记的模块之外,还会根据产品定义文件安装相应模块。ro.secure=1ro.debuggable=0, adb 默认处于停用状态。
userdebug user 相同,但以下几点除外:还会安装带有 debug 标记的模块。ro.debuggable=1,adb 默认处于启用状态。

4. 构建产品

可以通过多种不同的方式来组织设备的源文件。下面简要说明了 sigmastar 实现的一种组织方式。

为 sigmastar 实现名为 pioneer 的主设备配置(主板代号)。根据此设备配置,为产品创建产品定义 Makefile,用于声明关于设备的产品特定信息,例如名称和型号。可以查看 device/sigmastar/pioneer 目录,了解所有相关配置的具体设置方式。

4.1. 编写产品 Makefile

以下步骤介绍了如何采用与设置产品 Makefile:

1、 为产品创建一个 device/<company-name>/<device-name> 目录。例如,device/sigmastar/pioneer。此目录将包含设备的源代码以及构建这些代码所需的 Makefile。

2、 创建一个 device-common.mk Makefile,用来声明设备上搭载的所有产品所需的文件和模块。具体可以参考 device/sigmastar/pioneer/device-common.mk

3、 创建一个包含主板特定配置的公共 BoardConfig-common.mk Makefile,这里只会配置该设备上所有产品共有的主板配置。可以参考 device/sigmastar/pioneer/pioneer_sdp/BoardConfig-common.mk

4、 为具体设备所对应产品创建一个 device/<company-name>/<device-name>/<product-name> 子目录并创建一个 device.mk Makefile,用来声明该产品所需设备上搭载的的文件和模块。具体可以参考 device/sigmastar/pioneer/pioneer_sdp/device.mk。该 Makefile 会沿用 device/sigmastar/pioneer/device-common.mk 中的设置。

编写 device.mk 或者 device-common.mk makefile 一般厂商需要配置以下几部分内容:

  1. 添加产品必须的 HAL 模块;

    # HW Composer HAL(must)
    PRODUCT_PACKAGES +=
        android.hardware.graphics.composer@2.4-service
        hwcomposer.sstar
    
  2. 添加必要的 property 属性值;

    # OpenGLES/EGL/Vulkan
    PRODUCT_VENDOR_PROPERTIES +=
        ro.hardware.egl=mali
    PRODUCT_PACKAGES +=
        libGLES_mali
        vulkan.sstar
    
  3. 拷贝必要的配置文件到指定路径;

    # Feature
    PRODUCT_COPY_FILES +=
        frameworks/native/data/etc/android.hardware.usb.accessory.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.accessory.xml \
    
  4. 添加厂商客制化组件。

    # Smart Display APKs
    PRODUCT_PACKAGES +=
        LiveTv
        SStarTvInputService
        SStarTvSourceChange
        SStarFactoryMenu
        SStarCustomizedMenu
    

当然除了以上内容,还可以根据实际的需求添加必要的模块或者配置。

5、 创建一个产品定义 Makefile,以便基于设备创建具体产品。以下示例 Makefile 来自于 device/sigmastar/pioneer/pioneer_sdp/sstar_pioneer5.mk。该产品会通过 Makefile 沿用 device/sigmastar/pioneer/pioneer_sdp/device.mk 中的设置,同时还会声明产品特定信息,例如名称、品牌和型号。

$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/sdp_generic_system.mk)

$(call inherit-product, device/sigmastar/common/products/sdp_system_ext.mk)
$(call inherit-product, device/sigmastar/common/products/sdp_product.mk)
$(call inherit-product, device/sigmastar/common/products/sdp_vendor.mk)

$(call inherit-product, device/sigmastar/pioneer/pioneer_sdp/device.mk)

PRODUCT_MANUFACTURER := SigmaStar
PRODUCT_BRAND := Android
PRODUCT_NAME := sstar_pioneer5_sdp
PRODUCT_DEVICE := pioneer5_sdp
PRODUCT_MODEL := AOSP sdp on pioneer5

创建编写产品的 Makefile 往往需要去沿用 Android 必备的一些配置 Makefile,这些 Makefile 位于 Android 源码树的 /build/make/target/product/ 目录下。

// /build/make/target/product/ 目录下文件

AndroidProducts.mk
OWNERS
aosp_64bitonly_x86_64.mk // aosp 只针对 64 位设备的额外配置
aosp_arm.mk // aosp 针对 arm64 cpu 架构设备的参考配置
aosp_arm64.mk // aosp 针对 arm cpu 架构设备的参考配置
aosp_base.mk // aosp 的基本配置
aosp_base_telephony.mk // aosp 对于手机产品的基础配置
aosp_product.mk //  aosp 针对 product 分区的配置
aosp_x86.mk // aosp 针对 x86 cpu 架构设备的参考配置
aosp_x86_64.mk // aosp 针对 x86 64 cpu 架构设备的参考配置
aosp_x86_arm.mk // aosp 针对 x86 arm cpu 架构设备的参考配置
base.mk // base_product.mk,base_system.mk,base_system_ext.mk,base_vendor.mk的集合
base_product.mk // 系统 product 分区最基本的配置
base_system.mk // 系统 system 分区最基本的配置
base_system_ext.mk // 系统 system_ext 分区最基本的配置
base_vendor.mk // 系统 vendor 分区最基本的配置
cfi-common.mk // cfi 的公共配置
core_64_bit.mk // 64位设备配置参考
core_64_bit_only.mk // 64位设备额外配置
core_minimal.mk //核心最低
default_art_config.mk // 默认 art 相关配置参考
emulator.mk // 模拟器配置
emulator_system.mk // 模拟器 system 分区配置
emulator_vendor.mk // 模拟器 vendor 分区配置
generic.mk // 通用配置参考
generic_no_telephony.mk // 非手机设备通用配置参考
generic_ramdisk.mk // 通用 ramdisk 配置参考
generic_system.mk // 通用 system 分区配置参考
generic_system_arm64.mk // 通用 arm64 cpu 系统配置参考
generic_system_x86.mk // 通用 x86 系统配置参考
generic_system_x86_64.mk // 通用 x86 64 系统配置参考
generic_system_x86_arm.mk // 通用 x86 arm 系统配置参考
generic_x86.mk // 通用 x86 配置参考
go_defaults.mk // go 版本默认配置
go_defaults_512.mk // 512 G内存 go 版本默认配置
go_defaults_common.mk // go 版本公共默认配置
gsi_keys.mk // gsi key 配置
gsi_release.mk // gsi release 配置
handheld_product.mk // 手持设备 product 分区配置
handheld_system.mk // 手持设备 system 分区配置
handheld_system_ext.mk // 手持设备 system_ext 分区配置
handheld_vendor.mk // 手持设备 vendor 分区配置
...
telephony.mk // 手机设备配置集合
telephony_product.mk // 手机设备 product 分区配置参考
telephony_system.mk // 手机设备 system 分区配置参考
telephony_system_ext.mk // 手机设备 system_ext 分区配置参考
telephony_vendor.mk // 手机设备 vendor 分区配置参考
updatable_apex.mk // updatable apex 功能配置参考
...

Sigmastar 为了集成某类特定产品所需的公用的 Makefile,所以在 device/sigmastar/common/products 目录下预置了一些通用的 Makefile 供构建产品时使用。

fpga_product.mk // fpga 设备通用 product 分区配置
fpga_system.mk // fpga 设备通用 system 分区配置
fpga_system_ext.mk // fpga 设备通用 system_ext 分区配置
fpga_vendor.mk // fpga 设备通用 vendor 分区配置
handheld_generic_system.mk // 手持设备通用系统配置
sdp_generic_system.mk // sdp 设备通用系统配置
sdp_lowram_defaults.mk // sdp 设备低内存默认配置
sdp_product.mk // sdp 设备通用 product 分区配置
sdp_system.mk // sdp 设备通用 system 分区配置
sdp_system_ext.mk // sdp 设备通用 system_ext 分区配置
sdp_vendor.mk // sdp 设备通用 vendor 分区配置

产品可以根据实际产品类型特性来选择所需沿用的 Makefile。例如前例中的 Makefile 中就沿用了 core_64_bit_only.mksdp_generic_system.mk 这两个 Makefile。

6、 创建一个指向产品 Makefile 的 AndroidProducts.mk 文件。以下示例来自于 device/sigmastar/pioneer/AndroidProducts.mk(该文件同时包含 pioneer 设备上搭载的所有产品):

PRODUCT_MAKEFILES :=
    $(LOCAL_DIR)/pioneer5_ad/sstar_pioneer5_ad.mk \
    $(LOCAL_DIR)/pioneer5_sdp/sstar_pioneer5_sdp.mk \
    $(LOCAL_DIR)/pioneer5_voip/sstar_pioneer5_voip.mk

COMMON_LUNCH_CHOICES :=
    sstar_pioneer5_ad-userdebug \
    sstar_pioneer5_sdp-userdebug \
    sstar_pioneer5_voip-userdebug

其中 COMMON_LUNCH_CHOICES 所定义的值就是在 Android 设定环境变量时 lunch 指令需要设定的值。也就是说配置完 AndroidProducts.mk 文件便可以在 Android 根目录执行 lunch sstar_pioneer5_ad-userdebug 指令编译 sstar_pioneer5_ad-userdebug 产品了。

source build/envsetup.sh
lunch sstar_pioneer5_ad-userdebug

7、 创建一个包含主板特定配置的 BoardConfig.mk Makefile。可以参考 device/sigmastar/pioneer/pioneer_sdp/BoardConfig.mk。该 Makefile 同样会沿用前面所提及的 device/sigmastar/pioneer/BoardConfig-common.mk

BoardConfig.mkBoardConfig-common.mk Makefile 中主要需要配置以下几点内容:

  1. 指定主板的 CPU 架构;

    TARGET_ARCH := arm64
    TARGET_ARCH_VARIANT := armv8-2a
    TARGET_CPU_ABI := arm64-v8a
    TARGET_CPU_ABI2 :=
    TARGET_CPU_VARIANT := generic
    TARGET_CPU_VARIANT_RUNTIME := cortex-a55
    
  2. 指定板级的重要变量及相关配置

    TARGET_BOARD_PLATFORM := sstar // 平台名字
    
    # GKI-related variables.
    BOARD_USES_GENERIC_KERNEL_IMAGE := true
    BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
    BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true
    
    BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive // 添加 kernel cmdline
    
    BOARD_KERNEL_BASE     := 0x20000000 // kernel 的基地址
    BOARD_KERNEL_OFFSET   := 0x200000 // kernel 的偏移地址
    BOARD_RAMDISK_OFFSET  := 0x5000000 // ramdisk 的偏移地址
    BOARD_DTB_OFFSET      := 0x4000000 // dtb 的偏移地址
    // 使用 mkbootimg 工具生成 boot.img 的输入参数
    BOARD_MKBOOTIMG_ARGS  := --kernel_offset $(BOARD_KERNEL_OFFSET) --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --dtb_offset $(BOARD_DTB_OFFSET)
    
    TARGET_RECOVERY_UI_LIB := librecovery_ui_sstar // recovery UI 库
    TARGET_RECOVERY_PIXEL_FORMAT := "BGRA_8888" // recovery 使用的图形格式
    
    BOARD_INCLUDE_DTB_IN_BOOTIMG := true
    BOARD_PREBUILT_DTBOIMAGE := device/sigmastar/pioneer5/kernel/dtbo.img // 预置的 dtb 文件
    ...
    
  3. 指定 selinux 政策文件路径

    # Vendor SEPolicy
    BOARD_VENDOR_SEPOLICY_DIRS := device/sigmastar/pioneer5/sepolicy/vendor
    
  4. 指定需要开机自动加载的内核模块

    # Kernel modules
    TARGET_KERNEL_DIR := device/sigmastar/pioneer5/kernel
    BOARD_VENDOR_RAMDISK_KERNEL_MODULES :=
          $(TARGET_KERNEL_DIR)/kdrv_emmc.ko  \
          ...
    BOARD_RECOVERY_KERNEL_MODULES :=
          $(TARGET_KERNEL_DIR)/kdrv_emmc.ko
          $(TARGET_KERNEL_DIR)/sstar_iic.ko \
          ...
    

当然除了以上几点还有其他配置根据各自主板需求进行配置。

编写和创建 BoardConfig.mk 文件时同样可以参考或者沿用 Android 源码中给出了一些参考 makefile,这些配置文件被集成在 build/make/target/board 目录下:

emulator_arm/
emulator_x86/
emulator_x86_64/
emulator_x86_64_arm64/
generic/
generic_64bitonly_x86_64/
generic_arm64/
generic_x86/
generic_x86_64/
generic_x86_64_arm64/
generic_x86_arm/
gsi_arm64/
mainline_arm64/
mainline_sdk/
mainline_x86/
mainline_x86_64/
mainline_x86_arm/
module_arm/
module_arm64/
module_x86/
module_x86_64/
Android.mk
BoardConfigEmuCommon.mk // 模拟器公共配置参考
BoardConfigGkiCommon.mk // GKI 公共配置参考
BoardConfigGsiCommon.mk // GSI 公共配置参考
BoardConfigMainlineCommon.mk // Android 主线公共配置参考
BoardConfigModuleCommon.mk // 模块公共配置参考
BoardConfigPixelCommon.mk // Google piexl 公共配置参考

目录下有很多个文件夹,每个文件夹下面都有一个 BoardConfig.mk 并给出所代码的设备参考配置,一般而言都会沿用该目录某个公共的配置。当我们需要编写 BoardConfig.mk makefile 时就可以根据实际需求沿用公共的配置文件以快速达到配置某项功能的目的(例如配置 GKI 功能就沿用 BoardConfigGkiCommon.mk)。

注意: 在拿到 sigmastar 的 Android 代码时,只需要找到主板(例如 pioneer)所对应的目录 device/sigmastar/pioneer 并完成以上 5、6、7 步骤即可。

4.2. 设置产品定义变量

产品特定变量在产品的 Makefile 中进行定义。下表显示了在产品定义文件中维护的部分变量。

变量 说明 示例
PRODUCT_AAPT_CONFIG 创建软件包时使用的 aapt 配置。
PRODUCT_BRAND 对软件进行自定义所针对的品牌,例如运营商。
PRODUCT_CHARACTERISTICS 用于允许向软件包中添加变体特定资源的 aapt 特性。 tablet、nosdcard
PRODUCT_COPY_FILES(常用) 字词列表,如 source_path:destination_path。在构建相应产品时,应将源路径下的文件复制到目标路径。config/makefile 中定义了针对复制步骤的规则。
PRODUCT_DEVICE(必选) 主板代号/名称。构建系统会使用它来查找 BoardConfig.mk。 BoardConfig.mk 必须位于*/<PRODUCT_DEVICE>/目录下 pioneer5_sdp
PRODUCT_LOCALES(必选) 以空格分隔的列表,用于列出由双字母语言代码和双字母国家/地区代码组成的代码对,以便说明针对用户的一些设置,例如界面语言和时间、日期以及货币格式。PRODUCT_LOCALES 中列出的第一个语言区域会用作产品的默认语言区域。 en_GB、de_DE、es_ES、fr_CA
PRODUCT_MANUFACTURER(必选) 制造商的名称。 SigmaStar
PRODUCT_MODEL(必选) 最终产品的最终用户可见名称。 AOSP sdp on pioneer5
PRODUCT_NAME(必选) 总体产品的最终用户可见名称,将显示在设置 > 关于屏幕中。 sstar_pioneer5_sdp
PRODUCT_OTA_PUBLIC_KEYS 产品的无线下载 (OTA) 公钥列表。
PRODUCT_PACKAGES(常用) 将要安装的 APK 和模块列表。
PRODUCT_PACKAGE_OVERLAYS(常用) 指明是使用默认资源还是添加任何产品特定叠加层。
PRODUCT_SYSTEM_PROPERTIES(常用) 系统分区的系统属性分配(采用 "key=value" 格式)列表。其他分区的系统属性可通过 PRODUCT_<PARTITION>_PROPERTIES 设置,如供应商分区的 PRODUCT_VENDOR_PROPERTIES。支持的分区名称:SYSTEM、VENDOR、ODM、SYSTEM_EXT 和 PRODUCT。