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中】:

$(INTERNAL_OTA_PACKAGE_TARGET):$(BUILT_TARGET_FILES_PACKAGE) $(OTATOOLS)@echo"Package OTA: $@"$(hide)./build/tools/releasetools/ota_from_target_files -v \-p $(HOST_OUT) \-k $(KEY_CERT_PAIR) \$(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中】:

$(BUILT_TARGET_FILES_PACKAGE):\$(INSTALLED_BOOTIMAGE_TARGET) \$(INSTALLED_RADIOIMAGE_TARGET) \$(INSTALLED_RECOVERYIMAGE_TARGET)\$(INSTALLED_SYSTEMIMAGE) \$(INSTALLED_USERDATAIMAGE_TARGET)\$(INSTALLED_ANDROID_INFO_TXT_TARGET)\$(built_ota_tools) \$(APKCERTS_FILE) \$(HOST_OUT_EXECUTABLES)/fs_config\| $(ACP)@echo "Package target files:$@"$(hide) rm -rf $@ $(zip_root)$(hide) mkdir -p $(dir $@) $(zip_root)@# Components of the recovery image$(hide) mkdir -p $(zip_root)/RECOVERY$(hide) $(call package_files-copy-root, \$(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/RECOVERY/RAMDISK)
ifdef INSTALLED_KERNEL_TARGET$(hide) $(ACP) $(INSTALLED_KERNEL_TARGET)$(zip_root)/RECOVERY/kernel
endif
ifdef INSTALLED_2NDBOOTLOADER_TARGET$(hide) $(ACP) \$(INSTALLED_2NDBOOTLOADER_TARGET)$(zip_root)/RECOVERY/second
endif
ifdef BOARD_KERNEL_CMDLINE$(hide) echo"$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/RECOVERY/cmdline
endif
ifdef BOARD_KERNEL_BASE$(hide) echo"$(BOARD_KERNEL_BASE)" > $(zip_root)/RECOVERY/base
endif
ifdef BOARD_KERNEL_PAGESIZE$(hide) echo "$(BOARD_KERNEL_PAGESIZE)"> $(zip_root)/RECOVERY/pagesize
endif@# Components of the boot image$(hide) mkdir -p $(zip_root)/BOOT$(hide) $(call package_files-copy-root, \$(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)
ifdef INSTALLED_KERNEL_TARGET$(hide) $(ACP) $(INSTALLED_KERNEL_TARGET)$(zip_root)/BOOT/kernel
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_KERNEL_PAGESIZE$(hide) echo"$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
endif$(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)@# Extra contents of the OTA package$(hide) mkdir -p $(zip_root)/OTA/bin$(hide) $(ACP)$(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/$(hide) $(ACP) $(PRIVATE_OTA_TOOLS)$(zip_root)/OTA/bin/@# Files that do not end up in anyimages, but are necessary to@# build them.$(hide) mkdir -p $(zip_root)/META$(hide) $(ACP) $(APKCERTS_FILE)$(zip_root)/META/apkcerts.txt$(hide)       echo"$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt$(hide) echo"recovery_api_version=$(PRIVATE_RECOVERY_API_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
ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE$(hide) echo"recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >>$(zip_root)/META/misc_info.txt
endif
ifdef BOARD_SYSTEMIMAGE_PARTITION_SIZE$(hide) echo"system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >>$(zip_root)/META/misc_info.txt
endif
ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)">> $(zip_root)/META/misc_info.txt
endif$(hide) echo"tool_extensions=$(tool_extensions)" >>$(zip_root)/META/misc_info.txt
ifdef mkyaffs2_extra_flags$(hide) echo"mkyaffs2_extra_flags=$(mkyaffs2_extra_flags)" >>$(zip_root)/META/misc_info.txt
endif@# Zip everything up, preserving symlinks$(hide) (cd $(zip_root) && zip-qry ../$(notdir $@) .)@# Run fs_config on all the system filesin the zip, and save the output$(hide) zipinfo -1 $@ | awk -F/ 'BEGIN {OFS="/" } /^SYSTEM\// {$$1 = "system"; print}' |$(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/filesystem_config.txt$(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]的定义如下:

