FOTA相关知识总结

Android OTA升级,顾名思义是指over-the-air升级方式。通过在线下载安装包的形式,对整个系统进行升级。

在说FOTA之前,先看看Android的系统分区。具体参考官方网页

Android分区

  • boot 包括Linux系统内核和最小的系统文件。它负责安装系统和其他分区。
  • recovery 用于系统升级的分区,里面有一个单独的Linux系统。它通过读取一个新的软件包,来逐步更新其他分区,最终达到系统更新的目的。
  • system 包含在Android开源项目(AOSP)上提供源代码的系统应用程序和库。 在正常操作中,此分区挂载为只读; 其内容仅在OTA更新期间更改。
  • userdata 存储由用户安装的应用程序保存的数据等。OTA更新过程通常不会触及该分区
  • cache 应用使用的临时储存区域,访问该区域需要特殊权限。同时要用于储存下载的FOTA包。其他程序使用这个空间,期望文件可以随时消失。某些OTA软件包安装可能会导致此分区被完全擦除。

FOTA升级流程

  • 手机会定期检测是否有更新(也可手动检测),并通知用户有新版本可用。
  • 将安装包下载到cache分区,若cache分区不够,下载到data分区(这时候要注意是否有写入和删除权限),并根据system/etc/security/otacerts.zip的证书验证其加密签名。系统提示用户安装更新。
  • 系统重启到recovery模式,运行的是recovery分区中的系统内核。而不是boot中的系统。
  • init进程通过执行init.rc 脚本:service recovery /sbin/recovery 启动recovery程序
  • recovery首先校验下载的安装包是否与res/keys(ramdisk)中的公匙相匹配。
  • recovery根据脚本解析安装包,然后将修改分别更新到对应的分区中,在system 分区中包含了用于更新recovery分区的内容。
  • 系统正常启动:启动更新后的boot,system分区。启动时检测是否对recovery分区有更新,若有差异,则更新到recovery分区(这里也是为什么修改了recovery的代码后,需要更新完,且在下个更新中才能得到验证)
  • 设备通知服务器更新完成。

OTA包制作

build/tools/releasetools 中,ota_from_target_files脚本制作OTA安装包。它既可以制作全包,也可制作差分包。所谓完整版安装包,就是包中已经包含了当前要更新到的系统所有文件,只要设备下载了安装包,并启动recovery模式,该包就可以完成更新,而不管系统当前的状态是什么样的。
要制作OTA包,需要先编译target包。编译target包的指令如下:

. build/envsetup.sh && lunch full_E266L-user   //编译E266L
make -j4 otapackage   //编译target包,并将包放入新建的dist_output中

这其中,make otapackage 分为两个部分,一个是编译target包,一部分是编译FULL_OTA包。编译target包,是在build/core/Makefile中执行的。具体代码如下:

