android导出函数脚本,Android OTA升级包制作脚本详解(四,生成升级脚本updater-script)...
①对比更新包时间戳,只允许升级旧版本下面这段代码是在ota_from_target_files中的语句#下面这段代码我们可以理解为不允许降级,也就是说在脚本中的这段Assert语句,使得update zip包只能用于升级旧版本。if not OPTIONS.omit_prereq:ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)#得
①对比更新包时间戳,只允许升级旧版本
下面这段代码是在ota_from_target_files中的语句
#下面这段代码我们可以理解为不允许降级,也就是说在脚本中的这段Assert语句,使得update zip包只能用于升级旧版本。
if not OPTIONS.omit_prereq:
ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)#得到系统编译世界时间
ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict)#得到编译日期
script.AssertOlderBuild(ts, ts_text)
下面是对应edify_generator模块的中的相关方法:
def AssertOlderBuild(self, timestamp, timestamp_text):
"""Assert that the build on the device is older (or the same as)
the given timestamp."""
self.script.append(
('(!less_than_int(%s, getprop("ro.build.date.utc"))) || '
'abort("Can\'t install this package (%s) over newer '
'build (" + getprop("ro.build.date") + ").");'
) % (timestamp, timestamp_text))
那么我们从上面的代码中可以看到,这里呢在updater-script中追加了这样的一段语句:
'(!less_than_int(%s, getprop("ro.build.date.utc"))) || '
'abort("Can\'t install this package (%s) over newer '
'build (" + getprop("ro.build.date") + ").");'
) % (timestamp, timestamp_text)
那么实际在脚本中是这样子的,如:
(!less_than_int(1413536309, getprop("ro.build.date.utc"))) || abort("Can't install this package (Fri Oct 17 16:58:29 CST 2014) over newer build (" + getprop("ro.build.date") + ").");
那么这段话我们在执行updater-script脚本的时候具体逻辑是指当更新包中版本低于当前手机中的版本时终止安装更新。那么在安装的时候具体如何操作的呢,我们随后再详细描述。
②显示进度
#在升级脚本中生成显示进度的语句,这里实际上是在脚本中增加了这样一条语句(show_progress) 参数一表示将暂用的时间在总体时间的比例。参数二用于控制显示速度。如show_progress(0.1, 10);show_progress下面的操作可能进行10s,完成后进度条前进0.1(也就是10%)
script.ShowProgress(0.5, 0)
那么这里调用了edify_generator模块中的ShowProgress(0.05,0):
def SetProgress(self, frac):
"""Set the position of the progress bar within the chunk defined
by the most recent ShowProgress call. 'frac' should be in
[0,1]."""
self.script.append("set_progress(%f);" % (frac,))
而实际在updater-script中的逻辑如下:
show_progress(0.500000, 0);
③格式化分区
#如果命令中有参数要求擦除data分区数据,那么在升级脚本中生成格式化分区的语句,分区用挂载点来描述,格式如下:(/data)
if OPTIONS.wipe_user_data:
script.FormatPartition("/data")
那么这里调用了edify_generator模块中的FormatPartition()函数:
def FormatPartition(self, partition):
"""Format the given partition, specified by its mount point (eg,
"/system")."""
reserve_size = 0
fstab = self.info.get("fstab", None)
#wschen 2012-11-12
if partition == "/custom":
self.script.append('format("ext4", "EMMC", "/dev/block/mmcblk", "0", "/custom");')
elif fstab:
p = fstab[partition]
self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
(p.fs_type, common.PARTITION_TYPES[p.fs_type],
p.device, p.length, p.mount_point))
④挂载分区
script.Mount("/system")
那么这里调用了edify_generator模块中的Mount()函数:
def Mount(self, mount_point):
"""Mount the partition with the given mount_point."""
#根据指定的挂载点挂载分区
fstab = self.info.get("fstab", None)
#wschen 2012-11-12
#这里挂载定制分区custom,暂不作详细描述,随后会针对升级定制分区进行一个详细的介绍
if mount_point == "/custom":
self.script.append('mount("ext4", "EMMC", "/dev/block/mmcblk", "/custom");')
self.mounts.add(mount_point)
elif fstab:
p = fstab[mount_point]
self.script.append('mount("%s", "%s", "%s", "%s");' %
(p.fs_type, common.PARTITION_TYPES[p.fs_type],
p.device, p.mount_point))
self.mounts.add(p.mount_point)
⑤释放文件夹内容到指定文件夹下,注意这里被释放的文件夹是指在OTA package中也就是更新包中的对应的文件夹,也就是下面函数中的第一个参数
script.UnpackPackageDir("recovery", "/system")
script.UnpackPackageDir("system", "/system")
那么这里调用了edify_generator模块中的UnpackPackageDir()函数
def UnpackPackageDir(self, src, dst):
"""Unpack a given directory from the OTA package into the given
destination directory."""
self.script.append('package_extract_dir("%s", "%s");' % (src, dst))
⑥建立符号链接
symlinks = CopySystemFiles(input_zip, output_zip)
script.MakeSymlinks(symlinks)
edify_generator模块中相对应的MakeSymlinks()函数
def MakeSymlinks(self, symlink_list):
"""Create symlinks, given a list of (dest, link) pairs."""
by_dest = {}
for d, l in symlink_list:
by_dest.setdefault(d, []).append(l)
for dest, links in sorted(by_dest.iteritems()):
cmd = ('symlink("%s", ' % (dest,) +
",\0".join(['"' + i + '"' for i in sorted(links)]) + ");")
self.script.append(self._WordWrap(cmd))
⑦权限设置
script.SetPermissions("/"+item.name, item.uid, item.gid,
item.mode, item.selabel, item.capabilities)
具体函数如:
def SetPermissions(self, fn, uid, gid, mode, selabel, capabilities):
"""Set file ownership and permissions."""
if not self.info.get("use_set_metadata", False):
self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
else:
if capabilities is None: capabilities = "0x0"
cmd = 'set_metadata("%s", "uid", %d, "gid", %d, "mode", 0%o, ' \
'"capabilities", %s' % (fn, uid, gid, mode, capabilities)
if selabel is not None:
cmd += ', "selabel", "%s"' % ( selabel )
cmd += ');'
self.script.append(cmd)
⑧写入分区
script.WriteRawImage("/boot", "boot.img")
具体相对应函数如下:
def WriteRawImage(self, mount_point, fn):
"""Write the given package file into the partition for the given
mount point."""
fstab = self.info["fstab"]
if fstab:
p = fstab[mount_point]
partition_type = common.PARTITION_TYPES[p.fs_type]
args = {'device': p.device, 'fn': fn}
if fn == "boot.img" and p.device == "boot":
self.script.append(
('assert(package_extract_file("%(fn)s", "/tmp/%(fn)s"),\n'
' write_raw_image("/tmp/%(fn)s", "bootimg"),\n'
' delete("/tmp/%(fn)s"));') % args)
elif partition_type == "MTD":
self.script.append(
'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");'
% args)
elif partition_type == "EMMC":
self.script.append(
'package_extract_file("%(fn)s", "%(device)s");' % args)
else:
raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,))
更多推荐



所有评论(0)