• Android OTA升级(1):编译升级全包



    http://blog.csdn.net/thl789/article/details/8743743


    田海立@CSDN

    2013-3-23

         Android原生系统中就已经支持OTA升级。所谓OTA升级就是通过空中接口获取升级包,然后更新系统固件。一般地,升级包无论如何获取,哪怕是直接TCard本地升级,也被称为OTA升级。

         OTA升级首要是生成OTA升级包,升级包又分为升级全包和升级差分包(或要增量包)。升级全包是编译当前系统得到的软件包,这个包很大,有上百兆,但是不依赖与当前手机里的软件版本;升级差分包是对手机两个软件版本做差分,在第一个版本上打patch,得到第二个升级包,所以差分包只能对第一个版本的机器进行升级。

        本文主要讲述升级全包的生成过程。

    编译升级全包,用下面指令:

    #make otapackage

    最终生成INTERNAL_OTA_PACKAGE_TARGET,也就是$(PRODUCT_OUT)/$(name).zip。

    一、升级全包($(PRODUCT_OUT)/$(name).zip)的生成


    INTERNAL_OTA_PACKAGE_TARGET依赖于BUILT_TARGET_FILES_PACKAGE

    生成规则【在build/core/Makefile中】:

    1. $(INTERNAL_OTA_PACKAGE_TARGET):$(BUILT_TARGET_FILES_PACKAGE) $(OTATOOLS)  
    2.                 @echo"Package OTA: $@"  
    3.                 $(hide)./build/tools/releasetools/ota_from_target_files -v   
    4.                    -p $(HOST_OUT)   
    5.           -k $(KEY_CERT_PAIR)   
    6.           $(BUILT_TARGET_FILES_PACKAGE) $@  

    ota_from_target_files是Python脚本,需要中间文件$(BUILT_TARGET_FILES_PACKAGE)。所以,在分析完中间文件的生成之后再看最终升级全包的生成过程

    二、中间文件包($(TARGET_PRODUCT)-target_files-$(FILE_NAME_TAG).zip)的生成


    BUILT_TARGET_FILES_PACKAGE是$(intermediates)/$( TARGET_PRODUCT)-target_files-$(FILE_NAME_TAG).zip

    形如:out/target/product/<product>/obj/PACKAGING/target_files_intermediates/<product>-target_files-<eng>.haili.tian

    生成规则【在build/core/Makefile中】:

    1. $(BUILT_TARGET_FILES_PACKAGE):  
    2.               $(INSTALLED_BOOTIMAGE_TARGET)   
    3.               $(INSTALLED_RADIOIMAGE_TARGET)   
    4.               $(INSTALLED_RECOVERYIMAGE_TARGET)  
    5.               $(INSTALLED_SYSTEMIMAGE)   
    6.               $(INSTALLED_USERDATAIMAGE_TARGET)  
    7.               $(INSTALLED_ANDROID_INFO_TXT_TARGET)  
    8.               $(built_ota_tools)   
    9.               $(APKCERTS_FILE)   
    10.               $(HOST_OUT_EXECUTABLES)/fs_config  
    11.               | $(ACP)  
    12.        @echo "Package target files:$@"  
    13.        $(hide) rm -rf $@ $(zip_root)  
    14.        $(hide) mkdir -p $(dir $@) $(zip_root)  
    15.        @# Components of the recovery image  
    16.        $(hide) mkdir -p $(zip_root)/RECOVERY  
    17.        $(hide) $(call package_files-copy-root,   
    18.               $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/RECOVERY/RAMDISK)  
    19. ifdef INSTALLED_KERNEL_TARGET  
    20.        $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET)$(zip_root)/RECOVERY/kernel  
    21. endif  
    22. ifdef INSTALLED_2NDBOOTLOADER_TARGET  
    23.        $(hide) $(ACP)   
    24.               $(INSTALLED_2NDBOOTLOADER_TARGET)$(zip_root)/RECOVERY/second  
    25. endif  
    26. ifdef BOARD_KERNEL_CMDLINE  
    27.        $(hide) echo"$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/RECOVERY/cmdline  
    28. endif  
    29. ifdef BOARD_KERNEL_BASE  
    30.        $(hide) echo"$(BOARD_KERNEL_BASE)" > $(zip_root)/RECOVERY/base  
    31. endif  
    32. ifdef BOARD_KERNEL_PAGESIZE  
    33.        $(hide) echo "$(BOARD_KERNEL_PAGESIZE)"> $(zip_root)/RECOVERY/pagesize  
    34. endif  
    35.        @# Components of the boot image  
    36.        $(hide) mkdir -p $(zip_root)/BOOT  
    37.        $(hide) $(call package_files-copy-root,   
    38.               $(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)  
    39. ifdef INSTALLED_KERNEL_TARGET  
    40.        $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET)$(zip_root)/BOOT/kernel  
    41. endif  
    42. ifdef INSTALLED_2NDBOOTLOADER_TARGET  
    43.        $(hide) $(ACP)   
    44.               $(INSTALLED_2NDBOOTLOADER_TARGET)$(zip_root)/BOOT/second  
    45. endif  
    46. ifdef BOARD_KERNEL_CMDLINE  
    47.        $(hide) echo"$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline  
    48. endif  
    49. ifdef BOARD_KERNEL_BASE  
    50.        $(hide) echo"$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base  
    51. endif  
    52. ifdef BOARD_KERNEL_PAGESIZE  
    53.        $(hide) echo"$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize  
    54. endif  
    55.        $(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),  
    56.                    mkdir -p $(zip_root)/RADIO;   
    57.                    $(ACP) $(t)$(zip_root)/RADIO/$(notdir $(t));)  
    58.        @# Contents of the system image  
    59.        $(hide) $(call package_files-copy-root,   
    60.               $(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)  
    61.        @# Contents of the data image  
    62.        $(hide) $(call package_files-copy-root,   
    63.               $(TARGET_OUT_DATA),$(zip_root)/DATA)  
    64.        @# Extra contents of the OTA package  
    65.        $(hide) mkdir -p $(zip_root)/OTA/bin  
    66.        $(hide) $(ACP)$(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/  
    67.        $(hide) $(ACP) $(PRIVATE_OTA_TOOLS)$(zip_root)/OTA/bin/  
    68.        @# Files that do not end up in anyimages, but are necessary to  
    69.        @# build them.  
    70.        $(hide) mkdir -p $(zip_root)/META  
    71.        $(hide) $(ACP) $(APKCERTS_FILE)$(zip_root)/META/apkcerts.txt  
    72.        $(hide)       echo"$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt  
    73.        $(hide) echo"recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)" >$(zip_root)/META/misc_info.txt  
    74. ifdef BOARD_FLASH_BLOCK_SIZE  
    75.        $(hide) echo"blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $(zip_root)/META/misc_info.txt  
    76. endif  
    77. ifdef BOARD_BOOTIMAGE_PARTITION_SIZE  
    78.        $(hide) echo"boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >>$(zip_root)/META/misc_info.txt  
    79. endif  
    80. ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE  
    81.        $(hide) echo"recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >>$(zip_root)/META/misc_info.txt  
    82. endif  
    83. ifdef BOARD_SYSTEMIMAGE_PARTITION_SIZE  
    84.        $(hide) echo"system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >>$(zip_root)/META/misc_info.txt  
    85. endif  
    86. ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE  
    87.        $(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)">> $(zip_root)/META/misc_info.txt  
    88. endif  
    89.        $(hide) echo"tool_extensions=$(tool_extensions)" >>$(zip_root)/META/misc_info.txt  
    90. ifdef mkyaffs2_extra_flags  
    91.        $(hide) echo"mkyaffs2_extra_flags=$(mkyaffs2_extra_flags)" >>$(zip_root)/META/misc_info.txt  
    92. endif  
    93.        @# Zip everything up, preserving symlinks  
    94.        $(hide) (cd $(zip_root) && zip-qry ../$(notdir $@) .)  
    95.        @# Run fs_config on all the system filesin the zip, and save the output  
    96.        $(hide) zipinfo -1 $@ | awk -F/ 'BEGIN {OFS="/" } /^SYSTEM// {$$1 = "system"; print}' |$(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/filesystem_config.txt  
    97.        $(hide) (cd $(zip_root) && zip -q../$(notdir $@) META/filesystem_config.txt)  

    其中,变量定义:

    -         TARGET_RECOVERY_ROOT_OUT也就是$(TARGET_RECOVERY_OUT)/root;TARGET_RECOVERY_OUT是$(PRODUCT_OUT)/recovery;PRODUCT_OUT是out/target/product/<product>。所以,TARGET_RECOVERY_ROOT_OUT也就是out/target/product/<product>/recovery/root;

    -         zip_root是$(intermediates)/$( TARGET_PRODUCT)-target_files-$(FILE_NAME_TAG)路径,也就是out/target/product/<product>/obj/PACKAGING/target_files_intermediates/<product>-target_files-<eng>.haili.tian;

    -         TARGET_ROOT_OUT是$(PRODUCT_OUT)/root,也就是out/target/product/<product>/root;

    -         INSTALLED_RADIOIMAGE_TARGET;

    -         SYSTEMIMAGE_SOURCE_DIR是$(TARGET_OUT),也就是out/target/product/<product>/system/;

    -         TARGET_OUT_DATA是$(PRODUCT_OUT)/data,也就是out/target/product/<product>/data;

    -         INSTALLED_ANDROID_INFO_TXT_TARGET是$(PRODUCT_OUT)/android-info.txt,也就是out/target/product/<product>/android-info.txt;

    -         PRIVATE_OTA_TOOLS是$(built_ota_tools),也就是包含了:

        out/target/product/<product>/obj/EXECUTABLES/applypatch_intermediates/applypatch

        out/target/product/<product>/obj/EXECUTABLES/applypatch_static_intermediates/applypatch_static

        out/target/product/<product>/obj/EXECUTABLES/check_prereq_intermediates/check_prereq

        out/target/product/<product>/obj/EXECUTABLES/updater_intermediates/updater

    -         APKCERTS_FILE是out/target/product/<product>/obj/PACKAGING/apkcerts_intermediates/<product>-apkcerts-<eng>.haili.tian.txt

    -         PRODUCT_OTA_PUBLIC_KEYS目前为空;

    -         PRIVATE_RECOVERY_API_VERSION也就是RECOVERY_API_VERSION,RecoveryAPI的版本号;

    -         tool_extensions如果定义了TARGET_RELEASETOOLS_EXTENSIONS,tool_extensions也就是TARGET_RELEASETOOLS_EXTENSIONS;

    -         DEFAULT_SYSTEM_DEV_CERTIFICATE目前为空;

    -         HOST_OUT_EXECUTABLES是$(HOST_OUT)/bin,也就是out/host/linux-x86/bin;

    脚本的执行

    1.      #清理以前残存的目录和文件,并创建$(zip_root)目录(也就是out/target/product/<product>/obj/PACKAGING/target_files_intermediates/<product>-target_files-<eng>.haili.tian);

    2.      创建$(zip_root)/RECOVERY目录,把$(TARGET_RECOVERY_ROOT_OUT)(也就是out/target/product/<product>/recovery/root)下的所有文件和目录都拷贝到$(zip_root)/RECOVERY/RAMDISK/下;

    3.      创建$(zip_root)/BOOT目录,然后把$(TARGET_ROOT_OUT)(也就是out/target/product/<product>/root)下的所有文件和目录都拷贝到$(zip_root)/BOOT/RAMDISK/下;

    4.      创建$(zip_root)/RADIO目录,然后把$(INSTALLED_RADIOIMAGE_TARGET)下的所有文件和目录都拷贝到$(zip_root)/ RADIO/下;

    5.      把$(SYSTEMIMAGE_SOURCE_DIR)【也就是out/target/product/<product>/system/】下的所有文件和目录都拷贝到$(zip_root)/SYSTEM/下;

    6.      把$(TARGET_OUT_DATA)【也就是out/target/product/<product>/data】下的所有文件和目录都拷贝到$(zip_root)/DATA/下;

    7.      创建$(zip_root)/OTA/bin目录,然后把INSTALLED_ANDROID_INFO_TXT_TARGET【也就是out/target/product/<product>/android-info.txt】放到$(zip_root)/OTA/下;

    8.      把PRIVATE_OTA_TOOLS【也就是applypatchapplypatch_staticcheck_prerequpdater】放到$(zip_root)/OTA/bin下。

    9.      创建$(zip_root)/META目录,搜集META信息并保存到文件里:

        把APKCERTS_FILE【也就是out/target/product/<product>/obj/PACKAGING/apkcerts_intermediates/<product>-apkcerts-<eng>.haili.tian.txt】放到$(zip_root)/META/apkcerts.txt

        把$(PRODUCT_OTA_PUBLIC_KEYS)追加到$(zip_root)/META/otakeys.txt;【】

        把recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)这行追加到$(zip_root)/META/misc_info.txt

        把tool_extensions=$(tool_extensions)这行追加到$(zip_root)/META/misc_info.txt

        把default_system_dev_certificate=$(DEFAULT_SYSTEM_DEV_CERTIFICATE)这行追加到$(zip_root)/META/misc_info.txt

    10.  拷贝Image文件

        把$(PRODUCT_OUT)/ramdisk.img放到$(zip_root)/下;

        把$(PRODUCT_OUT)/ramdisk-recovery.img放到(zip_root)/

        把$(PRODUCT_OUT)/../../../../boot/out/u-boot.bin放到$(zip_root)/

        把$(PRODUCT_OUT)/../../../../kernel/out/uImage放到(zip_root)/

    11.  进入$(zip_root),把$(zip_root)下所有的内容打进zip包<product>-target_files-<eng>.haili.tian.zip

    12.  用$(HOST_OUT_EXECUTABLES)/fs_config获取文件系统信息并保存在文件里

         “SYSTEM/”下的文件系统信息保存在$(zip_root)/META/filesystem_config.txt中;

         “BOOT/RAMDISK/”下的文件系统信息保存在$(zip_root)/META/boot_filesystem_config.txt中;

         “RECOVERY/RAMDISK/”下的文件系统信息保存在$(zip_root)/META/recovery_filesystem_config.txt中;

    13.  把META/*filesystem_config.txt文件打到zip包<product>-target_files-<eng>.haili.tian.zip里。

    三、ota_from_target_file分析


    Ota_from_target_file是python脚本,从main()开始分析。

    3.1 生成总过程 – main()

    Main()里主要做下列工作:

    1.      从参数和环境中解析OPTIONS;

    2.      从中间zip包里的META/misc_info.txt中解析出{<key>=<value>}OPTIONS对,比如recovery_api_version=3;tool_extensions=device/<company>/<product>/recovery;

    3.      从OPTIONS对里找到tool_extensions,赋值给OPTIONS.device_specific;

    4.      input_zip为上文的中间zip包;output_zip为最终生成的临时zip包;

    5.      对于全包升级包,调用WriteFullOTAPackage(input_zip,output_zip);

    6.      签名临时包,生成最终签过名的最终全包升级包。

    上述过程中,我们最关注的是WriteFullOTAPackage(input_zip,output_zip)做的工作。


    3.2 生成全包 – WriteFullOTAPackage()


    WriteFullOTAPackage[file:build/tools/releasetools/ota_from_target_files]的定义如下:

    1. def WriteFullOTAPackage(input_zip, output_zip):  
    2.   # TODO:how to determine this?  We don't knowwhat version it will  
    3.   # beinstalled on top of.  For now, we expectthe API just won't  
    4.   # changevery often.  
    5.   script =edify_generator.EdifyGenerator(3, OPTIONS.info_dict)  
    6.    
    7.   metadata= {"post-build": GetBuildProp("ro.build.fingerprint",input_zip),  
    8.              "pre-device": GetBuildProp("ro.product.device",input_zip),  
    9.               "post-timestamp":GetBuildProp("ro.build.date.utc", input_zip),  
    10.              }  
    11.    
    12.  device_specific = common.DeviceSpecificParams(  
    13.      input_zip=input_zip,  
    14.      input_version=OPTIONS.info_dict["recovery_api_version"],  
    15.      output_zip=output_zip,  
    16.      script=script,  
    17.      input_tmp=OPTIONS.input_tmp,  
    18.      metadata=metadata,  
    19.      info_dict=OPTIONS.info_dict,  
    20.      trusted_boot=OPTIONS.trusted_boot)  
    21.    
    22. #  if not OPTIONS.omit_prereq:  
    23. #    ts =GetBuildProp("ro.build.date.utc", input_zip)  
    24. #   script.AssertOlderBuild(ts)  
    25.    
    26. # AppendAssertions(script, input_zip)  
    27. # device_specific.FullOTA_Assertions()  
    28.    
    29.  script.ShowProgress(0.916)  
    30.    
    31.   if OPTIONS.wipe_user_data:  
    32.    script.FormatPartition("/data")  
    33.    
    34.  script.FormatPartition("/system")  
    35.  script.Mount("/system")  
    36. # script.UnpackPackageDir("recovery", "/system")  
    37.  script.UnpackPackageDir("system""/system")  
    38.    
    39.   symlinks= CopySystemFiles(input_zip, output_zip)  
    40.  script.MakeSymlinks(symlinks)  
    41.    
    42. # boot_img = common.File("boot.img", common.BuildBootableImage(  
    43. #     os.path.join(OPTIONS.input_tmp, "BOOT")))  
    44. # recovery_img = common.File("recovery.img",common.BuildBootableImage(  
    45. #     os.path.join(OPTIONS.input_tmp, "RECOVERY")))  
    46. # MakeRecoveryPatch(output_zip, recovery_img, boot_img)  
    47.  Item.GetMetadata(input_zip)  
    48.  Item.Get("system").SetPermissions(script)  
    49.    
    50. # common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)  
    51. # common.ZipWriteStr(output_zip, "boot.img", boot_img.data)  
    52. # script.ShowProgress(0.2, 0)  
    53.    
    54. # script.ShowProgress(0.2, 10)  
    55. # script.WriteRawImage("/boot", "boot.img")  
    56.    
    57. # script.ShowProgress(0.1, 0)  
    58.  device_specific.FullOTA_InstallEnd()  
    59.    
    60.   if OPTIONS.extra_script is not None:  
    61.    script.AppendExtra(OPTIONS.extra_script)  
    62.    
    63.  script.UnmountAll()  
    64.  script.AddToZip(input_zip, output_zip)  
    65.   WriteMetadata(metadata,output_zip)  


    OTA全包生成的过程

    1.      script用来生成Edify脚本,在edify_generator.py中实现;

    2.      script中增加语句:显示进度;

    3.      script中增加语句:擦除“/system”分区;

    4.      script中增加语句:安装system分区到“/system”;

    5.      script中增加语句:把system中的内容复制到/system下;

    6.      把input_zip包/system中的内容,复制到output_zip包中,不包含其中的link文件;

    7.      对于link文件,script中增加指向链接的语句;

    8.      从input_zip包的META/filesystem_config.txt中获取其中描述的/system下各个文件的权限信息;

    9.      script中增加语句:设置/system下文件的权限和属主信息;

    10.  调用具体device特定的函数FullOTA_InstallEnd。

         main()函数中已经获取OPTIONS.device_specific为/device/<company>/<product>/recovery;这里的device_specific是common.DeviceSpecificParams。

         common实现在common.py中,在判断出OPTIONS.device_specific为目录时,用该目录下的releasetools.py脚本。所以这里执行releasetools.py中的FullOTA_InstallEnd。

    11.  如果特别指定了其他脚本,script中加入;

    12.  通过script.AddToZip()写META-INF

        把前面所有的脚本,写入到output_zip里的META-INF/com/google/android/updater-script这个edify脚本中;

        把input_zip里的OTA/bin/updater写入到output_zip里的META-INF/com/google/android/update-binary

    13.  把metadata的内容写入到output_zip里的META-INF/com/android/metadata

    总结


        本文分析了Android OTA全包的编译生成过程。首先生成中间包,这个包是后续全包生成的基础,也是差分包生成的基础,接着解析了生成最终升级全包的过程。通过分析知道升级包中update-binary和updater-script的来源,对于后续分析OTA升级的过程至关重要。

        差分包的生成在介绍完整个OTA的过程之后,再进一步阐述。


  • 相关阅读:
    第十三周总结
    第十二周作业
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周课程总结&实验报告(五)
    第六周&java实验报告四
    课程总结
    第二周课程总结
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645444.html
Copyright © 2020-2023  润新知