您的位置:首页 > 移动开发 > Android开发

Android OTA 升级之五:updater

2013-11-12 13:35 357 查看
作者: 宋立新
Email:zjujoe@yahoo.com

前言

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

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

入口函数 main

(from: bootable/recovery/updater/updater.c)

62
// Where in the package we expect to find the edify script to execute.
63
// (Note it's "updateR-script", not the older "update-script".)
64 #define
SCRIPT_NAME
"META-INF/com/google/android/updater-script"
65

这里定义脚本的位置,注释说明本updater支持edify格式的脚本。

66 int
main(int
argc, char**
argv) {
67
// Various things log information to stdout or stderr more or less
68
// at random. The log file makes more sense if buffering is
69
// turned off so things appear in the right order.
70
setbuf(stdout,
NULL);
71
setbuf(stderr,
NULL);
72

73 if (argc != 4) {
74
fprintf(stderr,
"unexpected number of arguments (%d)/n",
argc);
75 return 1;
76 }
77

78 char*
version =
argv[1];
79 if ((version[0]
!= '1' &&
version[0] != '2' &&
version[0] != '3') ||
80
version[1] !=
'/0') {
81
// We support version 1, 2, or 3.
82
fprintf(stderr,
"wrong updater binary API; expected 1, 2, or 3; "
83 "got %s/n",
84
argv[1]);
85 return 2;
86 }
87

获取 version 参数。
88
// Set up the pipe for sending commands back to the parent process.
89

90 int
fd =
atoi(argv[2]);
91
FILE* cmd_pipe =
fdopen(fd,
"wb");
92
setlinebuf(cmd_pipe);
93

获取命令管道(用于图形显示等,见前篇)

94
// Extract the script from the package.
95

96 char* package_data =
argv[3];
97
ZipArchive za;
98 int
err;
99
err =
mzOpenZipArchive(package_data, &za);
100 if (err != 0) {
101
fprintf(stderr,
"failed to open package %s: %s/n",
102 package_data,
strerror(err));
103 return 3;
104 }
105

106 const
ZipEntry* script_entry =
mzFindZipEntry(&za,
SCRIPT_NAME);
107 if (script_entry ==
NULL) {
108
fprintf(stderr,
"failed to find %s in %s/n",
SCRIPT_NAME, package_data);
109 return 4;
110 }
111

112 char*
script =
malloc(script_entry->uncompLen+1);
113 if (!mzReadZipEntry(&za,
script_entry,
script, script_entry->uncompLen)) {
114
fprintf(stderr,
"failed to read script from package/n");
115 return 5;
116 }
117
script[script_entry->uncompLen] =
'/0';
118

读入脚本 META-INF/com/google/android/updater-script

119
// Configure edify's functions.
120

121

RegisterBuiltins();
122

RegisterInstallFunctions();
123 RegisterDeviceExtensions();
124

FinishRegistration();
125

注册语句处理函数
126
// Parse the script.
127

128
Expr*
root;
129 int
error_count = 0;
130
yy_scan_string(script);
131 int
error =
yyparse(&root, &error_count);
132 if (error != 0 ||
error_count > 0) {
133
fprintf(stderr,
"%d parse errors/n",
error_count);
134 return 6;
135 }
136

调用yy* 库函数解析脚本。
137
// Evaluate the parsed script.
138

139
UpdaterInfo updater_info;
140 updater_info.cmd_pipe = cmd_pipe;
141 updater_info.package_zip = &za;
142 updater_info.version
= atoi(version);
143

144
State
state;
145
state.cookie = &updater_info;
146
state.script =
script;
147
state.errmsg =
NULL;
148

149 char*
result =
Evaluate(&state,
root);
150 if (result ==
NULL) {
151 if (state.errmsg
== NULL) {
152
fprintf(stderr,
"script aborted (no error message)/n");
153
fprintf(cmd_pipe,
"ui_print script aborted (no error message)/n");
154 } else {
155
fprintf(stderr,
"script aborted: %s/n",
state.errmsg);
156 char*
line =
strtok(state.errmsg,
"/n");
157 while (line)
{
158 fprintf(cmd_pipe,
"ui_print %s/n",
line);
159
line =
strtok(NULL,
"/n");
160 }
161
fprintf(cmd_pipe,
"ui_print/n");
162 }
163
free(state.errmsg);
164 return 7;
165 } else {
166
fprintf(stderr,
"script result was [%s]/n",
result);
167
free(result);
168 }
解释执行脚本。 核心函数是
Evaluate。它会调用其他callback函数,而这些callback函数又会调用Evaluate去解析不同的脚本片段。从而实现一个简单的解释器。
169

170

mzCloseZipArchive(&za);
171
free(script);
172

173 return 0;
174 }

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

RegisterBuiltins

415 void RegisterBuiltins() {

416     RegisterFunction("ifelse", IfElseFn);

417     RegisterFunction("abort", AbortFn);

418     RegisterFunction("assert", AssertFn);

419     RegisterFunction("concat", ConcatFn);

420     RegisterFunction("is_substring", SubstringFn);

421     RegisterFunction("stdout", StdoutFn);

422     RegisterFunction("sleep", SleepFn);

423

424     RegisterFunction("less_than_int", LessThanIntFn);

425     RegisterFunction("greater_than_int", GreaterThanIntFn);

426 }

这些语句控制执行流程。

RegisterInstallFunctions

1036

1037 void RegisterInstallFunctions() {

1038     RegisterFunction("mount", MountFn);

1039     RegisterFunction("is_mounted", IsMountedFn);

1040     RegisterFunction("unmount", UnmountFn);

1041     RegisterFunction("format", FormatFn);

1042     RegisterFunction("show_progress", ShowProgressFn);

1043     RegisterFunction("set_progress", SetProgressFn);

1044     RegisterFunction("delete", DeleteFn);

1045     RegisterFunction("delete_recursive", DeleteFn);

1046     RegisterFunction("package_extract_dir", PackageExtractDirFn);

1047     RegisterFunction("package_extract_file", PackageExtractFileFn);

1048     RegisterFunction("symlink", SymlinkFn);

1049     RegisterFunction("set_perm", SetPermFn);

1050     RegisterFunction("set_perm_recursive", SetPermFn);

1051

1052     RegisterFunction("getprop", GetPropFn);

1053     RegisterFunction("file_getprop", FileGetPropFn);

1054     RegisterFunction("write_raw_image", WriteRawImageFn);

1055

1056     RegisterFunction("apply_patch", ApplyPatchFn);

1057     RegisterFunction("apply_patch_check", ApplyPatchCheckFn);

1058     RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);

1059

1060     RegisterFunction("read_file", ReadFileFn);

1061     RegisterFunction("sha1_check", Sha1CheckFn);

1062

1063     RegisterFunction("ui_print", UIPrintFn);

1064

1065     RegisterFunction("run_program", RunProgramFn);

1066 }

这些语句执行各种功能。基本上,我们只需要知道用法就可以了。值得注意的是,run_program原语允许我们去执行自定义程序,这应该足够满足我们的个性化需求了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: