OTA更新包内部

原创 2015年11月20日 16:09:02

系统从bootable/recovery/updater中构建updater二进制程序,并且在OTA更新包里面使用他.

更新包本身是一个.zip压缩包文件(ota_update.zip,incremental_ota_update.zip),压缩包内包含可执行二进制程序 META-INF/com.google/android/update-binary .

Updater包含几个内置函数和用于可扩展脚本语言(edify)的解释器,可扩展脚本语言支持与更新任务相关的命令.Updater从.zip中的 META-INF/com/google/android/updater-script查找脚本.

注意:使用edify脚本和内置的函数不是命令,但是如果你需要调试这个更新文件的话是非常有用的

Edify语法


一个edify脚本是一个单一的语句,在脚本中,所有的值都是字符串.空字符串在一个Boolean上下文中是false,其他所有的字符串都是true.Edify支持下面的操作(都是通常的含义)

(expr )
 expr + expr  # string concatenation, not integer addition
 expr == expr
 expr != expr
 expr && expr
 expr || expr
 ! expr
 if expr then expr endif
 if expr then expr else expr endif
 function_name(expr, expr,...)
 expr; expr

任何由a-z,A-Z,0-9,_,:,/,.这些字符组成的,凡不是保留字的,都看作是字符串.(保留字是if else then endif).字符串使用双引号因起来,下面是如何创建空格和其他不在上面集合中的自负值.\n,\t,\”,和\为转义字符.

&&和||操作符是和我们平时编程的时候一样的,下面两个是等价的:

e1 && e2
if e1 then e2 endif

;操作符号是一个序列点;他的意思是,首先分析左边的表达式,然后分析右边的表达式.他的值是右边表达式的值.分号也用于一个表达式的后面,像是C语言风格的模拟.

prepare();
do_other_thing("argument");
finish_up();

内置函数


