Android系统Recovery工作原理之使用updatezip升级过程分析七.docx

上传人:b****8 文档编号:10478613 上传时间:2023-02-13 格式:DOCX 页数:5 大小:18.16KB
下载 相关 举报
Android系统Recovery工作原理之使用updatezip升级过程分析七.docx_第1页
第1页 / 共5页
Android系统Recovery工作原理之使用updatezip升级过程分析七.docx_第2页
第2页 / 共5页
Android系统Recovery工作原理之使用updatezip升级过程分析七.docx_第3页
第3页 / 共5页
Android系统Recovery工作原理之使用updatezip升级过程分析七.docx_第4页
第4页 / 共5页
Android系统Recovery工作原理之使用updatezip升级过程分析七.docx_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Android系统Recovery工作原理之使用updatezip升级过程分析七.docx

《Android系统Recovery工作原理之使用updatezip升级过程分析七.docx》由会员分享,可在线阅读,更多相关《Android系统Recovery工作原理之使用updatezip升级过程分析七.docx(5页珍藏版)》请在冰豆网上搜索。

Android系统Recovery工作原理之使用updatezip升级过程分析七.docx

Android系统Recovery工作原理之使用updatezip升级过程分析七

Android系统Recovery工作原理之使用update.zip升级过程分析(七)

[置顶]

Android系统Recovery工作原理之使用update.zip升级过程分析(七)---Recovery服务的核心install_package函数分类:

Andriod

2012-04-1613:

55

4480人阅读

评论(3)

收藏

举报

android工作commandnullpathfile

Android系统Recovery工作原理之使用update.zip升级过程分析(七)---Recovery服务的核心install_package函数一、Recovery服务的核心install_package(升级update.zip特有)和Recovery服务中的wipe_data、wipe_cache不同,install_package()是升级update.zip特有的一部分,也是最核心的部分。

在这一步才真正开始对我们的update.zip包进行处理。

下面就开始分析这一部分。

还是先看图例:

这一部分的源码文件位于:

/gingerbread0919/bootable/recovery/install.c。

这是一个没有main函数的源码文件,还是把源码先贴出来如下:

[cpp]viewplaincopy?

/**Copyright(C)2007TheAndroidOpenSourceProject**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethisfileexceptincompliancewiththeLicense.*YoumayobtainacopyoftheLicenseat**http:

//www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,software*distributedundertheLicenseisdistributedonan"ASIS"BASIS,*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.*SeetheLicenseforthespecificlanguagegoverningpermissionsand*limitationsundertheLicense.*/#include<ctype.h>#include<errno.h>#include<fcntl.h>#include<limits.h>#include<sys/stat.h>#include<sys/wait.h>#include<unistd.h>#include"common.h"#include"install.h"#include"mincrypt/rsa.h"#include"minui/minui.h"#include"minzip/SysUtil.h"#include"minzip/Zip.h"#include"mtdutils/mounts.h"#include"mtdutils/mtdutils.h"#include"roots.h"#include"verifier.h"#defineASSUMED_UPDATE_BINARY_NAME"META-INF/com/google/android/update-binary"#definePUBLIC_KEYS_FILE"/res/keys"//Ifthepackagecontainsanupdatebinary,extractitandrunit.staticinttry_update_binary(constchar*path,ZipArchive*zip){constZipEntry*binary_entry=mzFindZipEntry(zip,ASSUMED_UPDATE_BINARY_NAME);if(binary_entry==NULL){mzCloseZipArchive(zip);returnINSTALL_CORRUPT;}char*binary="/tmp/update_binary";unlink(binary);intfd=creat(binary,0755);if(fd<0){mzCloseZipArchive(zip);LOGE("Can'tmake%s\n",binary);return1;}boolok=mzExtractZipEntryToFile(zip,binary_entry,fd);close(fd);mzCloseZipArchive(zip);if(!

ok){LOGE("Can'tcopy%s\n",ASSUMED_UPDATE_BINARY_NAME);return1;}intpipefd[2];pipe(pipefd);//Whenexecutingtheupdatebinarycontainedinthepackage,the//argumentspassedare:

