整包与差分包生成流程

差分包生成指令

make otapackage 将编译生成的(xxx项目为例)

out/target/product/xxxxxxx/full_xxx_hxxxx-target_files-1527715386.zip

此时生成的是base.zip包

在代码中做一些修改,产生一些差异,第二次make otapackage将编译生成的

out/target/product/xxxxxxx/full_xxx_hxxxx-target_files-1533195243.zip

此时生成的是target.zip包

两者之间的差分包生成  ./build/tools/releasetools/ota_from_target_files -i base.zip target.zip update.zip

注:-i指定制作差分包,update.zip  就是升级用的差分包,这个脚本要在Android源码的根目录下执行。


/build/tools/releasetools/ota_from_target_files.py-v  (--verify)Remount and verify the checksums of the files written to thesystem and vendor (if used) partitions.  Incremental builds only.-i  (--incremental_from)  <file>Generate an incremental OTA using the given target-files zip asthe starting build.-t  (--worker_threads) <int>Specifies the number of worker-threads that will be used whengenerating patches for incremental updates (defaults to 3).......................

全包WriteFullOTAPackage函数主要功能

从ota_from_target_files.py脚本中WriteFullOTAPackage()和WriteBlockIncrementalOTAPackage这两个函数(分别用来生成全包和差分包)实现主要功能。

WriteFullOTAPackage将整包所需要的文件从差分资源包中读出并写入到整包中。

script = edify_generator.EdifyGenerator(target_api_version, target_info)

edify_generator对象,其FormatPartition、UnpackPackageDir等方法分别是向脚本文件update-script中写入格式化分区、解压包等指令。

.......

同时,它还会向整包中的META-INFO/com/google/android/updater-script文件中写入一些操作命令。而update-binary则是一个二进制文件,相当于一个脚本解释器,能够识别updater-script中描述的操作。

差分包WriteBlockIncrementalOTAPackage函数主要功能

Boot分区相关

def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):在函数中

  .......source_boot = common.GetBootableImage("/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",OPTIONS.source_info_dict)target_boot = common.GetBootableImage("/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT")updating_boot = (not OPTIONS.two_step and(source_boot.data != target_boot.data))

在之前已经得到了source target_file.zip中的boot.img和dest target_file.zip的boot.img数据分别为source_boot 与 target_boot,这里只是判断source_boot 与 target_boot是否相同来决定是否需要升级boot分区。

System数据来源

............system_src = GetImage("system", OPTIONS.source_tmp)system_tgt = GetImage("system", OPTIONS.target_tmp)

分别从source target_file.zip和dest target_file.zip中获取system数据,为后面生成system.new.dat、system.patch.dat、system.transfer.list三个文件提供数据来源。

生成差分包system dat,list文件

........system_diff = common.BlockDifference("system", system_tgt, system_src,check_first_block,version=blockimgdiff_version,disable_imgdiff=disable_imgdiff)

生成差分包中的system.new.dat、system.patch.dat、system.transfer.list三个文件 。

..........

d = common.Difference(target_boot, source_boot)

当boot.img有变化时生成boot.img.p文件,在updater-script脚本中对应下面命令:

apply_patch("EMMC:/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot:8306944:eec9f25c26fa112a037e15b265445ae142c5cca6:8308992:9bfb4708a965363ec53cd8b15f8a0d640f490dbc",

"-", 9bfb4708a965363ec53cd8b15f8a0d640f490dbc, 8308992,

eec9f25c26fa112a037e15b265445ae142c5cca6,

package_extract_file("patch/boot.img.p"))

校验system分区

...............

# Verify the existing partitions.

system_diff.WriteVerifyScript(script, touched_blocks_only=True)

校验升级前的system分区是否为基准版本,如果不是的话当然无法升级,因为system.new.dat、system.patch.dat、system.transfer.list是基于基准版本生成的。在updater-script脚本中对应下面命令

if (range_sha1("/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/system",”156,1,280,281,575,1256........”) == "faaa340bde5fccec0374da568463286d9454ae5b" || block_image_verify("/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat")) then

