吉游网提供最新游戏下载和手游攻略!

Android系统升级解析:深度剖析update包升级流程

发布时间:2024-10-04浏览:66

老铁们,大家好,相信还有很多朋友对于Android系统升级解析:深度剖析update包升级流程和的相关问题不太懂,没关系,今天就由我来为大家分享分享Android系统升级解析:深度剖析update包升级流程以及的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!

升级流程概述

升级的流程图:

升级流程分析

第一步:升级包获取

升级获取可以通过远程下载,也可直接拷贝到指定目录即可。

第二步:准备升级

然后调用RecoverySystem.installPackage将目录通过传参方式传递下去。这是应用层代码如下:

public void updateSystem(String updateSavePath) { File packageFile = new File(updateSavePath); try { //调用升级接口 RecoverySystem.installPackage(this, packageFile); } catch (IOException e) { LOG.e(TAG, "RecoverySystem ERROR!!!"); e.printStackTrace(); String errDesc =String.format("execute system update fail. reason->%s", e.toString()); reportUpdateError(errDesc); }LOG.d(TAG, "RecoverySystem OK!!!");copyUpdateFileIsSuccess = false;}

在应用层下载升级包后,会调用RecoverySystem.installPackage(Context context, File packageFile)函数来发起安装过程,这个过程主要的原理,实际上只是往 /cache/recovery/command 写入升级包存放路径,然后重启到recovery模式,仅此而已。

public static void installPackage(Context context, File packageFile) throws IOException { String filename = packageFile.getCanonicalPath(); Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");//升级包路径final String filenameArg = "--update_package=" + filename;final String localeArg = "--locale=" + Locale.getDefault().toString();bootCommand(context, filenameArg, localeArg);}private static void bootCommand(Context context, String… args) throws IOException { RECOVERY_DIR.mkdirs(); // In case we need it COMMAND_FILE.delete(); // In case it's not writable LOG_FILE.delete(); FileWriter command = new FileWriter(COMMAND_FILE); try { for (String arg : args) { if (!TextUtils.isEmpty(arg)) { command.write(arg); command.write("\n"); } } } finally { command.close(); } // Having written the command file, go ahead and reboot PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); //重启到recovery模式 pm.reboot(PowerManager.REBOOT_RECOVERY); throw new IOException("Reboot failed (no permissions?)");}

PowerManager.REBOOT_RECOVERY的值为字符串"recovery",pm.reboot()方法最后会将recovery写入到misc分区的BCB中去。

BCB即Bootloader Control Block,启动控制信息块,位于misc分区,从代码上看,就是一个结构体。如下:

struct bootloader_message { char command[32]; char status[32]; char recovery[1024]; };

bootloader_message 结构体包含三个字段,具体含义如下:

command 字段中存储的是命令,它有以下几个可能值:

boot-recovery:系统将启动进入Recovery模式

update-radia 或者 update-hboot:系统将启动进入更新firmware的模式,这个更新过程由bootloader完成

NULL:空值,系统将启动进入Main System主系统,正常启动。

status 字段存储的是更新的结果。更新结束后,由Recovery或者Bootloader将更新结果写入到这个字段中。

recovery 字段存放的是recovry模块的启动参数,一般包括升级包路径。其存储结构如下:第一行存放字符串“recovery”,第二行存放路径信息“–update_package=/mnt/sdcard/update.zip”等。 因此,参数之间是以“\n”分割的。

第三步:系统重启进入Recovery模式,进行升级操作

Android系统进行升级的时候,有两种途径:

一种是通过接口传递升级包路径自动升级(Android系统SD卡升级),升级完之后系统自动重启。另一种是手动进入recovery模式下,选择升级包进行升级,升级完成之后停留在recovery界面,需要手动选择重启。

前者多用于手机厂商的客户端在线升级,后者多用于开发和测试人员。但不管哪种,原理都是一样的,都要在recovery模式下进行升级。

下面介绍的是升级包保存在cache目录下,且升级包路径保存在/cache/recovery/command中的方式(升级包的存放路径,从BCB或者/cache/recovery/command里面解析得到的)。

重启进入升级主要流程:

系统重启进入Recovery模式。读取BCB的command,读取到”boot-recovery”后,加载recovery.img,启动recovery。

在install.cpp进行升级操作

try_update_binary执行升级脚本

调用finish_recovery方法,清除BCB信息,重启

1、系统重启进入Recovery模式

系统重启时会判断/cache/recovery目录下是否有command文件,如果存在就进入recovery模式,否则就正常启动。

进入到Recovery模式下,将执行recovery.cpp的main函数,下面贴出关键代码片段:

… …while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; … … } … …

2、在install.cpp进行升级操作

在main函数中最终会调用到install_package方法。

… …if (update_package != NULL) { status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true); … …} … …

具体的升级过程都是在install.cpp中执行的,再来看看install_package方法。

int install_package(const char* path, int* wipe_cache, const char* install_file, bool needs_mount) { … … if (setup_install_mounts() != 0) { … … } else { result = really_install_package(path, wipe_cache, needs_mount); } … …}

install_package方法中创建了log文件(记录升级报错的信息)。然后调用really_install_package方法。

really_install_package方法中,首先验证签名,再读取升级包,然后进行调用try_update_binary方法升级

3、try_update_binary执行升级脚本

static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);... ...const char* binary = "/tmp/update_binary";unlink(binary);int fd = creat(binary, 0755); ... ...//将升级包里面的update_binary解压到/tmp/update_binarybool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);... ...const char** args = (const char**)malloc(sizeof(char*) * 5);args[0] = binary; //update_binary存放路径args[1] = EXPAND(RECOVERY_API_VERSION); // Recovery版本号char* temp = (char*)malloc(10);sprintf(temp, "%d", pipefd[1]);args[2] = temp;args[3] = (char*)path; //升级包存放路径args[4] = NULL;pid_t pid = fork();//fork一个子进程if (pid == 0) { close(pipefd[0]); //子进程调用update-binary执行升级操作 execv(binary, (char* const*)args); fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); _exit(-1);}//父进程负责接受子进程发送的命令去更新ui显示 ... ...int status;waitpid(pid, &status, 0);if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { //安装失败,返回INSTALL_ERROR return INSTALL_ERROR;} //安装成功,返回INSTALL_SUCCESSreturn INSTALL_SUCCESS;}