def WriteFullOTAPackage(input_zip, output_zip):# TODO:how to determine this?  We don't knowwhat version it will# beinstalled on top of.  For now, we expectthe API just won't# changevery often.script =edify_generator.EdifyGenerator(3, OPTIONS.info_dict)metadata= {"post-build": GetBuildProp("ro.build.fingerprint",input_zip),"pre-device": GetBuildProp("ro.product.device",input_zip),"post-timestamp":GetBuildProp("ro.build.date.utc", input_zip),}device_specific = common.DeviceSpecificParams(input_zip=input_zip,input_version=OPTIONS.info_dict["recovery_api_version"],output_zip=output_zip,script=script,input_tmp=OPTIONS.input_tmp,metadata=metadata,info_dict=OPTIONS.info_dict,trusted_boot=OPTIONS.trusted_boot)#  if not OPTIONS.omit_prereq:
#    ts =GetBuildProp("ro.build.date.utc", input_zip)
#   script.AssertOlderBuild(ts)# AppendAssertions(script, input_zip)
# device_specific.FullOTA_Assertions()script.ShowProgress(0.9, 16)if OPTIONS.wipe_user_data:script.FormatPartition("/data")script.FormatPartition("/system")script.Mount("/system")
# script.UnpackPackageDir("recovery", "/system")script.UnpackPackageDir("system", "/system")symlinks= CopySystemFiles(input_zip, output_zip)script.MakeSymlinks(symlinks)# boot_img = common.File("boot.img", common.BuildBootableImage(
#     os.path.join(OPTIONS.input_tmp, "BOOT")))
# recovery_img = common.File("recovery.img",common.BuildBootableImage(
#     os.path.join(OPTIONS.input_tmp, "RECOVERY")))
# MakeRecoveryPatch(output_zip, recovery_img, boot_img)Item.GetMetadata(input_zip)Item.Get("system").SetPermissions(script)# common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)
# common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
# script.ShowProgress(0.2, 0)# script.ShowProgress(0.2, 10)
# script.WriteRawImage("/boot", "boot.img")# script.ShowProgress(0.1, 0)device_specific.FullOTA_InstallEnd()if OPTIONS.extra_script is not None:script.AppendExtra(OPTIONS.extra_script)script.UnmountAll()script.AddToZip(input_zip, output_zip)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相关推荐

  1. android ota 版本校验,OTA升级签名校验简析

    1. 概要 如果进行过OTA升级的开发者,都或多或少有这样的疑问,如何确定该OTA升级包是可以信任的呢?这其中其实涉及到一个签名验证的流程. 2. 签名生成 在生成正规的固件时,一般会运行生成新key ...

  2. 【转】Android OTA 升级之一:编译升级包

    Android OTA 升级之一:编译升级包 作者: 宋立新 Email : zjujoe@yahoo.com 前言 OTA 升级是 Android 系统提供的标准软件升级方式. 它功能强大,提供了完 ...

  3. Android OTA 升级之三:生成recovery.img

    Android OTA 升级之三:生成recovery.img 作者: 宋立新 Email:zjujoe@yahoo.com 前言 得到了ota升级包后,我们就可以用它来升级系统了.Android 手 ...

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

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

  5. android OTA更新

    Android OTA更新 ​ ​ ​ ​  Android设备可以接受和安装系统和应用软件的空中下载更新.设备有一个特殊的带有软件的recovery分区,该分区可以解压下载的更新包并且将他们应用到系 ...

  6. Android OTA升级原理和流程分析(五)---update.zip包从上层进入Recovery服务

    转载自:http://blog.chinaunix.net/uid-22028566-id-3533854.html 文章开头我们就提到update.zip包来源有两种: 一个是OTA在线下载(一般下 ...

  7. Android OTA在线升级一(架构分析)

    http://blog.csdn.net/huryjiang/article/details/7589625 1.前言 OTA(Over-the-Air Technology)空中下载技术.是通过移动 ...

  8. android ota机制,Android OTA简介

    Android OTA 简介 OTA 全称 over the air ,OTA升级是Android系统提供的标准软件升级方式. 它功能强大,提供了完全升级.增量升级模式,可以通过SD卡升级,也可以通过 ...

  9. Android OTA 问题分析

    分享下 Android OTA 问题分析思路,针对不同类型的问题进行分析. 一. 升级过程,校验失败: 升级校验失败是开发过程中常见的问题,校验失败实际是针对版本拿升级包进行打 patch,目前 An ...

  10. Android OTA 升级之五:updater

    2011-03-15 20:14 4164人阅读 评论(7) 收藏 举报 Android OTA 升级之五:updater 作者: 宋立新 Email:zjujoe@yahoo.com 前言 可以说, ...

最新文章

  1. 【Struts2学习笔记(1)】Struts2中Action名称的搜索顺序和多个Action共享一个视图--全局result配置...
  2. pythonscatter简书_python plotly 使用教程
  3. [我的成长:8期]一晃又半年了
  4. java deque_使用Deque
  5. 通过prompt方法增强开放领域问答模型
  6. vs 生成com组件 其他电脑_VS也可以这样进行快捷安装
  7. ERROR: libopenjp2 = 2.1.0 not found using pkg-config
  8. GoLang爬取花瓣网美女图片
  9. python url加密解密_python解密百度加密链接的脚本
  10. 基于Labview的瀑布图的生成
  11. win7系统无法开启telnet服务器,Win7系统开启telnet客户端解决无法使用命令问题
  12. linux电脑接电视,Ubuntu下如何给通过HDMI连接电视机的计算机强制设置1920*1080分辨率...
  13. lucene java 庖丁解牛_Lucene分词器之庖丁解牛
  14. Echarts安装失败
  15. 英语学习之沪江整理 20141101
  16. GEA 3.3 捕捉及处理错误
  17. 苏州文正学院计算机张晓青,北流市地图(广西政区图地图)
  18. 电脑性能配置怎么测试软件,配置查看性能测试及总结
  19. 【预测模型-BP分类】基于人工蜂群算法优化BP神经网络实现数据分类附matlab代码
  20. mongoDB拷贝数据库

热门文章

  1. java分层ppt_Java 合并、拆分PPT幻灯片
  2. 研究内容、研究方法、研究方案的区别与联系
  3. 微信小程序自定义组件省、市区联动
  4. verilog 移位运算符 说明_Verilog HDL的基本语法
  5. LDO的六大重要参数,你务必一一牢记
  6. HTML5期末大作业:茶叶网站设计——中国茶文化(30页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码
  7. 10kv配电网潮流 matlab,MATLAB配电网三相潮流程序设计
  8. manjaro远程linux,manjaro服务器的配置
  9. 【经典论文精读】浅谈神经网络的万能近似定理
  10. 少儿python编程和少儿c++编程学哪个比较好(2022.07.18)