Android OTA 升级中的一些零碎知识


# Recovery is generated as a patch using both the boot image
# (which contains the same linux kernel as recovery) and the file
# /system/etc/recovery-resource.dat (which contains all the images
# used in the recovery UI) as sources.  This lets us minimize the
# size of the patch, which must be included in every OTA package.
# For older builds where recovery-resource.dat is not present, we
# use only the boot image as the source. ref: build/tools/releasetools/ota_from_target_files

source of imgdiff and bsdiffbootable/recovery/applypatch

Android端的升级脚本两步策略中的第二步,升级重启后执行的脚本(包括建立软链接和权限设置)。 META-INF/com/google/android/updater-script


imgdiff是android提供的用来生成binary patch的工具,android同时还提供了另一个binary patch工具是bsdiff。

usage: -z <src-img> <tgt-img> <patch-file>

-z: 输入文件是否是ZIP格式

-b: 额外的二进制文件,在OTA中,这个文件就是recovery-resource.dat



- This program(imgdiff) constructs binary patches for images -- such as boot.img
- and recovery.img -- that consist primarily of large chunks of gzipped
- data interspersed with uncompressed data.  Doing a naive bsdiff of
- these files is not useful because small changes in the data lead to
- large changes in the compressed bitstream; bsdiff patches of gzipped
- data are typically as large as the data itself



ota_from_target_files -f 0 -d "MMC"  -p  out/host/linux-x86/   -k  build/target/product/security/testkey   -v  ~/tmp/


ota_from_target_files -f 0 -d "MMC" -p out/host/linux-x86 -k build/target/product/security/testkey -v -i   ~/tmp/



  if OPTIONS.incremental_source is None:

WriteFullOTAPackage(input_zip, output_zip, OPTIONS.fota)

if OPTIONS.package_key is None:

  OPTIONS.package_key = OPTIONS.info_dict.get(




print "unzipping source target-files..."

OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)

OPTIONS.target_info_dict = OPTIONS.info_dict

OPTIONS.source_info_dict = common.LoadInfoDict(source_zip, OPTIONS.device_type)

if OPTIONS.package_key is None:

  OPTIONS.package_key = OPTIONS.source_info_dict.get(



if OPTIONS.verbose:

  print "--- source info ---"


WriteIncrementalOTAPackage(input_zip, source_zip, output_zip, OPTIONS.fota)







  def GetMetadata(cls, input_zip):

The target_files contains a record of what the uid,

gid, and mode are supposed to be.

output ="META/filesystem_config.txt")

for line in output.split("\n"):

  if not line: continue

  columns = line.split()

  name, uid, gid, mode = columns[:4]

  selabel = None

  capabilities = None

After the first 4 columns, there are a series of key=value

pairs. Extract out the fields we care about.

  for element in columns[4:]:
key, value = element.split("=")
if key == "selabel":
  selabel = value
if key == "capabilities":
  capabilities = value
    i = cls.ITEMS.get(name, None)

  if i is not None:
i.uid = int(uid)
i.gid = int(gid)
i.mode = int(mode, 8)
i.selabel = selabel
i.capabilities = capabilities
if i.dir:
  i.children.sort(key=lambda i:
  set metadata for the files generated by this script.

i = cls.ITEMS.get("system/recovery-from-boot.p", None)

if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None

i = cls.ITEMS.get("system/etc/", None)

if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None

从上面的代码可以看到脚本读取的是META/filesystem_config.txt中的内容,这个文件是有源码编译的生成的。所以如果你增加了一些apk到image中,然后制作OTA,你需要自己赋予你的apk相应的权限,否则在生成OTA的时候就会出错(找不到 uid, gid, mode …),不要试图随意赋这些值。



$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt

$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt

$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt

$(hide) (cd $(zip_root) && zip -q ../$(notdir [email protected]) META/*filesystem_config.txt)


这个工具是生成上一步中的filesystem_config.txt的核心,其源码在build/tools/fs_config 参数说明:

// This program takes a list of files and directories (indicated by a

// trailing slash) on the stdin, and prints to stdout each input

// filename along with its desired uid, gid, and mode (in octal).

// The leading slash should be stripped from the input.


// After the first 4 columns, optional key=value pairs are emitted

// for each file.  Currently, the following keys are supported:

// * -S: selabel=[selinux_label]

// * -C: capabilities=[hex capabilities value]


// Example input:


//      system/etc/dbus.conf

//      data/app/


// Output:


//      system/etc/dbus.conf 1002 1002 440

//      data/app 1000 1000 771


//   or if, for example, -S is used:


//      system/etc/dbus.conf 1002 1002 440 selabel=u:object_r:system_file:s0

//      data/app 1000 1000 771 selabel=u:object_r:apk_data_file:s0


// Note that the output will omit the trailing slash from

// directories.