4、调用finish_recovery方法,清除BCB信息,重启

OTA升级成功,清空misc分区(BCB置零),并将保存到内存系统的升级日志/tmp/recovery.log保存到/cache/recovery/last_log。重启设备进入Main System,升级完成。

用户评论

自繩自縛

reszcie! w końcu ktoś postanowił rozłożyć na części pierwsze temat aktualizacji Androida.

    有15位网友表示赞同!

入骨相思

终于等到这篇文章了!一直想知道Android更新是怎么运作的,这篇分析特别详细,看得懂。太棒了,期待后续文章分解其他方面。

    有18位网友表示赞同!

沐晴つ

确实,update包升级流程很多时候都是"黑盒操作",官方很少解释这方面的细节。希望开发者能更加透明化这个过程,让用户了解到更新背后的技术逻辑。

    有18位网友表示赞同!

凉话刺骨

讲道理,Android系统升级的体验真的不太好,进度条卡,手机发热等等,这篇文章分析了update包升级流程,不知道有没有提到如何优化升级体验?

    有8位网友表示赞同!

笑叹尘世美

我觉得这个分析写的非常棒,图示清晰易懂,第一次了解到Android update包包含的这些文件和数据类型。

    有13位网友表示赞同!

不识爱人心

作者分析的很透彻!确实,update包的过程涉及很多环节,一个环节出现问题就会导致整个升级失败。希望未来能看到关于更新机制安全性和可靠性的文章。

    有17位网友表示赞同!

陌離

每次手机升级都感觉像在赌博,希望能顺利完成功能没有问题。真心的期待厂商能拿出更成熟的升级方案,提升用户体验!

    有20位网友表示赞同!

来瓶年的冰泉

说的没错啊!这篇文章把Android系统升级流程拆解的非常清楚,我以前觉得更新就只是点个选项然后等待,现在知道其实背后有很多复杂的逻辑,真的很佩服开发者们。

    有16位网友表示赞同!

墨城烟柳

这篇分析让我对Android系统有了更深入的理解。希望以后能看到更多关于系统本身架构和功能发展的分析,这样能够帮助我们更好地掌握并使用手机!

    有8位网友表示赞同!

迷路的男人

作者你写的太好了,我是一名安卓开发工程师,这篇分析非常有价值,特别是对于理解更新包内部结构的部分,我受益匪浅!

    有8位网友表示赞同!

有恃无恐

感觉这篇文章有点过于技术化了,对普通人来说理解难度还是挺大的。希望以后能结合一些案例和生活场景来解释,让普通用户也能更容易地理解Android系统升级的原理。

    有19位网友表示赞同!

搞搞嗎妹妹

总而言之,这篇分析虽然对更新流程进行了详细解析,但并没有探讨到如何解决实际升级过程中遇到的问题,比如:闪退、卡顿等。或许作者可以进一步深入这个方面?

    有7位网友表示赞同!

笑傲苍穹

我觉得这篇文章很客观,中立地展示了Android系统升级的流程,同时也提到了其中的优缺点。期待后续还能看到关于其他安卓系统更新模式的分析和比较。

    有10位网友表示赞同!

*巴黎铁塔

我感觉有点抽象,能不能用更加直观的方式解释呢?比如:可以用比喻或者动画来帮助用户更好地理解这些复杂的逻辑?

    有5位网友表示赞同!

蝶恋花╮

文章内容丰富,对Android系统的更新流程进行了全面的分析,非常专业。希望作者能继续推出相关主题的文章,深入探讨更新安全、稳定性等方面。

    有9位网友表示赞同!

你瞒我瞒

第一次看到这么详细的Android系统升级分析,受益匪浅!希望这些知识能够帮助我更好地了解手机系统,并进行开发和维护工作。

    有12位网友表示赞同!

微信名字

这篇分析很好地概括了android update包升级流程,对我来说有很好的参考价值。希望能了解到不同版本Android系统的更新机制是否有差异?

    有19位网友表示赞同!

玻璃渣子

这篇文章让我对Android系统有了更深刻的理解, 不过我还是觉得,更新过程太麻烦了!希望未来能实现更加高效快捷的更新方式。

    有12位网友表示赞同!

热点资讯