Android 的一些启动方式
翻译自 Android Booting Shenanigans by topjohnwu
术语
-
rootdir: 根目录(
/
),所有的文件、文件夹、分区、文件系统都被存储并挂载在根目录中,在 Android 中,文件系统可能是rootfs
或system
分区。 -
initramfs: Android 启动镜像中的一部分,Linux 内核把它作为
rootfs
使用 -
recovery
和boot
分区: 这两个分区其实十分相似,都是包含 ramdisk 和 Linux 内核的启动镜像(外加其它的一些东西),唯一的区别是启动boot
分区时将会启动 Android,而recovery
将会启动一个最小化的 Linux 环境,用来修复或升级设备 -
SAR: System-as-root,指将
system
分区作为根目录而不是rootfs
-
A/B, A-Only: 对于支持无缝系统更新,而且拥有两个相同的
system
、vendor
、boot
,我们称之为 A/B 设备,反之,没有 A/B 设备这些特性的,我们称之为 A-Only 设备 -
2SI: 双阶段启动,解释放在后面
这里有几个参数可以更精确地定义设备的 Android 版本:
-
LV: 发行版本,指设备发行时的 Android 版本。即设备首次上市时预装的Android版本
-
RV: 运行版本,指设备现在运行的 Android 版本
我们会使用 Android API 级别 来表示 LV 和 RV,API 级别和Android 版本之间的关系可以从这个表格中看到。例如,Pixel XL 发行时搭载 Android 7.1,现在运行 Android 10。这段话则可以用这段参数表示 LV = 25, RV = 29
启动方法
Android 的启动可以大致分为三种不同的方法,我们提供了一个方法,以确定您的设备最有可能使用的启动方法,例外情况将单独列出
方法 | 启动时的根目录 | 最终的根目录 |
---|---|---|
A | rootfs | rootfs |
B | system | system |
C | rootfs | system |
-
方法 A - Legacy ramdisk: 这是以前所有 Android 设备的启动方式,内核使用
initramfs
作为根目录,并执行/init
来启动- 不属于方法 B 和 C 标准的设备
-
方法 B - Legacy SAR: 这种启动方法最先出现在 Pixel 1,内核直接挂载
system
分区作为根目录,然后执行/init
启动- 设备
LV = 28
- Google: Pixel 1、2 和升级到 Android 9 的 Pixel 3(a)
- 一加: 6 - 7
- 也有可能出现在部分
LV < 29
的 Android GO 设备中?
- 设备
-
方法 C - 2SI ramdisk SAR: 这种启动方法最先出现在 Pixel 3 Android 10 的开发者预览版当中,内核会先将
initramfs
作为根目录,然后在rootfs
中执行/init
,这个init
负责挂载system
分区为新的根目录,最终执行/system/bin/init
来启动- 设备
LV > 29
- 设备
LV < 28, RV > 29
不包括已经使用方法 B 的设备 - Google: Pixel 3(a) 且
RV >= 29
- 设备
一些讨论
从 Google 官方的文档来看,Google 对 SAR 的定义只考虑了内核如何启动设备(上表中的 Initial rootdir),也就是说,从 Google 的角度来看,只有使用方法 B 的设备才是 Google 官方认为的 SAR 设备。
但对于 Magisk 来说,真正的区别在于设备在完全启动时最终使用的根目录是什么(上表中的 Final rootdir),也就是说,就 Magisk 而言,方法 B 和方法 C 都是 SAR 的一种形式,只是实现方式不同。本文档后面提到的每一个 SAR 例子都会参考 Magisk 的定义,除非另有特别说明。
方法 C 的标准有点复杂,简单点的话就是,要么你的设备足够新,预载 Android 10+,要么你就是在原本使用方法 A 的设备上运行第三方 Android 10+ 的 ROM。
- 任何使用方法 A 的设备在运行 Android 10+ 时,都必须使用方法 C
- 使用方法 B 的设备将继续使用方法 B 启动,除了 Pixel 3(a),Google 对其进行了改动以适应方法 C
SAR 是 Project Treble 中非常重要的一部分,因为 rootdir 应该与平台绑定,且谷歌强制所有 OEM 厂商遵守每年更新的要求。这也是为什么方法 B 和 C 带有 LV >= API级别
标准的原因。
一些历史
当 Google 发布初代 Pixel 时,他就已经支持了 A/B(无缝) 系统更新。出于存储空间的考虑,与 A-only 相比,有几个不同之处,最大的变化是的是删除了 recovery
和 cache
分区,recovery ramdisk 被合并到 boot
中。
让我们回到 Google 第一次设计 A/B 的时候,如果使用 SAR(当时只有方法 B 存在),内核不需要 initramfs
来启动 Android(因为会将 system
挂载为根目录)。这意味着我们可以把 recovery
删除,把 recovery ramdisk(包含了一个最小化到 Linux 环境)放到 boot
里,然后让内核根据 Bootloader 的信息来决定将哪个挂载为根目录 (system
或 recovery ramdisk)
随着时间的推移,Google 推出了动态分区,这对于 SAR 来说不是一个好消息,因为 Linux 内核不能直接识别这种新分区格式,从而无法直接将 system
挂载为根目录。他们想到了方法 C,先将 initramfs
作为根目录,然后让 userspace 处理剩下的启动步骤,包括决定要启动到 Android 或 Recovery,Google 官方称之为 USES_RECOVERY_AS_BOOT
一些使用 A/B 和 2SI 的新设备还带有 recovery_a/_b
分区,这是 Google 官方支持的标准。这些设备将只使用 boot ramdisk 启动到 Android,因为 recovery 存储在一个单独的分区。
总结
有了以上的信息,现在我们可以把所有的 Android 设备分为这几种不同的类型。
类型 | 启动方法 | 分区类型 | 是否使用 2SI | boot 中的 Ramdisk |
---|---|---|---|---|
一 | A | A-Only | 不使用 | boot ramdisk |
二 | B | A/B | 可选 | recovery ramdisk |
三 | B | A-Only | 可选 | N/A |
四 | C | Any | 使用 | 混合 ramdisk |
- 类型一: legacy ramdisk 启动
- 类型二: 较老的 A/B 设备,Pixel 1 是第一款此类型设备,是第一款使用了 A/B 和 SAR 设备。
- 类型三: 2018年末-2019年末的设备大多都是 A-Only,就 Magisk 而言,是有史以来最糟的一种设备
- 类型四: 所以使用方法 C 的设备都属于类型四,使用 A/b 分区的类型四设备的 ramdisk 可以根据 Bootloader 的信息启动到 Android 或 Recovery,A-Only 的类型四设备的 ramdisk 只能启动到 Android
关于类型三设备的更多信息:Magisk 安装在 boot
的 ramdisk 中。对于其它类型的设备,因为它们的 boot
分区包含 ramdisk,所以可以很容易地通过 Magisk 管理器或第三方 Recovery 来安装 Magisk。但类型三设备,只能将 Magisk 安装到 recovery
分区中。正常启动时,Magisk 无法工作。除非从 recovery
分区启动,Magisk 才能正常工作。
一些类型三设备的 Bootloader 仍然支持 initramfs
被手动添加到 boot 镜像中的内核中(例如一些小米设备),但是许多设备都不支持(例如三星 S10,Note 10)。这完全取决于厂商如何定义其 Bootloader 的功能。