recovery代码分析之三:try_update_binary
来源:互联网 发布:韩顺平 php大牛班课程 编辑:程序博客网 时间:2024/05/18 01:38
http://blog.csdn.net/sjz_iron/article/details/8861773
OTA升级包路径META-INF\com\google\android中,存在着两个关键的文件:update-script和update-binary。在这两个脚本文件中,update-script记载着系统升级所需要执行的命令(如图1所示),而update-binary则是对于每条命令的解析。进入recovery模式后,系统将会执行文件中记载的命令,完成升级。
图1 update-script内容截图
由http://blog.csdn.net/liudekuan/article/details/8707044可知,在文件./bootable/recovery/install.c中定义了对应于每条命令的执行函数(如图2所示),即在recovery模式下
,系统会将这些命令转换为相应的函数去执行。而RegisterInstallFunctions函数在./bootable/recovery/update.c中被调用,在源码编译过程中,./bootable/recovery/updater目录下的代码被编译为可执行文件:out/target/product/sp8825ea/system/bin/updater,供recovery模式下系统使用。
图2 函数注册
- static int
- try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
- const ZipEntry* binary_entry =
- mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
- if (binary_entry == NULL) {
- mzCloseZipArchive(zip);
- return INSTALL_CORRUPT;
- }
- char* binary = "/tmp/update_binary";
- unlink(binary);
- int fd = creat(binary, 0755);
- if (fd < 0) {
- mzCloseZipArchive(zip);
- LOGE("Can't make %s\n", binary);
- return INSTALL_ERROR;
- }
- bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
- close(fd);
- mzCloseZipArchive(zip);
- if (!ok) {
- LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
- return INSTALL_ERROR;
- }
- int pipefd[2];
- pipe(pipefd);
- // When executing the update binary contained in the package, the
- // arguments passed are:
- //
- // - the version number for this interface
- //
- // - an fd to which the program can write in order to update the
- // progress bar. The program can write single-line commands:
- //
- // progress <frac> <secs>
- // fill up the next <frac> part of of the progress bar
- // over <secs> seconds. If <secs> is zero, use
- // set_progress commands to manually control the
- // progress of this segment of the bar
- //
- // set_progress <frac>
- // <frac> should be between 0.0 and 1.0; sets the
- // progress bar within the segment defined by the most
- // recent progress command.
- //
- // firmware <"hboot"|"radio"> <filename>
- // arrange to install the contents of <filename> in the
- // given partition on reboot.
- //
- // (API v2: <filename> may start with "PACKAGE:" to
- // indicate taking a file from the OTA package.)
- //
- // (API v3: this command no longer exists.)
- //
- // ui_print <string>
- // display <string> on the screen.
- //
- // - the name of the package zip file.
- //
- char** args = malloc(sizeof(char*) * 5);
- args[0] = binary;
- args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk
- args[2] = malloc(10);
- sprintf(args[2], "%d", pipefd[1]);
- args[3] = (char*)path;
- args[4] = NULL;
- pid_t pid = fork();
- if (pid == 0) {
- close(pipefd[0]);
- execv(binary, args);
- fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
- _exit(-1);
- }
- close(pipefd[1]);
- *wipe_cache = 0;
- char buffer[1024];
- FILE* from_child = fdopen(pipefd[0], "r");
- while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
- char* command = strtok(buffer, " \n");
- if (command == NULL) {
- continue;
- } else if (strcmp(command, "progress") == 0) {
- char* fraction_s = strtok(NULL, " \n");
- char* seconds_s = strtok(NULL, " \n");
- float fraction = strtof(fraction_s, NULL);
- int seconds = strtol(seconds_s, NULL, 10);
- ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION),
- seconds);
- } else if (strcmp(command, "set_progress") == 0) {
- char* fraction_s = strtok(NULL, " \n");
- float fraction = strtof(fraction_s, NULL);
- ui_set_progress(fraction);
- } else if (strcmp(command, "ui_print") == 0) {
- char* str = strtok(NULL, "\n");
- if (str) {
- ui_print("%s", str);
- } else {
- ui_print("\n");
- }
- } else if (strcmp(command, "wipe_cache") == 0) {
- *wipe_cache = 1;
- } else {
- LOGE("unknown command [%s]\n", command);
- }
- }
- fclose(from_child);
- int status;
- waitpid(pid, &status, 0);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
- return INSTALL_ERROR;
- }
- return INSTALL_SUCCESS;
- }
代码段1 try_update_binary函数
./bootable/recovery/install.c中的try_update_binary函数,是真正实现读取升级包中的脚本文件并执行相应的函数的地方。在此函数中,通过调用fork函数创建出一个子进程(代码第72行),在子进程中开始读取并执行升级脚本文件(代码73-78)。在此需要注意的是函数fork的用法,fork被调用一次,将做两次返回,在父进程中返回的是子进程的进程ID,为正数;而在子进程中,则返回0。因此代码73-78事实是子进程中所进行的操作,即execv(binary, args)。子进程创建成功后,开始执行升级代码,并通过管道与父进程交互(代码27-28,创建管道,并将pipefd[1]作为参数传递给子进程,子进程则将相关信息写入到此管道描述符中);而父进程则通过读取子进程传递过来的信息更新UI(代码84-114)。
- recovery代码分析之三:try_update_binary
- recovery代码分析之三:try_update_binary
- recovery代码分析之二
- recovery代码分析之二
- try_update_binary
- try_update_binary
- Android Recovery 代码分析
- Android Recovery 代码分析
- Android Recovery 代码分析
- Recovery代码分析之一
- Recovery代码分析之一
- Android Recoveryの代码分析
- Android Recoveryの代码分析
- Android Recovery 的代码分析
- Android Recovery 的代码分析
- Android Recovery 的代码分析
- Android Recovery 的代码分析
- recovery ui界面代码分析
- Docker 在Centos 6.5 X64下安装
- gdb调试
- dropzone.js点击删除图片按钮后只执行action不跳转到新的jsp页面,也不刷新本页面
- 面向服务的架构SOA
- 日经社説 20150303 TPP決着へ米政権と議会は調整急げ
- recovery代码分析之三:try_update_binary
- 关于angularJS 框架优化(按需加载),性能提升问题(grunt)。
- 拨打紧急电话,在通话界面会快速闪现正常通话界面的人头图片
- Android网络之简单服务器与客户端双向接收
- C/C++堆和栈的区别
- ajax加载数据动画
- Android activity 去掉标题栏的三种方法
- 宏的副作用和do{}while(0)的说明
- csdn如何转载别人的文章