Android OTA 升级(五):updater .

一、简介

      前面分析的OTA升级的各部分代码都是在搭一个舞台,而主角现在终于登场,它就是updater。Google的代码架构设计非常好,各部分尽量松耦合。前面介绍升级脚本时,可知有两种类型的脚本,amend & edify(Amend脚本<update-script>在Android 1.5中已经被废除,只保留了Edify脚本<updater-script>). 他们各自对应一个updater. 这里,我们主要关注新的edify的updater.

       Updater可以作为学习解释器/编译器的同学一个很好的实例,但是我们只关心产品化相关的内容,所以并不去深究lex/yacc相关的东西。

二、入口函数main

bootable/recovery/updater/updater.c

// 这里定义脚本的位置,注释说明本updater支持edify格式的脚本。   
  1. // Where in the package we expect to find the edify script to execute.   
  2. // (Note it's "updateR-script", not the older "update-script".)   
  3. #define SCRIPT_NAME "META-INF/com/google/android/updater-script"   
  4.   
  5. int main(int argc, char** argv) {  
  6.     // Various things log information to stdout or stderr more or less   
  7.     // at random.  The log file makes more sense if buffering is   
  8.     // turned off so things appear in the right order.   
  9.     setbuf(stdout, NULL);  
  10.     setbuf(stderr, NULL);  
  11.   
  12.     if (argc != 4) {  
  13.         fprintf(stderr, "unexpected number of arguments (%d)\n", argc);  
  14.         return 1;  
  15.     }  
  16.     // 获取 version 参数。   
  17.     char* version = argv[1];  
  18.     if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||  
  19.         version[1] != '\0') {  
  20.         // We support version 1, 2, or 3.   
  21.         fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "  
  22.                         "got %s\n",  
  23.                 argv[1]);  
  24.         return 2;  
  25.     }  
  26.   
  27.     // 获取命令管道(用于图形显示等,见前篇)   
  28.     // Set up the pipe for sending commands back to the parent process.   
  29.     int fd = atoi(argv[2]);  
  30.     FILE* cmd_pipe = fdopen(fd, "wb");  
  31.     setlinebuf(cmd_pipe);  
  32.   
  33.     // Extract the script from the package.   
  34.   
  35.     char* package_data = argv[3];  
  36.     ZipArchive za;  
  37.     int err;  
  38.     err = mzOpenZipArchive(package_data, &za);  
  39.     if (err != 0) {  
  40.         fprintf(stderr, "failed to open package %s: %s\n",  
  41.                 package_data, strerror(err));  
  42.         return 3;  
  43.     }  
  44.   
  45.    // 读入脚本 META-INF/com/google/android/updater-script   
  46.     const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);  
  47.     if (script_entry == NULL) {  
  48.         fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data);  
  49.         return 4;  
  50.     }  
  51.   
  52.     char* script = malloc(script_entry->uncompLen+1);  
  53.     if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {  
  54.         fprintf(stderr, "failed to read script from package\n");  
  55.         return 5;  
  56.     }  
  57.     script[script_entry->uncompLen] = '\0';  
  58.   
  59.     // Configure edify's functions.   
  60.     // 注册语句处理函数   
  61.     RegisterBuiltins();  
  62.     RegisterInstallFunctions();  
  63.     RegisterDeviceExtensions();  
  64.     FinishRegistration();  
  65.   
  66.     // Parse the script.   
  67.     // 调用yy* 库函数解析脚本。   
  68.     Expr* root;  
  69.     int error_count = 0;  
  70.     yy_scan_string(script);  
  71.     int error = yyparse(&root, &error_count);  
  72.     if (error != 0 || error_count > 0) {  
  73.         fprintf(stderr, "%d parse errors\n", error_count);  
  74.         return 6;  
  75.     }  
  76.   
  77.     // Evaluate the parsed script.   
  78.     UpdaterInfo updater_info;  
  79.     updater_info.cmd_pipe = cmd_pipe;  
  80.     updater_info.package_zip = &za;  
  81.     updater_info.version = atoi(version);  
  82.   
  83.     State state;  
  84.     state.cookie = &updater_info;  
  85.     state.script = script;  
  86.     state.errmsg = NULL;  
  87.   
  88.     // 解释执行脚本。 核心函数是 Evaluate。它会调用其他callback函数,而这些callback函数   
  89.     // 又会调用Evaluate去解析不同的脚本片段。从而实现一个简单的解释器   
  90.     char* result = Evaluate(&state, root);  
  91.     if (result == NULL) {  
  92.         if (state.errmsg == NULL) {  
  93.             fprintf(stderr, "script aborted (no error message)\n");  
  94.             fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");  
  95.         } else {  
  96.             fprintf(stderr, "script aborted: %s\n", state.errmsg);  
  97.             char* line = strtok(state.errmsg, "\n");  
  98.             while (line) {  
  99.                 fprintf(cmd_pipe, "ui_print %s\n", line);  
  100.                 line = strtok(NULL, "\n");  
  101.             }  
  102.             fprintf(cmd_pipe, "ui_print\n");  
  103.         }  
  104.         free(state.errmsg);  
  105.         return 7;  
  106.     } else {  
  107.         fprintf(stderr, "script result was [%s]\n", result);  
  108.         free(result);  
  109.     }  
  110.   
  111.     if (updater_info.package_zip) {  
  112.         mzCloseZipArchive(updater_info.package_zip);  
  113.     }  
  114.     free(script);  
  115.   
  116.     return 0;  
  117. }  

