设计细节
(一) 文件权限
META/filesystem_config.txt
system 0 0 755 system/fonts 0 0 755 system/fonts/DroidSans-Bold.ttf 0 0 644 system/fonts/DroidSansDevanagari-Regular.ttf 0 0 644 system/fonts/AndroidClock.ttf 0 0 644 system/fonts/DroidSerif-Bold.ttf 0 0 644 system/fonts/Roboto-Bold.ttf 0 0 644 system/fonts/Lohit-Kannada.ttf 0 0 644 system/fonts/RobotoCondensed-Regular.ttf 0 0 644 system/fonts/DroidSerif-Regular.ttf 0 0 644 system/fonts/DroidSerif-Italic.ttf 0 0 644 system/fonts/Lohit-Telugu.ttf 0 0 644 …… |
该文件由fs_config工具生成。
升级命令set_perm_recursive能够递归设置目录下的所有文件权限,利用它能够提高效率(至少减少了升级脚本的行数)。这里的思想是寻找目录下最常见的权限设置,先通过set_perm_recursive设置,然后处理例外的情形。
在遍历目录时不处理符号链接,其权限都是root、root、777。
在增量升级的时候,权限设置会全部重新做一遍。
(二) 增量算法
- 构建文件字典(路径->File):source_data、target_data
- 对source_data的文件,
- 构建path:matching_file_cache
- 如果目标文件集中没有路径相同文件,增加file、sha1映射
- 对每个target_data中的文件
- 在matching_file_cache寻找匹配文件,
- 如果找到path匹配,返回之
- 如果update_rename_support为False,返回None
- 如果文件小于1K,返回None
- 如果sha1匹配,并且没有绑定,返回之
- 如果file(文件名)匹配,并且没有重命名绑定,返回之
- 返回None
- 如果找到匹配,但是路径不一样,加入到重命名组renames(字典:源文件路径->目标File),增加重命名绑定
- 如果没有找到匹配,加入到覆盖组:verbatim_targets(二元组:目标文件名,文件大小)
- 如果找到匹配,但是sha1不一样,加入到差异组:diffs(数组:Difference)
- 如果找到匹配,并且sha1一样,直接pass
- 计算差异组的差异文件
- 对每个差异组文件
- 如果差异文件大小大于目标文件大小的一定比例(patch_threshold),移动到覆盖组
- 否则,移动到补丁组:patch_list(五元组:源文件名,目标文件File,源文件File,目标文件大小,差异文件大小),更新最大源文件大小:largest_source_size
- 升级顺序
- 补丁组
- 覆盖组
- 重命名组
从目标文件的角度总结一下:
- 如果有path匹配
- 如果sha1不一样,差异组
- 如果差异太大,覆盖组
- 否则补丁组
- 否则,不加入任何组
- 如果有sha1匹配,重命名组
- 如果file匹配,重命名组,同时加入差异组
- 如果差异太大,覆盖组
- 否则补丁组
- 如果没有匹配,覆盖组
加入覆盖组,目标文件输出到zip,加入补丁组,差异文件输出到zip。
如果同时在补丁组和重命名组,先做补丁,再重命名。
(三) recovery升级
Recovery升级是在正常升级完成之后才执行的,目的是保证至少有一个可用系统存在。
Recovery的升级文件是recovery分区相对与boot分区的补丁文件。通过打补丁的方式升级,因为这两个分区(或者img文件)包含很多相同内容,所以这种方式升级可以减少升级包的大小。
在主系统init.rc中,有启动recovery升级的服务定义:
service flash_recovery /system/etc/install-recovery.sh class main oneshot |
该shell脚本在函数MakeRecoveryPatch中生成,内容为:
#!/system/bin/sh if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then log -t recovery "Installing new recovery image" applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p else log -t recovery "Recovery image already installed" fi |
(四) 符号链接
符号链接收集在二元数组(链接目标名,链接名)中,创建链接时以链接目标分组,同时创建到同一个目标的多个链接。
(五) 升级进度
升级进度有两个层次的控制,show_progress(frac, dur)控制进度在dur秒内增加frac。如果dur为0,那么由set_progress(frac)在上一个show_progress划定的块里面更新进度。
全量更新:
ShowProgress(0.5, 0) —— 解压system、recovery
ShowProgress(0.2, 0) —— 设置文件权限
ShowProgress(0.2, 10) —— 更新boot分区
ShowProgress(0.1, 0) —— 其他
增量更新:
ShowProgress(0.1, 0) —— 校验文件sha1,删除文件
SetProgress(so_far / total_verify_size)
ShowProgress(0.8, 0) —— 打补丁
SetProgress(so_far / total_patch_size)
ShowProgress(0.1, 10) —— 创建符号链接,重命名文件
(六) 签名
密钥来源:
- -k <package_key>(OPTIONS.package_key)
- META/misc_info.txt(OPTIONS.info_dict[“default_system_dev_certificate”])
- “build/target/product/security/testkey”
公钥扩展名: .x509.pem
私钥扩展名: .pk8
签名程序: signapk.jar -w <公钥> <私钥> <输入文件> <输出文件>