# -----------------------------------------------------------------
# A zip of the directories that map to the target filesystem.
# This zip can be used to create an OTA package or filesystem image
# as a post-build step.
#
name := $(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
  name := $(name)_debug
endif
name := $(name)-target_files-$(FILE_NAME_TAG)

intermediates := $(call intermediates-dir-for,PACKAGING,target_files)
BUILT_TARGET_FILES_PACKAGE := $(intermediates)/$(name).zip
$(BUILT_TARGET_FILES_PACKAGE): intermediates := $(intermediates)
$(BUILT_TARGET_FILES_PACKAGE): \
        zip_root := $(intermediates)/$(name)

# $(1): Directory to copy
# $(2): Location to copy it to
# The "ls -A" is to prevent "acp s/* d" from failing if s is empty.
define package_files-copy-root
  if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \
    mkdir -p $(2) && \
    $(ACP) -rd $(strip $(1))/* $(2); \
  fi
endef

built_ota_tools :=

# We can't build static executables when SANITIZE_TARGET=address
ifeq ($(strip $(SANITIZE_TARGET)),)
built_ota_tools += \
    $(call intermediates-dir-for,EXECUTABLES,updater,,,$(TARGET_PREFER_32_BIT))/updater
endif

$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)

$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_FSTAB_VERSION := $(RECOVERY_FSTAB_VERSION)

ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),)
# default to common dir for device vendor
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_DEVICE_DIR)/../common
else
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)
endif

# Build OTA tools if not using the AB Updater.
ifneq ($(AB_OTA_UPDATER),true)
$(BUILT_TARGET_FILES_PACKAGE): $(built_ota_tools)
endif

# If we are using recovery as boot, output recovery files to BOOT/.
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_OUT := BOOT
else
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_OUT := RECOVERY
endif

# Depending on the various images guarantees that the underlying
# directories are up-to-date.
$(BUILT_TARGET_FILES_PACKAGE): \
        $(INSTALLED_BOOTIMAGE_TARGET) \
        $(INSTALLED_RADIOIMAGE_TARGET) \
        $(INSTALLED_RECOVERYIMAGE_TARGET) \
        $(INSTALLED_SYSTEMIMAGE) \
        $(INSTALLED_USERDATAIMAGE_TARGET) \
        $(INSTALLED_CACHEIMAGE_TARGET) \
        $(INSTALLED_VENDORIMAGE_TARGET) \
        $(INSTALLED_ANDROID_INFO_TXT_TARGET) \
        $(SELINUX_FC) \
        $(APKCERTS_FILE) \
        $(HOST_OUT_EXECUTABLES)/fs_config \
        | $(ACP)
ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
$(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_CACHEIMAGE_TARGET)
endif
    @echo "Package target files: $@"
    $(hide) rm -rf $@ $(zip_root)
    $(hide) mkdir -p $(dir $@) $(zip_root)
ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
    @# Components of the recovery image
    $(hide) mkdir -p $(zip_root)/$(PRIVATE_RECOVERY_OUT)
    $(hide) $(call package_files-copy-root, \
        $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/$(PRIVATE_RECOVERY_OUT)/RAMDISK)
ifdef INSTALLED_KERNEL_TARGET
    $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel
    $(hide) $(ACP) $(recovery_ramdisk) $(zip_root)/RECOVERY/ramdisk
ifeq ($(MTK_HEADER_SUPPORT),yes)
    $(hide) $(ACP) $(recovery_ramdisk_bthdr) $(zip_root)/RECOVERY/ramdisk-bthdr
endif
endif
ifdef INSTALLED_2NDBOOTLOADER_TARGET
    $(hide) $(ACP) \
        $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
endif
ifdef BOARD_KERNEL_CMDLINE
    $(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
endif
ifdef BOARD_KERNEL_BASE
    $(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/base
endif
ifdef BOARD_KERNEL_PAGESIZE
    $(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/pagesize
endif
endif # INSTALLED_RECOVERYIMAGE_TARGET defined or BOARD_USES_RECOVERY_AS_BOOT is true

ifdef BOARD_RAMDISK_OFFSET
    $(hide) echo "$(BOARD_RAMDISK_OFFSET)" > $(zip_root)/RECOVERY/ramdisk_offset
endif
ifdef BOARD_KERNEL_OFFSET
    $(hide) echo "$(BOARD_KERNEL_OFFSET)" > $(zip_root)/RECOVERY/kernel_offset
endif
ifdef BOARD_TAGS_OFFSET
    $(hide) echo "$(BOARD_TAGS_OFFSET)" > $(zip_root)/RECOVERY/tags_offset
endif
ifdef CUSTOM_BUILD_VERNO
    $(hide) echo -n $(CUSTOM_BUILD_VERNO_HDR) > $(zip_root)/RECOVERY/board
endif
    @# Components of the boot image
    $(hide) mkdir -p $(zip_root)/BOOT
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
    $(hide) mkdir -p $(zip_root)/ROOT
    $(hide) $(call package_files-copy-root, \
        $(TARGET_ROOT_OUT),$(zip_root)/ROOT)
else
    $(hide) $(call package_files-copy-root, \
        $(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)
endif
    @# If we are using recovery as boot, this is already done when processing recovery.
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
ifdef INSTALLED_KERNEL_TARGET
    $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel
    $(hide) $(ACP) $(INSTALLED_RAMDISK_TARGET) $(zip_root)/BOOT/ramdisk
endif
ifdef INSTALLED_2NDBOOTLOADER_TARGET
    $(hide) $(ACP) \
        $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
endif
ifdef BOARD_KERNEL_CMDLINE
    $(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
endif
ifdef BOARD_KERNEL_BASE
    $(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
endif
ifdef BOARD_RAMDISK_OFFSET
    $(hide) echo "$(BOARD_RAMDISK_OFFSET)" > $(zip_root)/BOOT/ramdisk_offset
endif
ifdef BOARD_KERNEL_OFFSET
    $(hide) echo "$(BOARD_KERNEL_OFFSET)" > $(zip_root)/BOOT/kernel_offset
endif
ifdef BOARD_TAGS_OFFSET
    $(hide) echo "$(BOARD_TAGS_OFFSET)" > $(zip_root)/BOOT/tags_offset
endif
ifdef BOARD_KERNEL_PAGESIZE
    $(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
endif
ifdef CUSTOM_BUILD_VERNO
    $(hide) echo -n $(CUSTOM_BUILD_VERNO_HDR) > $(zip_root)/BOOT/board
endif
endif # BOARD_USES_RECOVERY_AS_BOOT
    $(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
                mkdir -p $(zip_root)/RADIO; \
                $(ACP) $(t) $(zip_root)/RADIO/$(notdir $(t));)
    @# Contents of the system image
    $(hide) $(call package_files-copy-root, \
        $(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)
    @# Contents of the data image
    $(hide) $(call package_files-copy-root, \
        $(TARGET_OUT_DATA),$(zip_root)/DATA)
ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
    @# Contents of the vendor image
    $(hide) $(call package_files-copy-root, \
        $(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
endif
#wschen 2012-11-07
    $(if $(BOARD_CUSTOMIMAGE_PARTITION_SIZE), \
    $(hide) $(call package_files-copy-root, \
        $(TARGET_CUSTOM_OUT),$(zip_root)/CUSTOM))
    @# Extra contents of the OTA package
    $(hide) mkdir -p $(zip_root)/OTA
    $(hide) $(ACP) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
ifneq ($(AB_OTA_UPDATER),true)
ifneq ($(built_ota_tools),)
    $(hide) mkdir -p $(zip_root)/OTA/bin
    $(hide) $(ACP) $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/
endif
endif
    @# Files that do not end up in any images, but are necessary to
    @# build them.
    $(hide) mkdir -p $(zip_root)/META
    $(hide) $(ACP) $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
    $(hide) if test -e $(tool_extensions)/releasetools.py; then $(ACP) $(tool_extensions)/releasetools.py $(zip_root)/META/; fi
    $(hide) echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
    $(hide) $(ACP) $(SELINUX_FC) $(zip_root)/META/file_contexts.bin
    $(hide) echo "recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/misc_info.txt
    $(hide) echo "fstab_version=$(PRIVATE_RECOVERY_FSTAB_VERSION)" >> $(zip_root)/META/misc_info.txt
ifdef BOARD_FLASH_BLOCK_SIZE
    $(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
    $(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),)
    $(hide) echo "recovery_as_boot=$(BOARD_USES_RECOVERY_AS_BOOT)" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
    $(hide) echo "no_recovery=true" >> $(zip_root)/META/misc_info.txt
endif
ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
    $(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifdef BOARD_HAS_EXT4_RESERVED_BLOCKS
    $(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(zip_root)/META/misc_info.txt
endif
ifdef TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
    @# TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS can be empty to indicate that nothing but defaults should be used.
    $(hide) echo "recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
else
    $(hide) echo "recovery_mount_options=$(DEFAULT_TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
endif
    $(hide) echo "tool_extensions=$(tool_extensions)" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "default_system_dev_certificate=$(DEFAULT_SYSTEM_DEV_CERTIFICATE)" >> $(zip_root)/META/misc_info.txt
ifdef PRODUCT_EXTRA_RECOVERY_KEYS
    $(hide) echo "extra_recovery_keys=$(PRODUCT_EXTRA_RECOVERY_KEYS)" >> $(zip_root)/META/misc_info.txt
endif
    $(hide) echo 'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)' >> $(zip_root)/META/misc_info.txt
    $(hide) echo 'mkbootimg_version_args=$(INTERNAL_MKBOOTIMG_VERSION_ARGS)' >> $(zip_root)/META/misc_info.txt
    $(hide) echo "use_set_metadata=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "multistage_support=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "update_rename_support=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "blockimgdiff_versions=1,2,3,4" >> $(zip_root)/META/misc_info.txt
ifeq ($(MTK_HEADER_SUPPORT),yes)
    $(hide) echo "mtk_header_support=1" >> $(zip_root)/META/misc_info.txt
endif
ifneq ($(OEM_THUMBPRINT_PROPERTIES),)
    # OTA scripts are only interested in fingerprint related properties
    $(hide) echo "oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)" >> $(zip_root)/META/misc_info.txt
endif
ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH),)
    $(hide) $(ACP) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH) \
      $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH))
endif
ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),)
    $(hide) $(ACP) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH) \
      $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH))
endif
ifneq ($(strip $(SANITIZE_TARGET)),)
    # We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
    $(hide) echo "userdata_img_with_data=true" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
    $(hide) echo "full_recovery_image=true" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(TARGET_USERIMAGES_USE_UBIFS),true)
    $(call generate-ubifs-prop-dictionary, $(zip_root)/META/misc_info.txt)
endif
    $(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)

    @# sign image used to get boot and recovery sig files
    $(hide) $(SHELL) vendor/mediatek/proprietary/scripts/sign-image/sign_image.sh
    @#prepare image and update list for OTA upgrade used
    #[email protected] 20170411 add for preloader upgrade start
    #$(hide) ./device/mediatek/build/releasetools/mt_ota_preprocess.py $(zip_root) $(PRODUCT_OUT) $(PRODUCT_OUT)/ota_update_list.txt
    $(hide) MTK_LOADER_UPDATE=yes MTK_PRELOADER_OTA_BACKUP=no ./device/mediatek/build/releasetools/mt_ota_preprocess.py $(zip_root) $(PRODUCT_OUT) $(PRODUCT_OUT)/ota_update_list.txt
    #[email protected] 20170411 add for preloader upgrade end
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
    $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
        ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
endif
ifeq ($(AB_OTA_UPDATER),true)
    @# When using the A/B updater, include the updater config files in the zip.
    $(hide) $(ACP) $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
    $(hide) for part in $(AB_OTA_PARTITIONS); do \
      echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
    done
    $(hide) for conf in $(AB_OTA_POSTINSTALL_CONFIG); do \
      echo "$${conf}" >> $(zip_root)/META/postinstall_config.txt; \
    done
    @# Include the build type in META/misc_info.txt so the server can easily differentiate production builds.
    $(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "ab_update=true" >> $(zip_root)/META/misc_info.txt
ifdef OSRELEASED_DIRECTORY
    $(hide) $(ACP) $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)/product_id $(zip_root)/META/product_id.txt
    $(hide) $(ACP) $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)/product_version $(zip_root)/META/product_version.txt
endif
endif
ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
    @# If breakpad symbols have been generated, add them to the zip.
    $(hide) $(ACP) -r $(TARGET_OUT_BREAKPAD) $(zip_root)/BREAKPAD
endif
    @# Zip everything up, preserving symlinks and placing META/ files first to
    @# help early validation of the .zip file while uploading it.
    $(hide) (cd $(zip_root) && \
            zip -qryX ../$(notdir $@) ./META && \
            zip -qryXu ../$(notdir $@) .)
    @# Run fs_config on all the system, vendor, boot ramdisk,
    @# and recovery ramdisk files in the zip, and save the output
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="VENDOR/" } /^VENDOR\// {print "vendor/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/vendor_filesystem_config.txt
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="ROOT/" } /^ROOT\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/root_filesystem_config.txt
endif
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt
endif
# 2012-11-07
    $(if $(BOARD_CUSTOMIMAGE_PARTITION_SIZE), \
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="CUSTOM/" } /^CUSTOM\// {print "custom/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/custom_filesystem_config.txt)
    $(hide) (cd $(zip_root) && zip -qX ../$(notdir $@) META/*filesystem_config.txt)
    $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
        ./build/tools/releasetools/add_img_to_target_files -a -v -p $(HOST_OUT) $@
    $(hide) ./build/tools/releasetools/replace_img_from_target_files.py $@ $(PRODUCT_OUT)

.PHONY: target-files-package
target-files-package: $(BUILT_TARGET_FILES_PACKAGE)

ifneq ($(filter $(MAKECMDGOALS),target-files-package),)
$(call dist-for-goals, target-files-package, $(BUILT_TARGET_FILES_PACKAGE))
endif

上面编译target包的过程,可以分为几个步骤:

  • 创建RECOVERY目录,并填充该目录的内容,包括kernel的镜像和recovery根文件系统的镜像。此目录最终用于生成recovery.img。
  • 创建并填充BOOT目录。包含kernel和cmdline以及pagesize大小等,该目录最终用来生成boot.img。
  • 向SYSTEM目录填充system image。
  • 向DATA填充data image。
  • 用于生成OTA package包所需要的额外的内容。主要包括一些bin命令。
  • 创建META目录并向该目录下添加一些文本文件,如apkcerts.txt(描述apk文件用到的认证证书),misc_info.txt(描述Flash内存的块大小以及boot、recovery、system、userdata等分区的大小信息)。
  • 使用保留连接选项压缩我们在上面获得的root_zip目录。
  • 使用fs_config(build/tools/fs_config)配置上面的zip包内所有的系统文件(system/下各目录、文件)的权限属主等信息。fs_config包含了一个头文件#include“private/android_filesystem_config.h”。在这个头文件中以硬编码的方式设定了system目录下各文件的权限、属主。执行完配置后会将配置后的信息以文本方式输出 到META/filesystem_config.txt中。并再一次zip压缩成我们最终需要的原始包。

编译OTA包,则需要用到ota_from_target_files脚本。其中编译完整OTA包(SD卡包),最终是用到WriteFullOTAPackage(input_zip, output_zip)方法。编译增量包,需要用到WriteIncrementalOTAPackage方法。两个方法另起文档具体分析。

在制作OTA包时,需要注意是否支持基于block的系统。所谓基于block,是指Android 5.0及更高版本使用块OTA更新来确保每个设备使用完全相同的分区。代替比较单个文件和计算二进制补丁,块OTA将整个分区作为一个文件处理,并计算一个二进制补丁,以确保生成的分区完全包含预期的位。 这允许设备系统映像通过fastboot或OTA实现相同的状态。

你可能感兴趣的:(FOTA相关知识总结)