cm-14.1 Android系统启动过程分析(n)- 关机/重启/重置/升级的那些事(偏嵌入式方向)

本文探讨了Android系统的定制过程,包括关机和重启的机制,其中涉及Linux内核的中断处理和WindowPolicy对象。此外,文章详细介绍了应用的备份和恢复机制,以及系统重置和升级的过程,特别提到了recovery模式的重要角色。
摘要由CSDN通过智能技术生成

声明

1 关机和重启

  按下电源键,会产生一个中断,然后该中断会被Linux内核捕获到,并被内核转换成一个输入事件,再作为一个EV_KEY/KEY_POWER/DOWN事件传给Android运行时(Runtime)。和其他所有事件一样,该事件会依次交给Android的InputReader和InputDispatcher(这两个都是system server线程),后者会把该事件传递给WindowPolicy对象。如果按键的时间足够长(这个时长是定义在 ViewConfiguration的GLOBAL_ACTIONS_KEY_TIMEOUT上的常量500毫秒)默认的WindowPolicy对象(com.android.internal.policyimpl.PhoneWindowManager)就会拦截到该事件,并(通过调用GlobalActions.showDialog()方法) 在屏幕上弹出一个菜单。
在这里插入图片描述
  如果用户确实是要关机,那么还要分两种情况:

  • 如果用户只是正常点击一下“关机”虚拟键的话,就会正常关机;
  • 如果用户长按“关机”虚拟键的话,手机就会重启到安全模式下;

  这两个操作都是由一个专门的ShutdownThread来处理的,其中的shutdownInner()方法负责在执行具体的关机操作之前弹出一个确认对话框(当然也可以设置成不弹出这个对话框)。
  如果用户确认要关机,beginShutdownSequence()要设置两个屏幕唤醒锁 (wakelock),以保持屏幕在整个过程中始终处于点亮状态(这是为了提供更好的用户体验)。然后ShutdownThread就会运行,它依次要执行的操作如下图所示:
在这里插入图片描述
  关机的最后一步在。Linux原生层上是由init执行的。因为这个线程是负责实现系统属性的,它负责把sys.power.ctl属性设置为shutdown或是reboot,reason。这里的这个reason可以是recovery,也可以是Boot Loader。要是你觉得这几个属性值挺眼熟的话,那一点也不奇怪,因为adb reboot也是要求用户在这些值中选择一个,并以用户的输入设置同一个属性(在adb中把它称为ANDROID_RB_PROPERTY)的。这样,不管之前选择的是何种操作,终归都会回到init,而它又会去调用libcutils中的android_reboot函数。这个函数实际上只是内核中的reboot() )系统调用的一个封装。reboot的调用格式是Linux定好了的,上面那个reason将被作为参数传递给它。

2 应用的备份和恢复

  操作系统需要处理数据遭到破坏甚至是完全丢失的问题。因此备份和恢复也是操作系统必须提供的一项重要功能。App也需要这一能力以保存和还原它们的配置和数据。高级用户也需要这一能力,来备份整个手机,以便在出现问题时,能将手机恢复到系统还原点或一个已知可以正常工作和启动的配置上。
  Android向应用提供了一个名为BackupManagerService的框架服务,它既可以让各个应用各自单独地进行备份,也可以一次性地备份所有应用。备份的架构相当地简洁,它让应用自己决定要备份哪些数据。当相关数据发生变化时,应用会通知 BackupManager,然后BackupManager会把该应用添加到一个队列中。
在这里插入图片描述
  当BackupManager得到一个可以进行备份的通知时,它就会创建一个备份集(backupset),把队列中的应用放在一起,对于每个应用,它都要去调用该应用的onBackup()回调函数。
  BackupManager会把一个文件描述符通过这个回调函数传递给应用,应用用它读写备份数据。这个BackupManager提供的文件描述符实际上是指向一个transport的,但这一点对于应用来说是完全透明的。应用根本无须操心通过 transport读写的数据具体是源自何方的一一数据可能是备份在本地的,也有可能会被备份到“云端”(谷歌云服务器或设备制造商提供的云服务)。至于数据到底应该被备份到哪里去这一问题,最终要交给系统或厂商来决定。下表中给出了常用的transport:

Transport 名称备份到
com.google.android.backup/.BackupTransportService谷歌的云服务器,应用需要提供一个特定的使用该服务的API key
com.android.server.enterprise/.EdmBackupTransport企业备份,仅用于被托管的 (managed)手机
android/com.android.internal.backup.LocalTransport手机本地备份

  Android系统提供了命令行工具bmgr和bu,这两个脚本借助Java通过Binder与BackupManagerService进行通信。adb backup -all命令会触发系统对所有应用做一个完全备份(full backup),这么做会使得bu去调用BackupManagerService的fullBackup()方法,该方法将弹出一个可以定制的UI提示界面给用户。

3 系统重置和升级

  系统的重置(recovery)和升级的过程十分相似:系统都要用另一套代码去启动。用这套代码不会加载完整的操作系统用户界面,而是只加载一个最小的配置,用一个特定的二进制可执行文件/xbin/recovery来执行我们目前正在讨论的这个启动过程。
  不论是系统升级还是重置,一般都是在系统完全启动起来之后在图形界面里开始操作的。(也可以用adb reboot recovery 命令或者通过 fastboot 让手机进入 recovery 模式)。在通过图形界面开始系统升级或重置时,android.os.RecoverySystem类提供了一个在用户发出升级请求时下载和验证升级包的框架。升级包必须经过数据签名,而且该签名要能被 /system/etc/security/otacerts.zip这个keystore中的证书验证为有效。只有签名被验证通过了,升级包才会被复制到cache分区中去。
  android.os.RecoverySystem这个类也可以在recovery过程中传递参数。要传递的参数会被写入/cache/recovery/command文件,然后这个类会去重启系统,并在重启过程中传一个参数给BootLoader,让它从recovery分区而不是从boot分区启动。recovery分区和boot分区中的内容差不多,都存有RAM disk镜像,只不过在从recovery分区启动时,加载的是/xbin/recovery,而不是完整的Android操作系统。RecoverySystem向/xbin/recovery传递命令的过程如下图所示:
在这里插入图片描述
  /xbin/recovery会从它自己的命令行中获得它的参数一如果有的话。如果没有参数的话,它还会去misc 区寻找BCB(Boot Loader 控制块,Boot Loader Control Block)。如果找不到这个分区,或者分区里的内容没法解析,该可执行文件会转而使用/cache/recovery/command。Android 运行时不会直接与 BCB 进行交互,它是留给/sbin/recovery保存所有给它的参数的。这样可以保证一旦出现了意外的中断,重启之后依旧会进入recovery模式,并再次执行之前失败的动作。
  二进制可执行文件/xbin/recovery是肯定可以加载的,因为它是RAM disk的一部分,和/system一点关系都没有。注意,这一点很重要,因为/system可能会处于一种完全无法启动的状态。然后,当内核初始化完毕,且加载了/init之后,recovery(或许还有 adbd)也许就是除/init之外的唯一被执行的进程了。接着/sbin/recovery会去读取/cache/recovery/command文件中留给它的参数(如上图所示),并根据这些参数执行相关的操作。/ache/recovery/command中可以使用的参数如下表所示:
在这里插入图片描述
  在整个过程中,不断向用户输出信息,并保持屏幕点亮是非常重要的。所以 recovery 也要使用minui(一个提供基本 GUI 功能的库)来完成相关操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小馬佩德罗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值