Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节【转】

本文转载自:http://blog.csdn.net/mu0206mu/article/details/7465439

 Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节

 

         Recovery服务毫无疑问是Recovery启动模式中最核心的部分。它完成Recovery模式所有的工作。Recovery程序对应的源码文件位于:/gingerbread0919/bootable/recovery/recovery.c。

一、 Recovery的三类服务:

先看一下在这个源码文件中开始部分的一大段注释,这将对我们理解Recovery服务的主要功能有很大帮助。代码如下:

[cpp] view plain copy

  1. /*
  2. * The recovery tool communicates with the main system through /cache files.
  3. *   /cache/recovery/command - INPUT - command line for tool, one arg per line
  4. *   /cache/recovery/log - OUTPUT - combined log file from recovery run(s)
  5. *   /cache/recovery/intent - OUTPUT - intent that was passed in
  6. *
  7. * The arguments which may be supplied in the recovery.command file:
  8. *   --send_intent=anystring - write the text out to recovery.intent
  9. *   --update_package=path - verify install an OTA package file
  10. *   --wipe_data - erase user data (and cache), then reboot
  11. *   --wipe_cache - wipe cache (but not user data), then reboot
  12. *   --set_encrypted_filesystem=on|off - enables / diasables encrypted fs
  13. *
  14. * After completing, we remove /cache/recovery/command and reboot.
  15. * Arguments may also be supplied in the bootloader control block (BCB).
  16. * These important scenarios must be safely restartable at any point:
  17. *
  18. * FACTORY RESET
  19. * 1. user selects "factory reset"
  20. * 2. main system writes "--wipe_data" to /cache/recovery/command
  21. * 3. main system reboots into recovery
  22. * 4. get_args() writes BCB with "boot-recovery" and "--wipe_data"
  23. *    -- after this, rebooting will restart the erase --
  24. * 5. erase_volume() reformats /data
  25. * 6. erase_volume() reformats /cache
  26. * 7. finish_recovery() erases BCB
  27. *    -- after this, rebooting will restart the main system --
  28. * 8. main() calls reboot() to boot main system
  29. *
  30. * OTA INSTALL
  31. * 1. main system downloads OTA package to /cache/some-filename.zip
  32. * 2. main system writes "--update_package=/cache/some-filename.zip"
  33. * 3. main system reboots into recovery
  34. * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..."
  35. *    -- after this, rebooting will attempt to reinstall the update --
  36. * 5. install_package() attempts to install the update
  37. *    NOTE: the package install must itself be restartable from any point
  38. * 6. finish_recovery() erases BCB
  39. *    -- after this, rebooting will (try to) restart the main system --
  40. * 7. ** if install failed **
  41. *    7a. prompt_and_wait() shows an error icon and waits for the user
  42. *    7b; the user reboots (pulling the battery, etc) into the main system
  43. * 8. main() calls maybe_install_firmware_update()
  44. *    ** if the update contained radio/hboot firmware **:
  45. *    8a. m_i_f_u() writes BCB with "boot-recovery" and "--wipe_cache"
  46. *        -- after this, rebooting will reformat cache & restart main system --
  47. *    8b. m_i_f_u() writes firmware image into raw cache partition
  48. *    8c. m_i_f_u() writes BCB with "update-radio/hboot" and "--wipe_cache"
  49. *        -- after this, rebooting will attempt to reinstall firmware --
  50. *    8d. bootloader tries to flash firmware
  51. *    8e. bootloader writes BCB with "boot-recovery" (keeping "--wipe_cache")
  52. *        -- after this, rebooting will reformat cache & restart main system --
  53. *    8f. erase_volume() reformats /cache
  54. *    8g. finish_recovery() erases BCB
  55. *        -- after this, rebooting will (try to) restart the main system --
  56. * 9. main() calls reboot() to boot main system
  57. *
  58. * SECURE FILE SYSTEMS ENABLE/DISABLE
  59. * 1. user selects "enable encrypted file systems"
  60. * 2. main system writes "--set_encrypted_filesystems=on|off" to
  61. *    /cache/recovery/command
  62. * 3. main system reboots into recovery
  63. * 4. get_args() writes BCB with "boot-recovery" and
  64. *    "--set_encrypted_filesystems=on|off"
  65. *    -- after this, rebooting will restart the transition --
  66. * 5. read_encrypted_fs_info() retrieves encrypted file systems settings from /data
  67. *    Settings include: property to specify the Encrypted FS istatus and
  68. *    FS encryption key if enabled (not yet implemented)
  69. * 6. erase_volume() reformats /data
  70. * 7. erase_volume() reformats /cache
  71. * 8. restore_encrypted_fs_info() writes required encrypted file systems settings to /data
  72. *    Settings include: property to specify the Encrypted FS status and
  73. *    FS encryption key if enabled (not yet implemented)
  74. * 9. finish_recovery() erases BCB
  75. *    -- after this, rebooting will restart the main system --
  76. * 10. main() calls reboot() to boot main system
  77. */