大多数更新功能都被包含在可用的函数中被脚本执行.(在Lisp意义上,严格的说这些是宏而不是函数,他们需要分析所有的参数).除非另有说明,函数返回true表示执行成功,返回false表示执行出错.如果你想在出错的时候停止脚本的执行,使用abort()或者是asset()函数.在updater中可用的函数集合也可以被扩展提供设备特定功能(后面会讲到).

  • abort([msg])
    立即结束脚本的执行,带有可选信息.如果用户已经切换到文本显示,msg会出现在recovery log中和屏幕上.

  • assert(expr[, expr, ...])
    依次分析每一个expr.如果任何一个是false,立即终止脚本的执行,并且显示信息”assert failed”和错误语句的源文本.

    -apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])
    将一个二进制补丁应用到src_file中来生成tgt_file.如果期望的目标和源码是一样的,向tgt_file传递”-“.tgt_sha1和tgt_size是期望的最终的SHA1哈希和目标文件的大小.剩下的参数必须是成对出现的:一个SHA1哈希(40位字符的16进制字符串)和一个块.当源码当前的内容已经有了SHA1,块就是要被应用的补丁.

    打补丁以一个安全的方式完成了,这保证了目标文件拥有期望的SHA1哈希和大小,或者是他是不变的.如果打包过程被中断,目标文件可能会在一个中间状态;位于cache分区的一个复制品,所以重启更新就能成功更新那个文件.

    把存储技术设备(MTD)分区当作文件的特殊语法也是支持的,允许对raw分区的打包,例如boot.为了读取一个MTD分区,既然该分区没有文件末尾的概念,你一定要知道你想要读取多少数据.你一定要使用字符串”MTD:partition:size_1:sha1_1:size_2: sha1_2”作为文件名称来读取给定的分区.你至少指定一个(size,sha-1)对;如果有多个可能性,但是对你想要读取的内容至少指定一个.

  • apply_patch_check(filename, sha1[, sha1, ...])
    如果文件名称或者是在cache分区中的临时复制品有一个和给定的sha1值相同的SHA1的话,就会返回true.sha1值被指定为40位的16进制数字.这个函数和sha1_check(read_file(filename), sha1 [, …]) 不同的是,他知道去检查cache分区中的copy,所以,apply_patch_check()将会成功即使文件被一个中断的apply_patch() 更新损坏了.

  • apply_patch_space(bytes)
    如果至少暂存空间对应用的二进制补丁可用的话返回true

  • concat(expr[, expr, ...])
    分析每一个语句并且连接他们.+操作在两个参数的特殊情况下是这个函数的语法糖(但是该函数能够接受任意数量的语句).语句必须是字符串,他不能连接块.

  • delete([filename, ...])
    删除列出文件名的所有.返回成功删除的文件的数量.

  • delete_recursive([dirname, ...])
    递归删除dirnames和其所有的内容.返回成功删除的目录的个数.

  • file_getprop(filename, key)
    读取给定的文件名的文件,作为属性文件解释(例如,/system/build.prop),返回给定的key的值,或者是如果key不存在,返回空字符串.

  • format(fs_type, partition_type, location, fs_size, mount_point)
    重新格式化给定的分区.支持的分区类型:

    • fs_type = “yaffs2”并且partition_type=”MTD”.位置必须是MTD分区的名称;一个空的yaffs2文件系统在那里被构建.其他的参数就不用了.

    • fs_type=”ext4”并且partition_type=”EMMC”.位置一定是分区的设备文件.一个空的ext4文件系统在那里被构建.如果fs_size为0,文件系统采用整个分区.如果fs_size为一个正数,文件系统采用分区的fs_size大小位.如果fs_size是一个负数,文件系统采用除了|fs_size|大小的区域.

    • fs_type=”f2fs”并且partition_type=”EMMC”.位置一定要是分区设备文件.fs_size必须是非负数.如果fs_size为0,文件系统采用整个分区.如果fs_size为正数,文件系统采用这些大小位的分区.
      mount_point(挂载点)一定要是后来文件系统挂载的点.

  • getprop(key)
    返回系统属性key的值(如果没有定义,返回空字符串).被recovery分区定义的系统属性值不必和主系统定义的一样.这个函数在recovery模式中返回值.

  • greater_than_int(a, b)
    如果a比b大的话,返回true

  • ifelse(cond, e1[, e2])
    分析条件,如果条件为真,返回e1的值,如果条件为假,返回e2的值(如果存在的话).”if…else..then..endif”是该函数的一个语法糖.

  • is_mounted(mount_point)
    如果文件系统在挂载点被挂载了返回true

  • is_substring(needle, haystack)
    如果needle是haystack的子串的话返回true

  • less_than_int(a, b)
    如果a小于b的话返回true

  • mount(fs_type, partition_type, name, mount_point)
    挂载fs_type在mount_point的文件系统.partition_type一定是下面的一个:

    • MTD:名称是MTD分区的名称(例如,system,userdata;查看设备上的/proc/mtd获取完整的列表).

    • EMMC:Recovery默认情况下不会挂载任何文件系统(如果用户从SD卡中手动安装更新的话,SD开需要挂载);你的脚本必须挂载你需要修改的分区.

  • package_extract_dir(package_dir, dest_dir)
    从package_dir下提取所有的文件,并且将他们写到相应的dest_dir下面.任何存在的文件都要被重写.

  • package_extract_file(package_file[, dest_file])
    从更新包中提取一个单一的package_file,并且将他们写入到dest_file中,如果必要的话,重写存在的文件.如果没有dest_dir参数的话,将包文件的内容作为二进制块返回.

  • read_file(filename)
    读取文件并且返回他的内容作为一个二进制块.

  • rename(src_filename, tgt_filename)
    重命名src_filename为tgt_filename.他自动为tgt_filename创建一个必要的目录.例如:
    rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk").

  • run_program(path[, arg, ...])
    在path中,通过传递args执行二进制程序.返回程序的退出状态.

  • set_metadata(filename, key1, value1[, key2 , value2, ...])
    给给定的文件名称的键赋值.举个例子:

    set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0).

  • set_metadata_recursive(dirname, key1, value1[, key2, value2, ...])
    递归设置给定目录和他的子文件的键和值.举个例子:

    set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0)

  • set_progress(frac)
    在由show_progress()调用创建的块中设置进度条的位置.frac必须在[0.0,1.0]区间内.进度条不会后退.尝试这样的做法被忽略了.

  • sha1_check(blob[, sha1])
    blob参数是有read_file()返回的类型的块或者是package_extract_file()的一个参数形式.如果没有sha1参数,该函数返回块的SHA1哈希.如果存在一个或多个sha1参数,如果SHA1和一个参数相等的话,返回SHA1哈希,如果没有相等的,则返回空字符串.

  • show_progress(frac, secs)
    推进进度条在sec秒中到达frac长度.secs可能为0,在这种情况下,进度条不会被自动推进.

  • sleep(secs)
    睡眠secs秒(必须是整数)

  • stdout(expr[, expr, ...])
    分析每一个表达式并且将他的值转储到stdout.在调试的时候有用.

  • symlink(target[, source, ...])
    创建所有源码为链接到目标中.

  • tune2fs(device[, arg, …])
    在设备上调整可调参数args

  • ui_print([text, ...])
    连接所有的文本参数并且将结果打印到UI中(如果用户转换到文本显示的话结果就是可视的)

  • unmount(mount_point)
    卸载在挂载点挂载的文件系统

  • wipe_block_device(block_dev, len)
    清楚给定块设备block_dev的len位的数据.

  • wipe_cache()
    在成功安装之后,清空cache分区

  • write_raw_image(filename_or_blob, partition)
    在filename_or_blob中把镜像写入到MTD分区中. filename_or_blob可以是一个字符串名称是本地文件或者是一个包含数据的块值参数.为了能够从OTA包中复制一个文件到分区中,使用:

    write_raw_image(package_extract_file("zip_filename"), "partition_name")

    注意:之前Android 4.1,仅仅接收文件名称,所以,为了能够完成这个工作,数据需要首先去解压缩到一个临时本地文件中.