ui_print("Verified system image...");

生成升级system命令

.............

system_diff.WriteScript(script, output_zip,

progress=0.8 if vendor_diff else 0.9)

生成升级system的命令,在updater-script脚本中对应下面命令:

block_image_update("/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||

abort("E1001: Failed to update system image.");

对应recovery中的BlockImageUpdateFn函数

update-binary

........

script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)

把updater可执行程序放进升级包中,重命名为update-binary。update-binary是完成升级的程序,负责解析updater-script脚本中的命令并执行对应的C函数。

元数据

.........

FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)

把元数据输出到升级包的META-INF/com/android/metadata中。

差分包目录

差分升级包就是比较现存基础包与原来的基础包的差异而生成的,即该OTA包有特定的应用背景(用于两个差分包之间),用差分包升级不会格式化system分区,只是对其中部分存储段的内容进行重写。升级过程中,升级脚本(打开该升级包)会检测fingerprint,确保该升级包被正确应用。fingerprint这个属性存在于build.prop,可通过adb shell进入根路径,通过cat build.prop查看这个属性(或getprop)。内容在差分包的脚本META-INF/com/google/android/updater-script中。

getprop("ro.xxx.projectname") == "xxx_h5312_c1_in" || abort("E3004: This package is for \"x572_h5312_c1_in\" devices; this is a \"" + getprop("ro.rlk.projectname") + "\".");ui_print("Source: XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-XXX-O-IN-180531V42:user/release-keys");ui_print("Target: XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-XXX-O-IN-180802V69:user/release-keys");ui_print("Verifying current system...");getprop("ro.xxx.fingerprint") == "XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-XXX-O-IN-180531V42:user/release-keys" ||getprop("ro.xxx.fingerprint") == "XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-XXX-O-IN-180802V69:user/release-keys" ||abort("E3001: Package expects build fingerprint of XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-HXXX-O-IN-180531V42:user/release-keys or XXX/HXXX/XXX-XXX:8.1.0/O11019/XXX-HXXX-O-IN-180802V69:user/release-keys; this device has " + getprop("ro.xxx.fingerprint") + ".");apply_patch_check("EMMC:/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot:8306944:eec9f25c26fa112a037e15b265445ae142c5cca6:8308992:9bfb4708a965363ec53cd8b15f8a0d640f490dbc") || abort("E3005: \"EMMC:/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot:8306944:eec9f25c26fa112a037e15b265445ae142c5cca6:8308992:9bfb4708a965363ec53cd8b15f8a0d640f490dbc\" has unexpected contents.");apply_patch_space(81530880) || abort("E3006: Not enough free space on /cache to apply patches.");ui_print("Verified system image...");

差分包解压后主要包含了如下信息,如下截图是一个差分包的目录结构:

META-INF 该目录升级包的升级脚本

system.new.dat (升级包新数据)

system.new.dat文件实际上是由system.transfer.list描述的一个稀疏数组,这个过程的主要目的是降低ota.zip的大小,将system.img转换成为稀疏数组描述。
system.patch.dat(升级包中用于patch的数据)’
system.transfer.list(升级命令执行列表)

system.transfer.list

system.transfer.list是由build/tools/releasetools/blockimgdiff.py生成的,如下是文件头部的生成信息

    out.insert(0, "%d\n" % (self.version,))   # format version numberout.insert(1, "%d\n" % (total,))# v3+: the number of stash slots is unused.out.insert(2, "0\n")out.insert(3, str(max_stashed_blocks) + "\n")

升级参数命令解释(此部分摘自网络)

整个升级过程中的数据操作,包括数据转移(move)、临时存储(stash)、差分目标数据写入(bsdiff/imgdiff)、新数据写入(new)、数据删除(free/erase)是一个极为复杂且严格依照顺序执行的过程,有的命令是上下相关甚至是一环扣着一环的。这些命令的执行顺序是在生成升级包时即已确定。

在一个system.transfer.list文件中:

4

787044

0

19905

erase 10,197764,228864,263267,294400,654312,654345,1051592,1080832,1081858,1113600

