345 def WriteFullOTAPackage(input_zip, output_zip):
346 if OPTIONS.script_mode == "auto":
347 script = both_generator.BothGenerator(2)
348 elif OPTIONS.script_mode == "amend":
349 script = amend_generator.AmendGenerator()
350 else:
351 # TODO: how to determine this? We don't know what version it will
352 # be installed on top of. For now, we expect the API just won't
353 # change very often.
354 script = edify_generator.EdifyGenerator(2)
首先,我们获得脚本生成器,他们的实现见脚本:edify_generator.py 等。
356 metadata = {"post-build": GetBuildProp("ro.build.fingerprint", input_zip),
357 "pre-device": GetBuildProp("ro.product.device", input_zip),
358 "post-timestamp": GetBuildProp("ro.build.date.utc", input_zip),
359 }
获得一些环境变量,来自android 环境变量。 Google 一下即知其义。
361 device_specific = common.DeviceSpecificParams(
362 input_zip=input_zip,
363 input_version=GetRecoveryAPIVersion(input_zip),
364 output_zip=output_zip,
365 script=script,
366 input_tmp=OPTIONS.input_tmp,
367 metadata=metadata)
设备相关参数,不深究。
369 if not OPTIONS.omit_prereq:
370 ts = GetBuildProp("ro.build.date.utc", input_zip)
371 script.AssertOlderBuild(ts)
如果需要,在脚本中增加一个Assert语句,要求update zip包只能用于升级老的系统。
373 AppendAssertions(script, input_zip)
如果需要,在脚本中增加一个Assert语句,要求update zip包只能用于同一设备,即目标设备的 ro.product.device必须跟update.zip中的相同。
374 device_specific.FullOTA_Assertions()
Callback, 用于调用设备相关代码。调用时机为即将开始升级。类似还有:
FullOTA_InstallEnd IncrementalOTA_Assertions IncrementalOTA_VerifyEnd。 不深究。
376 script.ShowProgress(0.5, 0)
在升级脚本中加入显示进度的语句, 参数一表示底下的操作(到下一条同类语句或者到末尾)将暂用的时间在总体时间的比例。参数二用于控制显示的速度。比如,50 则表示底下的操作估计50秒内完成,要求进度条显示线程用50秒显示这一部分的进度。0 表示不自动更新,手动控制(使用SetProgress)
378 if OPTIONS.wipe_user_data:
379 script.FormatPartition("userdata")
如果需要,在脚本中增加语句,擦除 userdata 分区。
381 script.FormatPartition("system")
在脚本中增加语句,擦除 system分区。
382 script.Mount("MTD", "system", "/system")
在脚本中增加语句,安装 system分区到 /system 目录。
383 script.UnpackPackageDir("recovery", "/system")
384 script.UnpackPackageDir("system", "/system")
在脚本中增加语句,将recovery以及system中的内容拷贝到 /system目录。其中recovery 目录包含一个patch 以及应用该patch 的脚本。
386 symlinks = CopySystemFiles(input_zip, output_zip)
387 script.MakeSymlinks(symlinks)
386 行从输入 ZIP 包 /system 拷贝文件到输出 ZIP 包 /system。由于这个过程不支持链接文件,所以它将这些文件返回。 于 387 行做继续处理。该行建立这些link 文件。所有的link文件都指向 toolbox
389 boot_img = File("boot.img", common.BuildBootableImage(
390 os.path.join(OPTIONS.input_tmp, "BOOT")))
391 recovery_img = File("recovery.img", common.BuildBootableImage(
392 os.path.join(OPTIONS.input_tmp, "RECOVERY")))
393 MakeRecoveryPatch(output_zip, recovery_img, boot_img)
这个复杂,MakeRecoveryPatch 做了两件事:
1.在输出 ZIP包中生成一个patch: recovery/recovery-from-boot.p(boot.img和 recovery.img的patch), 它最后会位于:system/recovery-from-boot.p
2.在输出 ZIP包中生成一个脚本:recovery/etc/install-recovery.sh , 它最后会位于system/etc/install-recovery.sh.
该脚本的内容为:
#!/system/bin/sh
if ! applypatch -c MTD:recovery:2048:6a167ffb86a4a16cb993473ce0726a3067163fc1; then
log -t recovery "Installing new recovery image"
applypatch MTD:boot:2324480:9a72a20a9c2f958ba586a840ed773cf8f5244183 MTD:recovery f6c2a70c5f2b02b6a49c9f5c5507a45a42e2d389 2564096 9a72a20a9c2f958ba586a840ed773cf8f5244183:/system/recovery-from-boot.p
else
log -t recovery "Recovery image already installed"
fi
395 Item.GetMetadata(input_zip)
从 META/filesystem_config.txt 中获得 system 目录下的各文件权限信息。
396 Item.Get("system").SetPermissions(script)
在脚本中增加语句,设置 system 目录下文件的权限及属主等。
398 common.CheckSize(boot_img.data, "boot.img")
检查 boot.img 文件大小是否超标.
399 common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
将boot.img 放到输出 ZIP 包中。
400 script.ShowProgress(0.2, 0)
402 script.ShowProgress(0.2, 10)
更行进度条。
403 script.WriteRawImage("boot", "boot.img")
在脚本中增加语句,将 boot.img 写到 boot 分区。
405 script.ShowProgress(0.1, 0)
更行进度条。
406 device_specific.FullOTA_InstallEnd()
Callback, 同前。
408 if OPTIONS.extra_script is not None:
409 script.AppendExtra(OPTIONS.extra_script)
如果有额外脚本,加入。
411 script.UnmountAll()
在脚本中增加语句,umount 所有分区。
412 script.AddToZip(input_zip, output_zip)
1)将前面生成的脚本输出到:META-INF/com/google/android/updater-script (对于edify)
- assert(getprop("ro.product.device") == "thedevicename" ||
-
- getprop("ro.build.product") == "theproductname");
-
- show_progress(0.500000, 0);
-
- format("MTD", "system");
-
- mount("MTD", "system", "/system");
-
- package_extract_dir("recovery", "/system");
-
- package_extract_dir("system", "/system");
-
- symlink("dumpstate", "/system/bin/dumpcrash");
-
- symlink("toolbox", "/system/bin/cat", "/system/bin/chmod",
-
- "/system/bin/chown", "/system/bin/cmp", "/system/bin/date",
-
- "/system/bin/dd", "/system/bin/df", "/system/bin/dmesg",
-
- "/system/bin/fb2bmp", "/system/bin/getevent", "/system/bin/getprop",
-
- "/system/bin/hd", "/system/bin/id", "/system/bin/ifconfig",
-
- "/system/bin/iftop", "/system/bin/insmod", "/system/bin/ioctl",
-
- "/system/bin/kill", "/system/bin/ln", "/system/bin/log",
-
- "/system/bin/ls", "/system/bin/lsmod", "/system/bin/mkdir",
-
- "/system/bin/mount", "/system/bin/mv", "/system/bin/netstat",
-
- "/system/bin/newfs_msdos", "/system/bin/notify", "/system/bin/printenv",
-
- "/system/bin/ps", "/system/bin/reboot", "/system/bin/renice",
-
- "/system/bin/rm", "/system/bin/rmdir", "/system/bin/rmmod",
-
- "/system/bin/route", "/system/bin/schedtop", "/system/bin/sendevent",
-
- "/system/bin/setconsole", "/system/bin/setprop", "/system/bin/sleep",
-
- "/system/bin/smd", "/system/bin/start", "/system/bin/stop",
-
- "/system/bin/sync", "/system/bin/top", "/system/bin/umount",
-
- "/system/bin/vmstat", "/system/bin/watchprops",
-
- "/system/bin/wipe");
-
- set_perm_recursive(0, 0, 0755, 0644, "/system");
-
- set_perm_recursive(0, 2000, 0755, 0755, "/system/bin");
-
- set_perm(0, 3003, 02755, "/system/bin/netcfg");
-
- set_perm(0, 3004, 02755, "/system/bin/ping");
-
- set_perm_recursive(1002, 1002, 0755, 0440, "/system/etc/bluez");
-
- set_perm(0, 0, 0755, "/system/etc/bluez");
-
- set_perm(1002, 1002, 0440, "/system/etc/dbus.conf");
-
- set_perm(1014, 2000, 0550, "/system/etc/dhcpcd/dhcpcd-run-hooks");
-
- set_perm(0, 2000, 0550, "/system/etc/init.goldfish.sh");
-
- set_perm(0, 0, 0544, "/system/etc/install-recovery.sh");
-
- set_perm_recursive(0, 0, 0755, 0555, "/system/etc/ppp");
-
- set_perm_recursive(0, 2000, 0755, 0755, "/system/xbin");
-
- show_progress(0.200000, 0);
-
- show_progress(0.200000, 10);
-
- assert(package_extract_file("boot.img", "/tmp/boot.img"),
-
- write_raw_image("/tmp/boot.img", "boot"),
-
- delete("/tmp/boot.img"));
-
- show_progress(0.100000, 0);
-
- unmount("/system");
2)将升级程序:OTA/bin/updater 从输入ZIP包中拷贝到输出ZIP包中的:META-INF/com/google/android/update-binary
413 WriteMetadata(metadata, output_zip)
将前面获取的metadata 写入输出包的文件中: META-INF/com/android/metadata
至此,我们就得到了一个update.zip包。可以开始升级了。
思考
1) 虽然提供了更新recovery分区的机制,但是没有看到触发该更新的语句。所以,缺省的情况是不会更新recovery分区的。大概是为了安全的原因吧。 但是,有时确实需要更新recovery 分区(比如,设备的硬件配置、分区表等发生改变),这该如何操作呢?