Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1373772
  • 博文数量: 478
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4833
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-28 11:12
文章分类

全部博文(478)

文章存档

2019年(1)

2018年(27)

2017年(21)

2016年(171)

2015年(258)

我的朋友

分类: Android平台

2015-08-18 09:46:27

 

Android OTA 升级(五):updater

分类: Android OTA 2696人阅读 评论(1) 收藏 举报

一、简介

      前面分析的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

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

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

1)  RegisterBuiltins

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

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

  1. void RegisterInstallFunctions() {  
  2.     RegisterFunction("mount", MountFn);  
  3.     RegisterFunction("is_mounted", IsMountedFn);  
  4.     RegisterFunction("unmount", UnmountFn);  
  5.     RegisterFunction("format", FormatFn);  
  6.     RegisterFunction("show_progress", ShowProgressFn);  
  7.     RegisterFunction("set_progress", SetProgressFn);  
  8.     RegisterFunction("delete", DeleteFn);  
  9.     RegisterFunction("delete_recursive", DeleteFn);  
  10.     RegisterFunction("package_extract_dir", PackageExtractDirFn);  
  11.     RegisterFunction("package_extract_file", PackageExtractFileFn);  
  12.     RegisterFunction("retouch_binaries", RetouchBinariesFn);  
  13.     RegisterFunction("undo_retouch_binaries", UndoRetouchBinariesFn);  
  14.     RegisterFunction("symlink", SymlinkFn);  
  15.     RegisterFunction("set_perm", SetPermFn);  
  16.     RegisterFunction("set_perm_recursive", SetPermFn);  
  17.   
  18.     RegisterFunction("getprop", GetPropFn);  
  19.     RegisterFunction("file_getprop", FileGetPropFn);  
  20.     RegisterFunction("write_raw_image", WriteRawImageFn);  
  21.     RegisterFunction("write_raw_parameter_image", WriteRawParameterImageFn);  
  22.     RegisterFunction("clear_misc_command", ClearMiscCommandFn);  
  23.   
  24.     RegisterFunction("apply_patch", ApplyPatchFn);  
  25.     RegisterFunction("apply_patch_check", ApplyPatchCheckFn);  
  26.     RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);  
  27.   
  28.     RegisterFunction("read_file", ReadFileFn);  
  29.     RegisterFunction("sha1_check", Sha1CheckFn);  
  30.   
  31.     RegisterFunction("wipe_cache", WipeCacheFn);  
  32.   
  33.     RegisterFunction("ui_print", UIPrintFn);  
  34.   
  35.     RegisterFunction("run_program", RunProgramFn);  
  36. }  

    这些语句执行各种功能。基本上,我们只需要知道用法就可以了。值得注意的是,run_program原语允许我们去执行自定义程序,这应该足够满足我们的个性化需求了。

 

 

 

 


 


 

 

 

阅读(893) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~