////-theversionnumberforthisinterface////-anfdtowhichtheprogramcanwriteinordertoupdatethe//progressbar.Theprogramcanwritesingle-linecommands:

////progress<frac><secs>//fillupthenext<frac>partofoftheprogressbar//over<secs>seconds.If<secs>iszero,use//set_progresscommandstomanuallycontrolthe//progressofthissegmentofthebar////set_progress<frac>//<frac>shouldbebetween0.0and1.0;setsthe//progressbarwithinthesegmentdefinedbythemost//recentprogresscommand.////firmware<"hboot"|"radio"><filename>//arrangetoinstallthecontentsof<filename>inthe//givenpartitiononreboot.////(APIv2:

<filename>maystartwith"PACKAGE:

"to//indicatetakingafilefromtheOTApackage.)////(APIv3:

thiscommandnolongerexists.)////ui_print<string>//display<string>onthescreen.////-thenameofthepackagezipfile.//char**args=malloc(sizeof(char*)*5);args[0]=binary;args[1]=EXPAND(RECOVERY_API_VERSION);//definedinAndroid.mkargs[2]=malloc(10);sprintf(args[2],"%d",pipefd[1]);args[3]=(char*)path;args[4]=NULL;pid_tpid=fork();if(pid==0){close(pipefd[0]);execv(binary,args);fprintf(stdout,"E:

Can'trun%s(%s)\n",binary,strerror(errno));_exit(-1);}close(pipefd[1]);charbuffer[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;}elseif(strcmp(command,"progress")==0){char*fraction_s=strtok(NULL,"\n");char*seconds_s=strtok(NULL,"\n");floatfraction=strtof(fraction_s,NULL);intseconds=strtol(seconds_s,NULL,10);ui_show_progress(fraction*(1-VERIFICATION_PROGRESS_FRACTION),seconds);}elseif(strcmp(command,"set_progress")==0){char*fraction_s=strtok(NULL,"\n");floatfraction=strtof(fraction_s,NULL);ui_set_progress(fraction);}elseif(strcmp(command,"ui_print")==0){char*str=strtok(NULL,"\n");if(str){ui_print("%s",str);}else{ui_print("\n");}}else{LOGE("unknowncommand[%s]\n",command);}}fclose(from_child);intstatus;waitpid(pid,&status,0);if(!

WIFEXITED(status)||WEXITSTATUS(status)!

=0){LOGE("Errorin%s\n(Status%d)\n",path,WEXITSTATUS(status));returnINSTALL_ERROR;}returnINSTALL_SUCCESS;}//Readsafilecontainingoneormorepublickeysasproducedby//DumpPublicKey:

thisisanRSAPublicKeystructasitwouldappear//asaCsourceliteral,eg:

////"{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"////(Notethatthebracesandcommasinthisexampleareactual//characterstheparserexpectstofindinthefile;theellipses//indicatemorenumbersomittedfromthisexample.)////Thefilemaycontainmultiplekeysinthisformat,separatedby//commas.Thelastkeymustnotbefollowedbyacomma.////ReturnsNULLifthefilefailedtoparse,orifitcontainzerokeys.staticRSAPublicKey*load_keys(constchar*filename,int*numKeys){RSAPublicKey*out=NULL;*numKeys=0;FILE*f=fopen(filename,"r");if(f==NULL){LOGE("opening%s:

%s\n",filename,strerror(errno));gotoexit;}inti;booldone=false;while(!

done){++*numKeys;out=realloc(out,*numKeys*sizeof(RSAPublicKey));RSAPublicKey*key=out+(*numKeys-1);if(fscanf(f,"{%i,0x%x,{%u",&(key->len),&(key->n0inv),&(key->n[0]))!

=3){gotoexit;}if(key->len!

=RSANUMWORDS){LOGE("keylength(%d)doesnotmatchexpectedsize\n",key->len);gotoexit;}for(i=1;i<key->len;++i){if(fscanf(f,",%u",&(key->n[i]))!

=1)gotoexit;}if(fscanf(f,"},{%u",&(key->rr[0]))!

=1)gotoexit;for(i=1;i<key->len;++i){if(fscanf(f,",%u",&(key->rr[i]))!

=1)gotoexit;}fscanf(f,"}}");//ifthelineendsinacomma,thisfilehasmorekeys.switch(fgetc(f)){case',':

//morekeystocome.break;caseEOF:

done=true;break;default:

LOGE("unexpectedcharacterbetweenkeys\n");gotoexit;}}fclose(f);returnout;exit:

