OTA更新包内部

简介: 版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49948147 系统从bo...
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49948147

系统从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,仅仅接收文件名称,所以,为了能够完成这个工作,数据需要首先去解压缩到一个临时本地文件中.

目录
相关文章
|
3月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
4月前
|
监控 安全 数据安全/隐私保护
什么是OTA升级模式?
【7月更文挑战第20天】什么是OTA升级模式?
154 8
|
3月前
|
监控 开发工具 Android开发
结合GB/T28181规范探讨Android平台设备接入模块心跳实现
本文介绍了GB28181标准中的状态信息报送机制,即心跳机制,用于监控设备与服务器间的连接状态。根据国标GB/T28181-2016,设备在异常时需立即发送状态信息,在正常状态下则按固定间隔(默认60秒)定期发送。若连续三次(默认值)未收到心跳,则视为离线。文章展示了在Android平台的GB28181设备接入模块(SmartGBD)中,如何调整心跳间隔为20秒及超时次数为3次,并给出了心跳消息的示例和异常处理代码片段。对于希望深入了解或遇到问题的开发者,作者提供了进一步交流的机会。
|
6月前
|
Java API Android开发
Android系统升级A/B分区OTA升级应用层调用UpdateEngine代码
Android系统升级A/B分区OTA升级应用层调用UpdateEngine代码
132 0
|
6月前
|
JSON 算法 应用服务中间件
嵌入式设备OTA升级的大致过程!
嵌入式设备OTA升级的大致过程!
116 0
|
XML 前端开发 数据格式
国网B接口资源上报(Push_Resourse)接口描述和消息示例
上篇blog,梳理了国网B接口的REGISTER接口描述和消息示例,前端系统加电启动并初次注册成功后,向平台上报前端系统的设备资源信息(包括:视频服务器、DVR/DVS、摄像机、告警设备、环境量采集设备等模拟或数字信号采集设备信息)。
179 0
国网B接口资源上报(Push_Resourse)接口描述和消息示例
|
监控 JavaScript 物联网
阿里云物联网平台设备端响应物模型属性更新
在使用云端API SetDeviceProperty、iot studio设置设备属性、物联网平台控制台在线调试功能时,会出现物模型属性没有更新的情况。 以上功能中都是在调用SetDeviceProperty接口去更新物模型属性。 因为云端下发属性设置命令和设备收到并执行该命令是异步的,所以调用该接口时,返回的成功结果只表示云端下发属性设置的请求成功,不能保证设备端收到并执行了该请求。需设备端SDK成功响应云端设置设备属性值的请求,设备属性值才能真正设置成功。
1318 14
阿里云物联网平台设备端响应物模型属性更新
|
物联网 测试技术 数据安全/隐私保护
蓝牙核心规范V5.3版本有这些变动,你需要知道的都在这里
蓝牙核心规范V5.3版本有这些变动,你需要知道的都在这里
504 0
蓝牙核心规范V5.3版本有这些变动,你需要知道的都在这里
|
存储 自然语言处理 物联网
软件定义IOT,软件定义一切的时代正在到来
自从“软件定义”这个概念出现以后,所有硬件设备都在围绕软件定义作部署。于是,软件开始定义网络,定义存储,定义计算。
427 0
软件定义IOT,软件定义一切的时代正在到来