从注释中我们可以看到Recovery的服务内容主要有三类:

①FACTORY RESET,恢复出厂设置。

②OTA INSTALL,即我们的update.zip包升级。

③ENCRYPTED FILE SYSTEM ENABLE/DISABLE,使能/关闭加密文件系统。具体的每一类服务的大概工作流程,注释中都有,我们在下文中会详细讲解OTA INSTALL的工作流程。这三类服务的大概的流程都是通用的,只是不同操作体现与不同的操作细节。下面我们看Recovery服务的通用流程。

二、Recovery服务的通用流程:

在这里我们以OTA INSTALL的流程为例具体分析。并从相关函数的调用过程图开始,如下图:

我们顺着流程图分析,从recovery.c的main函数开始:

1.    ui_init():Recovery服务使用了一个基于framebuffer的简单ui(miniui)系统。这个函数对其进行了简单的初始化。在Recovery服务的过程中主要用于显示一个背景图片(正在安装或安装失败)和一个进度条(用于显示进度)。另外还启动了两个线程,一个用于处理进度条的显示(progress_thread),另一个用于响应用户的按键(input_thread)。

2.    get_arg():这个函数主要做了上图中get_arg()往右往下直到parse arg/v的工作。我们对照着流程一个一个看。

①get_bootloader_message():主要工作是根据分区的文件格式类型(mtd或emmc)从MISC分区中读取BCB数据块到一个临时的变量中。

②然后开始判断Recovery服务是否有带命令行的参数(/sbin/recovery,根据现有的逻辑是没有的),若没有就从BCB中读取recovery域。如果读取失败则从/cache/recovery/command中读取然后。这样这个BCB的临时变量中的recovery域就被更新了。在将这个BCB的临时变量写回真实的BCB之前,又更新的这个BCB临时变量的command域为“boot-recovery”。这样做的目的是如果在升级失败(比如升级还未结束就断电了)时,系统在重启之后还会进入Recovery模式,直到升级完成。

③在这个BCB临时变量的各个域都更新完成后使用set_bootloader_message()写回到真正的BCB块中。

这个过程可以用一个简单的图来概括,这样更清晰:

3.     parserargc/argv:解析我们获得参数。注册所解析的命令(register_update_command),在下面的操作中会根据这一步解析的值进行一步步的判断,然后进行相应的操作。

4.    if(update_package):判断update_package是否有值,若有就表示需要升级更新包,此时就会调用install_package()(即图中红色的第二个阶段)。在这一步中将要完成安装实际的升级包。这是最为复杂,也是升级update.zip包最为核心的部分。我们在下一节详细分析这一过程。为从宏观上理解Recovery服务的框架,我们将这一步先略过,假设已经安装完成了。我们接着往下走,看安装完成后Recovery怎样一步步结束服务,并重启到新的主系统的。

5.    if(wipe_data/wipe_cache):这一步判断实际是两步,在源码中是先判断是否擦除data分区(用户数据部分)的,然后再判断是否擦除cache分区。值得注意的是在擦除data分区的时候必须连带擦除cache分区。在只擦除cache分区的情形下可以不擦除data分区。

6.    maybe_install_firmware_update():如果升级包中包含/radio/hboot firmware的更新,则会调用这个函数。查看源码发现,在注释中(OTA INSTALL)有这一个流程。但是main函数中并没有显示调用这个函数。目前尚未发现到底是在什么地方处理。但是其流程还是向上面的图示一样。即,① 先向BCB中写入“boot-recovery”和“—wipe_cache”之后将cache分区格式化,然后将firmware image 写入原始的cache分区中。②将命令“update-radio/hboot”和“—wipe_cache”写入BCB中,然后开始重新安装firmware并刷新firmware。③之后又会进入图示中的末尾,即finish_recovery()。

7.    prompt_and_wait():这个函数是在一个判断中被调用的。其意义是如果安装失败(update.zip包错误或验证签名失败),则等待用户的输入处理(如通过组合键reboot等)。

8.    finish_recovery():这是Recovery关闭并进入Main System的必经之路。其大体流程如下:

① 将intent(字符串)的内容作为参数传进finish_recovery中。如果有intent需要告知Main System,则将其写入/cache/recovery/intent中。这个intent的作用尚不知有何用。

② 将内存文件系统中的Recovery服务的日志(/tmp/recovery.log)拷贝到cache(/cache/recovery/log)分区中,以便告知重启后的Main System发生过什么。

③ 擦除MISC分区中的BCB数据块的内容,以便系统重启后不在进入Recovery模式而是进入更新后的主系统。

④ 删除/cache/recovery/command文件。这一步也是很重要的,因为重启后Bootloader会自动检索这个文件,如果未删除的话又会进入Recovery模式。原理在上面已经讲的很清楚了。