版权声明:您好,转载请留下本人博客的地址,谢谢

OTA升级包制作

1.差分升级 差分包(版本A差分升级到版本B,要先分别制作版本A的资源包A,和版本B的资源包B)的制作步骤 source build/envsetup.sh  lunch MULTILANGU...
  • qzh870808
  • qzh870808
  • 2016年12月06日 09:19
  • 591

Android下编译OTA升级包

1)概念介绍          我们知道Android系统一般可以通过本地升级和空中升级两种,一般本地升级包括SD卡升级、U盘升级、串口升级等。而所谓的空中升级就是通过网络将升级包下载升级包到本地,进...
  • llping2010
  • llping2010
  • 2013年07月26日 10:58
  • 3634

Android 5.x OTA Update官方文档(十、版本签名)

在Android中,一般来说有两个地方使用加密签名。 1.每个.apk文件必须进行签名。Android的程序包管理器通过两种方式使用签名: 当一个应用程序被替换时,只有相同签名的应用才能操作旧版本的数...
  • huangyabin001
  • huangyabin001
  • 2015年04月06日 21:10
  • 4908

如何给Android的OTA包添加校验标识

如何给Android OTA 升级包添加 检测标识
  • y20082478
  • y20082478
  • 2016年09月02日 13:04
  • 976

android ota 升级包制作分析 (3 打包流程)

主流程(main) 解析输入参数(common.ParseOptions) 解压输入zip文件(input_zip,common.UnzipTemp) 读入META信息字典(com...
  • luansxx
  • luansxx
  • 2014年06月08日 10:52
  • 4281

Android 5.x OTA Update官方文档(四、OTA更新包解读)

写在前面: 系统创建通过“bootable/recovery/updater”创建一个二进制更新程序并在OTA包中使用进行更新的安装。 更新包实际上也就是一个.zip格式的压缩文件(如我们之前提到过的...
  • huangyabin001
  • huangyabin001
  • 2015年04月04日 16:24
  • 3054

关于ota升级查找不到更新包的原因分析

首先此类问题要回溯一下在此之前是否有类似的问题出现,或者查找具有参参考价值的资料,如果没有,就需要了解ota升级客户端与服务器交互的流程,以便于查找问题出现的根源。     总的来说我遇到过3例类似...
  • huangyabin001
  • huangyabin001
  • 2015年02月02日 14:42
  • 1094

iOS通过OTA方式分发应用的实现

转:http://blog.sina.com.cn/s/blog_6afb7d800101fa16.html   苹果的企业级证书发布的应用,是不用设备授权即可直接安装,并且不限设备上限。为了方便分...
  • zhangmiaoping23
  • zhangmiaoping23
  • 2015年07月20日 23:12
  • 3786

OTA本质与实现流程分析

接触OTA也有段时间了,是时候总结下了。所谓OTA(Over-the-AirTechnology)是指手机终端通过无线网下载远程服务器上的升级包,对系统或应用进行升级的技术。有关网络部分不做过多讨论,...
  • bi511304183
  • bi511304183
  • 2013年07月16日 10:38
  • 8188

OTA服务器和android客户端添加HTTPS协议

有段时间没总结了,这期间主要学习三个问题: 一是https协议,OTA HTTPS 协议可以工作了。 二是消息推送,推送用的是openfire+asmack方案,目前只能给所有用户广播消息,如果针对不...
  • tww85
  • tww85
  • 2016年11月30日 12:15
  • 1070
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OTA更新包内部
举报原因:
原因补充:

(最多只允许输入30个字)