简介

可以说,前面分析的OTA升级的各部分代码都是在搭一个舞台,而主角现在终于登场,它就是updater. Google的代码架构设计非常好,各部分尽量松耦合。前面介绍升级脚本时,可知有两种类型的脚本,amend& edify. 他们各自对应一个updater. 这里,我们主要关注新的edify的updater.

源码文件

tree

1
2
3
4
5
6
7
8
.
├── Android.mk
├── blockimg.c
├── blockimg.h
├── install.c
├── install.h
├── updater.c
└── updater.h

入口函数 main

  1. 处理version 参数
  2. 获取命令管道

    Set up the pipe for sending commands back to the parent process.

  3. 读入脚本

    mzFindZipEntry(&za, SCRIPT_NAME);

  4. 注册语句处理函数

    Configure edify’s functions.

  5. 解析脚本命令

    Parse the script.

  6. 执行脚本

    核心函数是 Evaluate。它会调用其他callback函数,而这些callback函数又会调用Evaluate去解析不同的脚本片段。

主流程的代码非常简单,因为细节隐藏在那些 callback 函数里。

callback函数

  1. RegisterBuiltins
1
2
3
4
5
6
7
8
9
10
11
void RegisterBuiltins() {
RegisterFunction("ifelse", IfElseFn);
RegisterFunction("abort", AbortFn);
RegisterFunction("assert", AssertFn);
RegisterFunction("concat", ConcatFn);
RegisterFunction("is_substring", SubstringFn);
RegisterFunction("stdout", StdoutFn);
RegisterFunction("sleep", SleepFn);
RegisterFunction("less_than_int", LessThanIntFn);
RegisterFunction("greater_than_int", GreaterThanIntFn);
}
  1. RegisterInstallFunctions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    void RegisterInstallFunctions() {
    RegisterFunction("mount", MountFn);
    RegisterFunction("is_mounted", IsMountedFn);
    RegisterFunction("unmount", UnmountFn);
    RegisterFunction("format", FormatFn);
    RegisterFunction("show_progress", ShowProgressFn);
    RegisterFunction("set_progress", SetProgressFn);
    RegisterFunction("delete", DeleteFn);
    RegisterFunction("delete_recursive", DeleteFn);
    RegisterFunction("package_extract_dir", PackageExtractDirFn);
    RegisterFunction("package_extract_file", PackageExtractFileFn);
    RegisterFunction("symlink", SymlinkFn);
    // Usage:
    // set_metadata("filename", "key1", "value1", "key2", "value2", ...)
    // Example:
    // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
    RegisterFunction("set_metadata", SetMetadataFn);
    // Usage:
    // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
    // Example:
    // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
    RegisterFunction("set_metadata_recursive", SetMetadataFn);
    RegisterFunction("getprop", GetPropFn);
    RegisterFunction("file_getprop", FileGetPropFn);
    RegisterFunction("write_raw_image", WriteRawImageFn);
    RegisterFunction("write_raw_parameter_image", WriteRawParameterImageFn);
    RegisterFunction("clear_misc_command", ClearMiscCommandFn);
    RegisterFunction("apply_patch", ApplyPatchFn);
    RegisterFunction("apply_patch_check", ApplyPatchCheckFn);
    RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
    RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
    RegisterFunction("read_file", ReadFileFn);
    RegisterFunction("sha1_check", Sha1CheckFn);
    RegisterFunction("rename", RenameFn);
    RegisterFunction("wipe_cache", WipeCacheFn);
    RegisterFunction("ui_print", UIPrintFn);
    RegisterFunction("run_program", RunProgramFn);
    RegisterFunction("reboot_now", RebootNowFn);
    RegisterFunction("get_stage", GetStageFn);
    RegisterFunction("set_stage", SetStageFn);
    RegisterFunction("enable_reboot", EnableRebootFn);
    RegisterFunction("tune2fs", Tune2FsFn);
    }
  2. RegisterBlockImageFunctions

1
2
3
4
5
void RegisterBlockImageFunctions() {
RegisterFunction("block_image_verify", BlockImageVerifyFn);
RegisterFunction("block_image_update", BlockImageUpdateFn);
RegisterFunction("range_sha1", RangeSha1Fn);
}
  1. FinishRegistration

    1
    2
    3
    void FinishRegistration() {
    qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
    }