9.    reboot():这是一个系统调用。在这一步Recovery完成其服务重启并进入Main System。这次重启和在主系统中重启进入Recovery模式调用的函数是一样的,但是其方向是不一样的。所以参数也就不一样。查看源码发现,其重启模式是RB_AUTOBOOT。这是一个系统的宏。

至此,我们对Recovery服务的整个流程框架已有了大概的认识。下面就是升级update.zip包时特有的也是Recovery服务中关于安装升级包最核心的第二个阶段。即我们图例中的红色2的那个分支。

我们将在下一篇详细讲解这一部分,即Recovery服务的核心部分install_package函数

时间: 2024-12-08 19:41:52

Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节【转】的相关文章

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

通过分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.我们先从update.zip包的制作开始,然后是Android系统的启动模式分析,Recovery工作原理,如何从我们上层开始选择system update到重启到Recovery服务,以及在Recovery服务中具体怎样处理update.zip包升级的,我们的安装脚本updater-script怎样被解析并执行的等一系列问题.分析过程中所用的Android源码是gin

Android系统Recovery工作原理之使用update.zip升级过程---updater-script脚本语法简介以及执行流程(转)

目前update-script脚本格式是edify,其与amend有何区别,暂不讨论,我们只分析其中主要的语法,以及脚本的流程控制. 一.update-script脚本语法简介: 我们顺着所生成的脚本来看其中主要涉及的语法. 1.assert(condition):如果condition参数的计算结果为False,则停止脚本执行,否则继续执行脚本. 2.show_progress(frac,sec):frac表示进度完成的数值,sec表示整个过程的总秒数.主要用与显示UI上的进度条. 3.for

揭秘Android App的工作原理-乐居猫学Android开发

Android App的工作原理 Android系统是基于liunx内核的,但是与传统的基于liunx的pc系统不同,用户对Android app没有绝对的掌控权.pc系统中,在应用程序的系统菜单上选择"退出"或者"关闭"之类的选项会直接杀死进程.在Android系统中不是这样的.而是由系统,当系统需要释放内存来运行新进程或者保证某些后台进程和前端进程顺利执行的时候才会释放相应应用程序的资源,这个释放过程有一个重要性的层次,接下来就听乐居猫做一下说明: androi

理解Android系统的进程间通信原理(二)----RPC机制

理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI的相关知识,可以通过下图来归纳: Android中的RPC也是参考了JAVA中的RMI方案,这里我们再详细了解一下RPC的实现过程. Android中的RPC机制是为了实现一个进程使用另一个进程中的远程对象,它使用了Android自己的AIDL(接口定义语言),使用户很方便地定义出一个接口作为规范,

理解Android系统的进程间通信原理(一)----RPC中的代理模式

Android系统中的进程间通信是通过一个轻量级的RPC(Remote Procedure Call远程进程调用)和AIDL(Android Interface Definination Language)规范来生成两个进程之间可以相互访问的代码.其中RPC是以接口方式来实现,客户端与被调用实现之间是通过代理模式来实现的,这些又是以JAVA的RMI和代理模式为理论基础的,若要灵活掌握这个轻量级的解决方案,有必要重新理顺这些基础知识的,这里我们先了解代理模式的相关基础, 有关代理模式的知识,可以用

车牌识别停车场计费系统的工作原理解析

今天主要来分享下车牌识别以及车牌识别停车计费系统的一些知识. 关键核心:车牌识别.停车场计费系统.停车管理系统.OCR识别 一.首先那停车收费系统由哪些组成的呢? 从产品形态上来看停车收费系统由软件(车牌识别.计费系统)和硬件(相机.立柱.显示屏.道闸.地感等)这两方面来组成. 1.车牌识别软件系统 车牌识别系统(Vehicle License Plate Recognition,VLPR) 是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符.英文字母.阿拉伯数字及号牌颜色)进行处

Android:制作Update.zip升级包 【转】

本文转载自:http://zwkufo.blog.163.com/blog/static/2588251201382293049118/ 很多时候厂商或者三方提供的ROM并不能满足需求,比如系统自带软件陈旧.缺少GMS软件包(Google Mobile Service,包含了Gmail.GooglePlay等Google自家的常用软件,很多用户习惯用Gmail.用ContactsSync,所以通常会对这个服务包有比较强烈的需求),等等. 在这种情况下,一种方法是用户可以通过破解设备.加Root权

(原)android系统下绑定Server的时候报MainActivity has leaked ServiceConnection的错误

今天在android系统下根据官方的demo代码,我们需要启动一个服务,并绑定,但在程序启动以后,老是报错: Activity MainActivity has leaked ServiceConnection CameraUtil$[email protected] that was originally bound here android.app.ServiceConnectionLeaked: Activity MainActivity has leaked ServiceConnect

Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6786239 Android 系统的运行时库层代码是用C++来编写的,用C++来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃.不过系统为 我们提供了智能指针,避免出现上述问题,本文将系统地分析Android系统智能指针(轻量级指针.强指针和弱指针)的实现原理. 在使用C++来编写代码的过程中,指针使用不当造成