还没开始,就结束了。代码非常简单,因为细节隐藏在那些callback函数里。我们看一下。
三、callback函数

1)  RegisterBuiltins

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

这些语句控制执行流程。
2) RegisterInstallFunctions

 
void RegisterInstallFunctions() {  
  1.     RegisterFunction("mount", MountFn);  
  2.     RegisterFunction("is_mounted", IsMountedFn);  
  3.     RegisterFunction("unmount", UnmountFn);  
  4.     RegisterFunction("format", FormatFn);  
  5.     RegisterFunction("show_progress", ShowProgressFn);  
  6.     RegisterFunction("set_progress", SetProgressFn);  
  7.     RegisterFunction("delete", DeleteFn);  
  8.     RegisterFunction("delete_recursive", DeleteFn);  
  9.     RegisterFunction("package_extract_dir", PackageExtractDirFn);  
  10.     RegisterFunction("package_extract_file", PackageExtractFileFn);  
  11.     RegisterFunction("retouch_binaries", RetouchBinariesFn);  
  12.     RegisterFunction("undo_retouch_binaries", UndoRetouchBinariesFn);  
  13.     RegisterFunction("symlink", SymlinkFn);  
  14.     RegisterFunction("set_perm", SetPermFn);  
  15.     RegisterFunction("set_perm_recursive", SetPermFn);  
  16.   
  17.     RegisterFunction("getprop", GetPropFn);  
  18.     RegisterFunction("file_getprop", FileGetPropFn);  
  19.     RegisterFunction("write_raw_image", WriteRawImageFn);  
  20.     RegisterFunction("write_raw_parameter_image", WriteRawParameterImageFn);  
  21.     RegisterFunction("clear_misc_command", ClearMiscCommandFn);  
  22.   
  23.     RegisterFunction("apply_patch", ApplyPatchFn);  
  24.     RegisterFunction("apply_patch_check", ApplyPatchCheckFn);  
  25.     RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);  
  26.   
  27.     RegisterFunction("read_file", ReadFileFn);  
  28.     RegisterFunction("sha1_check", Sha1CheckFn);  
  29.   
  30.     RegisterFunction("wipe_cache", WipeCacheFn);  
  31.   
  32.     RegisterFunction("ui_print", UIPrintFn);  
  33.   
  34.     RegisterFunction("run_program", RunProgramFn);  
  35. }  
 
    这些语句执行各种功能。基本上,我们只需要知道用法就可以了。值得注意的是,run_program原语允许我们去执行自定义程序,这应该足够满足我们的个性化需求了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值