第一行1表示该transfer文件的版本为4;

第二行表示new命令总共要写入787044个block;

第三行表示同时并存的stash文件数;

第四行表示最大tash文件所占用的block空间数;

第五行表示删除的range是从197764到1113600,10表示range的区间描述数目是10个数值,即197764,228864,263267,294400,654312,654345,1051592,1080832,1081858,1113600;

上述参数之后,就是具体的操作命令,逐条仔细分析(相同的命令将略过):

move

1.   move 3b8219cff7a8035c5cfe4e82a5e718c32f7439e8 2,289578,289582 4 2,287350,287354

格式:"cmdname" + "source hash"  + "tg block pos" +"sourceblock num" + "source block pos"

解析:将源block 287350至block 287354(共4 block,hash值为3b8219cff7a8035c5cfe4e82a5e718c32f7439e8)的数据移动至目标block 289578至block 289582的空间。

2.   move 1e100337aa3a13fd57fdd76ff3923aaff3c3c597 2,285947,288845 2898 2,283719,286617

本命令执行格式及目标与命令1相同,但由于源块区间(283719,286617)与目标块区间(285947,288845)产生重叠,所以在命令执行的过程中会先将读出的源数据临时存储于cache目录下文件名为1e100337aa3a13fd57fdd76ff3923aaff3c3c597的stash文件中,然后再将stash的数据读出写入目标块区间,写完之后再删除这个stash 文件。

3.   move c182ec1c52cb74fd5eb8c9ae87df62d5778d91c4 2,229351,229363 12 -c182ec1c52cb74fd5eb8c9ae87df62d5778d91c4:2,0,12

格式:"cmdname" + "source hash"  + "tg block pos" + "sourceblocknum" + "source stash file";

解析:将存储于cache目录下文件名为c182ec1c52cb74fd5eb8c9ae87df62d5778d91c4的stash文件中从0至12 block的数据读出,写入目标块区间(229351,229363)。

free

4.   free c182ec1c52cb74fd5eb8c9ae87df62d5778d91c4

解析: 删除存储于cache/reovery目录下指定的stash文件;

bsdiff

5.   bsdiff 0 3169086 ffc645d03fa4f56e72fefa872b792a76c26f9bb4 4bc0c9ddf123d54a04c800824c0951873e195ef1 2,295583,311859 16290 2,295583,311873

格式:"cmdname" +"patch offset" + "patch length" + "source hash" +"target hash" + "tg block pos" + "sourceblocknum" + "source block pos"

解析:读取源block区间数据(block 295583至block 311873,hash值为 ffc645d03fa4f56e72fefa872b792a76c26f9bb4),与system.patch.dat文件里偏移量为0,长度为3169086的数据进行bsdiff差分算法运算,生成的新数据存储至目标块区间blokc 295583至block 311859(hash值为4bc0c9ddf123d54a04c800824c0951873e195ef1)。

6.   bsdiff 30447439 8190 624a0bae2be2c5c40d562a7f3d26e7d7ef343329 6da9fb7c288322db82365bcafbe1371b3441a444 2,210082,210263 181 -624a0bae2be2c5c40d562a7f3d26e7d7ef343329:2,0,181

格式:"cmdname" +"patch offset" + "patch length" + "source hash" +"target hash" + "tg block pos" + "stash hash" +"stash range"

解析:读取stash文件624a0bae2be2c5c40d562a7f3d26e7d7ef343329数据(block 0至block 181,hash值为624a0bae2be2c5c40d562a7f3d26e7d7ef343329),与system.patch.dat文件里偏移量为30447439,长度为8190字节的数据进行bsdiff差分算法运算,生成的新数据存储至目标块区间block 210082至block 210263(hash值为6da9fb7c288322db82365bcafbe1371b3441a444)。

imgdiff

7.   imgdiff 6249859 22259bc3809a88c9f9b80b40fc23aeb5646333440717af4f900ef6c78fa7fca2ff6c2870aa88ec0247c7 2,155835,156013 178 2,153161,153339

解析:与命令6格式及执行流程一致,只是调用的差分算法为imgdiff算法。

