Original article: http://blog.csdn.net/zjujoe/article/details/6251747
Android OTA Update 5: Updater
Author: Song Lixin
Email: zjujoe@yahoo.com
Preface
It can be said that all the sections of the OTA update code analyzed above are on the stage, and the main character is now on the stage, it is Updater. google's code architecture is well designed, and each part should be loosely coupled. When we first introduced the upgrade script, we know there are two types of scripts, amend & edify. They each correspond to an Updater. Here, we mainly focus on the Updater of the new edify.
Updater can be used as a good example for students who are learning interpreters/compilers. But we only care about productization-related content, so we do not go into lex/YACC-related details.
Main
(From: bootable/recovery/Updater. c)
62// Where in the package we recommend CT 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
The location of the script is defined here. Note that this Updater supports the script in edify format.
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
Obtain the version parameter.
88// Set up the pipe for sending commands back to the parent process.
89
90 int FD = atoi (argv [2]);
91 file * pai_pipe = fdopen (FD,"WB");
92 setlinebuf (pai_pipe );
93
Obtain the command pipeline (for graphic display, see the previous article)
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
Read scriptMETA-INF/COM/Google/Android/Updater-script
119// Configure edify's functions.
120
121 registerbuiltins ();
122 registerinstallfunctions ();
123 registerdeviceextensions ();
124 finishregistration ();
125
Register statement processing functions
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
Call the YY * library function parsing script.
137// Evaluate the parsed script.
138
139 updaterinfo updater_info;
140 updater_info.pai_pipe = pai_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 (pai_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 (pai_pipe,"Ui_print % S/N", Line );
159 line = strtok (null,"/N");
160}
161 fprintf (pai_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}
Explain the execution script. The core function is evaluate. It calls other callback functions, and these callback functions call evaluate to parse different script fragments. To implement a simple interpreter.
169
170 mzcloseziparchive (& za );
171 free (SCRIPT );
172
173 return 0;
174}
It's over before it starts. The code is very simple, because the details are hidden in those callback functions. Let's take a look.
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 }
These statements control the execution process.
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 }
These statements execute various functions. Basically, we only need to know the usage. It is worth noting that the run_program primitive allows us to execute custom programs, which should meet our personalized needs.