版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49834125
Android OTA更新
Android设备可以接受和安装系统和应用软件的空中下载更新.设备有一个特殊的带有软件的recovery分区,该分区可以解压下载的更新包并且将他们应用到系统中.
这一小节描述了这些包的结构和为了构建他们所提供的工具.主要是为了那些想要在新的Android设备上制作OTA更新系统工作和那些为发行的的设备构建更新包的开发者设计的.OTA更新被设计用于设计底层的操作系统和安装在系统分区的只读app;这些更新不会影响来自应用市场的用户安装的应用程序.
这一小节描述的是Android5.x发行版的OTA系统升级.最后我会将其他版本的OTA相关的代码附上.
Android设备更新
Android设备上的flash空间包含下面的几个分区:
boot
包含Linux内核和一个小型的根文件系统(被加载到RAM中).他挂载系统和其他分区,并且启动位于系统分区上的运行时.
system
包含系统应用和在android开源项目(AOSP)中存在源代码的库文件.在正常操作期间,这个分区是以只读方式被挂载的;他的内容仅仅在OTA更新期间被改变.
vendor
包含系统应用和在AOSP中不存在源代码的库文件.在正常操作期间,该分区是以只读的方式挂载的;他的内容仅仅在OTA更新期间被改变.
userdata
保存由用户安装的应用的数据.这个分区通常是不能被OTA更新改变的.
cache
暂时持有被一些应用所使用的区域(访问这个分区需要特殊的app权限),并且用于存储下载的OTA更新包.其他应用程序使用这个空间,会知道文件会在任何时候消息.一些OTA包安装程序可能会导致这个分区被完全擦除.
recovery
包含一个完整的Linux系统,包括一个内核和特殊的recovery二进制文件,这些文件读取一个包并且使用他的内容来更新其他分区.
misc
被recovery使用的小型分区来保存一些信息,以防止当OTA包正在被应用的时候设备重启.
一个OTA更新的声明周期
一个典型的OTA更新包含下面的步骤:
- 设备使用OTA服务运行常规的检查,并且被可用更新通知,包括更新包的URL和展示给用户的一个描述字符串.
- 更新下载到一个cache或者是data分区,并且他的加密签名和位于/system/etc/security/otacerts.zip的证书进行验证.用户被推送来安装更新
- 设备重启进入recovery模式,在这个模式中,位于recovery分区的内核和系统被启动,而不是位于boot分区内核启动
- Recovery二进制文件被init启动.他寻找位于/cache/recovery/command中的命令行参数,该参数执行下载的包.
- Recovery通过位于/res/keys(位于recovery分区的一部分RAM)下的公共钥匙来验证包的加密签名.
- 数据从包中提取出来并且用于去更新需要的boot,system和vendor分区.位于system分区的其他新文件之一包含新的recovery分区的内容
- 设备正常重启.
a. 新更新的boot分区被加载,他挂载和开始执行位于新的更新的system分区中的二进制文件
b. 作为正常启动的一部分,系统检查recovery分区的内容和需要的内容做对比(之前以文件的形式保存在/system中). 他们是不同的,所以recovery分区被需要的内容写入.(在随后的启动中,recovery分区已经包含新的内容,所以不需要重新写入了.)
系统更新完成了.
迁移从先前的版本
当从Android2.3/3.0/4.0发行版迁移的时候,主要的改变就是所有的设备特定的函数从一套C函数到预定义名称的C++对象的转换.下列的表列举除了实现同样目的的旧函数和新方法.
C function | C++ method |
---|---|
device_recovery_start() | Device::RecoveryStart() |
device_toggle_display() device_reboot_now() |
RecoveryUI::CheckKey() (also RecoveryUI::IsKeyPressed()) |
device_handle_key() | Device::HandleMenuKey() |
device_perform_action() | Device::InvokeMenuItem() |
device_wipe_data() | Device::WipeData() |
device_ui_init() | ScreenRecoveryUI::Init() |
旧函数到新方法的转换应该是非常合理直接的.不要忘记添加一个新的make_device()函数来创建和返回一个新的设备子类的实例.