stash

8.   stash 087da7ef6fac4bd7f31f19b428fead8067e4ac218,287287,287288,287417,287420,287444,287445,287457,287458

格式:"cmdname"+ "stash hash id" + "source range"

解析:将读取到的源块数据(从287287至287288,287417至287420,287444至287445,287457至287458),并确认其hash值为087da7ef6fac4bd7f31f19b428fead8067e4ac21后,存储于cache目录下文件名为087da7ef6fac4bd7f31f19b428fead8067e4ac21的stash文件。

new

9.   new 2,633274,634729

解析:system.new.dat文件中的数据被system.transfer.list文件中的new命令按顺序读取(634729-633274)*4096个字节,offset为前(n-1)new命令读取的字节总数;读取到的数据存储于block 633274至block 634729中。

erase

10. erase 6,32770,32929,32931,33439,65535,65536

解析:删除block 32770至32929,block32931至33439,block 65535至65536的数据。

zero 

11 .zero 4,1114498,1114620,1133015,1133016

解析:zero [rangeset]将目标分区的range使用0填充,需要填充0的block块范围总数:总共4个范围,【0-1114498】【1114498-1114620】,【1114620-1133015】,【1133015-1133016】

打印每个差分文件大小

以xxx的target zip

full_xxxx_hxxxx-target_files-1533195243/IMAGES/system.map其中内容是有diff相关的文件路径及块区域

.............

/system/xbin/tcpdump 1047561-1047824/system/vendor/ueventd.rc 1015803-1015804/system/vendor/thh/soter.raw 1049084-1051079/system/vendor/res/sound/testpattern1.wav 1015762-1015801/system/vendor/res/sound/ringtone.wav 1047092-1047560/system/vendor/res/images/lcd_test_02.png 1046641-1047091 .............会与XXX-HXXXE-O-IN-180531V42-180802V69_20180802173249差分包中system.transfer.list patchbsdiff 0 8110984 8ca22be96f18677d4d0867f68fa477c77b0bdde2 b15c4c039087cd9288998a0b5b7f995c78f50140 2,124693,128782 4712 2,124693,129405//通过这两个值属于system.map 文件中diff文件目录的块区间来匹配上,更改文件的patch大小bsdiff 8110984 256 5a057126ef0cb595ab425bf618a3eb5520b8f1e9 1c1dbf59201cd2c9e0462ad3a3850c4eacd34f1c 2,967806,967808 2 2,706180,706182bsdiff 8111240 266 fe97fd30a0fc42d0534d064b5c1c367d270cf2f0 82b3ed14ff51ed22324c6d55f362b21965e0fe2e 2,968647,968649 2 2,707021,707023

目前在blockimgdiff.py中在生成system.transfer.list文件之前添加相关输出

print("%s %10d %10d %7s %s (from %s) %d " % (

xf.style, xf.patch_start, xf.patch_len,

xf.tgt_name if xf.tgt_name == xf.src_name else (

xf.tgt_name + " (from " + xf.src_name + ")"),

str(xf.tgt_ranges), str(xf.src_ranges),xf.src_ranges.size()*4 * 1024))

xf.style差分类型

xf.patch_start patch起始位置

xf.patch_len patch文件大小

xf.src_ranges.size()*4 * 1024)  被写入字节

bsdiff      0       8110984  /system/app/Chrome/Chrome.apk-2 124693-128781 (from 124693-129404) 19300352bsdiff    8110984    256    /system/vendor/operator/app/TouchPal_ThaiPack/oat/arm64/TouchPal_ThaiPack.odex-cropped 967806-967807 (from 706180-706181) 8192bsdiff    8111240   266     /system/vendor/operator/app/TouchPal_UrduPack/oat/arm64/TouchPal_UrduPack.odex-cropped 968647-968648 (from 707021-707022) 8192bsdiff    8111506   2702    /system/vendor/operator/app/instagram/oat/arm/instagram.vdex 1043130-1046640 (from 877522-881032) 14381056bsdiff    8114208  21259875 /system/vendor/operator/app/facebook_messenger/oat/arm/facebook_messenger.vdex-0 1016316-1030144 (from 740774-753204) 50917376