if(f)fclose(f);free(out);*numKeys=0;returnNULL;}intinstall_package(constchar*path){ui_set_background(BACKGROUND_ICON_INSTALLING);ui_print("Findingupdatepackage...\n");ui_show_indeterminate_progress();LOGI("Updatelocation:

%s\n",path);if(ensure_path_mounted(path)!

=0){LOGE("Can'tmount%s\n",path);returnINSTALL_CORRUPT;}ui_print("Openingupdatepackage...\n");intnumKeys;RSAPublicKey*loadedKeys=load_keys(PUBLIC_KEYS_FILE,&numKeys);if(loadedKeys==NULL){LOGE("Failedtoloadkeys\n");returnINSTALL_CORRUPT;}LOGI("%dkey(s)loadedfrom%s\n",numKeys,PUBLIC_KEYS_FILE);//Giveverificationhalftheprogressbar...ui_print("Verifyingupdatepackage...\n");ui_show_progress(VERIFICATION_PROGRESS_FRACTION,VERIFICATION_PROGRESS_TIME);interr;err=verify_file(path,loadedKeys,numKeys);free(loadedKeys);LOGI("verify_filereturned%d\n",err);if(err!

=VERIFY_SUCCESS){LOGE("signatureverificationfailed\n");returnINSTALL_CORRUPT;}/*Trytoopenthepackage.*/ZipArchivezip;err=mzOpenZipArchive(path,&zip);if(err!

=0){LOGE("Can'topen%s\n(%s)\n",path,err!

=-1?

strerror(err):

"bad");returnINSTALL_CORRUPT;}/*Verifyandinstallthecontentsofthepackage.*/ui_print("Installingupdate...\n");returntry_update_binary(path,&zip);}下面顺着上面的流程图和源码来分析这一流程:

①ensure_path_mount():

先判断所传的update.zip包路径所在的分区是否已经挂载。

如果没有则先挂载。

②load_keys():

加载公钥源文件,路径位于/res/keys。

这个文件在Recovery镜像的根文件系统中。

③verify_file():

对升级包update.zip包进行签名验证。

④mzOpenZipArchive():

打开升级包,并将相关的信息拷贝到一个临时的ZipArchinve变量中。

这一步并未对我们的update.zip包解压。

⑤try_update_binary():

在这个函数中才是对我们的update.zip升级的地方。

这个函数一开始先根据我们上一步获得的zip包信息,以及升级包的绝对路径将update_binary文件拷贝到内存文件系统的/tmp/update_binary中。

以便后面使用。

⑥pipe():

创建管道,用于下面的子进程和父进程之间的通信。

⑦fork():

创建子进程。

其中的子进程主要负责执行binary(execv(binary,args),即执行我们的安装命令脚本),父进程负责接受子进程发送的命令去更新ui显示(显示当前的进度)。

子父进程间通信依靠管道。

⑧其中,在创建子进程后,父进程有两个作用。

一是通过管道接受子进程发送的命令来更新UI显示。

二是等待子进程退出并返回INSTALLSUCCESS。

其中子进程在解析执行安装脚本的同时所发送的命令有以下几种:

progress<frac><secs>:

根据第二个参数secs(秒)来设置进度条。

set_progress<frac>:

直接设置进度条,frac取值在0.0到0.1之间。

firmware<”hboot”|”radio”><filename>:

升级firmware时使用,在APIV3中不再使用。

ui_print<string>:

在屏幕上显示字符串,即打印更新过程。

execv(binary,args)的作用就是去执行binary程序,这个程序的实质就是去解析update.zip包中的updater-script脚本中的命令并执行。

由此,Recovery服务就进入了实际安装update.zip包的过程。

下一篇继续分析使用update-binary解析并执行updater-script的过程。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 管理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1