.......

这样就可以查看是比较详细的查看每个差分文件的改动大小,比较方便的排查差分更新之后哪些文件增长多。

Android 差分包制作流程分析相关推荐

  1. linux差分包升级流程,OTA 差分升级包的制作

    OTA 升级是 Android 系统提供的标准软件升级方式. 它功能强大,提供了完全升级.增量升级模式,可以通过 SD卡升级,也可以通过网络升级. 那如何生成差分升级包呢? Android源码的根目录 ...

  2. Android OTA差分包制作(RK平台)

    一.步骤说明 1. 编译两个新旧版本,需要用到两个版本的rk3566_r-target_files-eng.zip文件. 2. 将两个版本的rockdev/Image-rk3566_r/rk3566_ ...

  3. c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

    在我的上一篇文章: AJie:按下电源键后竟然发生了这一幕 -- Android 系统启动流程分析​zhuanlan.zhihu.com 我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS( ...

  4. android 屏幕旋转流程,android自动屏幕旋转流程分析.doc

    android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...

  5. Android8.0(34)----Android 8.0 Settings流程分析与变动

    Android 8.0 Settings流程分析与变动 一,相比Android Settings 7.0 如下图,在7.0的基础上,去掉了7.0新加的侧滑菜单(可能是觉得有点鸡肋吧).多加了一级页面, ...

  6. Android 手机灭屏流程分析详解

    参考地址:https://www.jianshu.com/p/9241f3a91095 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.前言 2.Pow ...

  7. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

  8. Android Fota(差分包)制作

    Android Fota包制作 Fota包生成步骤 问题 Fota包生成步骤 在Android系统编译(make)完成后,执行 make otapackage即可生成制作差分包所需的target pa ...

  9. RK3326平台Android9.0OTA差分包制作

    源码全编成功后执行make otapackage 会生成两个OTA包,路径如下 #整包 out/target/product/rk3326/rk3326-ota-eng.ubuntu.zip #用于制 ...

最新文章

  1. 【干货】105页周志华教授《机器学习手推公式》开源PDF
  2. 十进制转换成二进制列表
  3. Gradle Android客户端程序打包(基于gradle 2.10版本验证通过)
  4. chrome添加来自其他网站的扩展程序
  5. VTK:PolyData之HighlightBadCells
  6. React系列---Babel
  7. mysql存储java对象_Mysql存储java对象 | 学步园
  8. html中transition默认,CSS3中的Transition详解
  9. 利用网络月赚10000元揭密
  10. tecplot 360 2018 R1 R2安装教程及软件百度云
  11. matlab get(gcf,'postion ')相关解释
  12. python刷新cdn_使用Python解析阿里云CDN日志
  13. Cloudreve离线下载Aria2安装教程
  14. web课程设计网页规划与设计----公司官网带轮播图 (页面精美 1页)
  15. PBC Library Manual(PBC库手册)翻译(一)
  16. mpvue的一些知识
  17. html+css静态页面还原 拼多多网页
  18. 存款准备金率,央行票据
  19. oracle 00600 kccpb,惜分飞 - 提供7*24专业数据库(Oracle,SQL Server,MySQL等)恢复和Oracle技术服务@Tel:+86 13429648788...
  20. 甲骨文总裁拉里·埃里森在耶鲁大学的演讲

热门文章

  1. word 怎么删除多余的空白页
  2. 【Android studio】使用雷电模拟器详细过程(或其他)(转)
  3. 冰冻三尺非一日之寒-自学篇 浅谈个人学习方法
  4. 新媒体营销的模式,自媒体营销方式有哪些
  5. 猿辅导python编程老师面试_猿辅导辅导老师面试一系列的感受
  6. U盘文件丢失求恢复教程
  7. (六)Activiti之实现学生请假流程
  8. 计算机的桌面图标都可以重新命名对吗,windows上哪个图标不能重命名
  9. c语言字节类型(bytes),Python bytes类型及用法
  10. 详解windows10安装失败怎么办