Skip to content

01 开机到桌面:从 BootROM 到 Launcher 的全时间线 ​

本页导读:一次按电源键,CPU 从一片死寂到画出一整张桌面壁纸,中间经历 BootROM、一级/二级 bootloader(LK 或 U-Boot,fastboot 模式是它的调试分身)、内核、init、zygote、system_server,最后由 Launcher 交出接力棒。本页按时间轴逐段拆解:每段跑什么代码、读什么文件、出错了用什么命令验证。基线 Android 16(API 36),但这段链路十年骨架未变,差异集中在 AVB、动态分区与 GKI。


读完本页你应该能回答:

  • 电源键按下去后,代码控制权在谁手里、信任是怎么传递的?
  • sys.boot_completed=1 到底意味着“什么就绪了”?
  • 卡 logo、卡动画、黑屏三种事故分别该从哪里开始查?

一、全景时间轴 ​

text
按下电源键
  └─ BootROM(SoC 内固化)         验签并加载一级 bootloader
      └─ 一级 bootloader(sbl)     初始化 DRAM/时钟,加载二级
          └─ 二级 bootloader       LK / U-Boot / EDK2(厂商选择)
              ├─ fastboot 模式     刷机协议分身
              └─ 正常启动          验签 boot.img → 跳内核入口
                  └─ Linux 内核    挂 ramdisk,执行 /init(PID 1)
                      └─ init 一阶段  挂载 system 等,切根
                          └─ init 二阶段 解析 rc,起 servicemanager/zygote/SF
                              └─ zygote 预加载 → fork system_server
                                  └─ system_server 起服务 → systemReady
                                      └─ 启动 Launcher(HOME)→ boot_completed

经验值(AOSP 参考实现,厂商差异大):现代设备冷开机到锁屏可交互一般在 20~45 秒量级;sys.boot_completed=1 只代表系统服务就绪,不代表 Launcher 首帧已出。

二、BootROM 与 AVB:信任的起点 ​

  • BootROM 烧死在 SoC 里,做第一件事是找启动介质(eMMC/UFS/SPI),用 eFuse 里的公钥哈希验签一级 bootloader;
  • Android Verified Boot(AVB)从 bootloader 接力:boot/recovery/vendor_boot 等镜像尾部挂 avb footer,vbmeta 分区集中存放各分区描述符哈希;
  • 校验结果通过 cmdline 告诉内核:androidboot.verifiedbootstate=green|yellow|orange|red,framework 侧 SystemProperties 与 ro.boot.verifiedbootstate 可见;
  • fastboot 解锁(fastboot flashing unlock)会把状态打成 orange,部分 OEM 会清数据——这是设计,不是 bug。

验证:adb shell getprop | grep ro.boot.(注意在表格内书写时需转义竖线),能看到 ro.boot.bootloader 等字段;串口/dmesg 里能看到 AVB 逐分区校验日志。

  • 校验失败分级处置:red 直接拒绝启动;解锁后的 yellow/orange 由 OEM 策略决定是否警告、是否擦数据;
  • dm-verity 运行期发现分区被篡改会按 androidboot.verity_mode 策略当场重启或 panic,日志关键字 dm-verity corruption。

三、二级 bootloader:LK、U-Boot 与 fastboot ​

  • LK(little kernel):高通/MediaTek 老平台常见,本身就是个小 RTOS,源码在 GitHub 上以 lk/little kernel 名义流传(AOSP 本体不再收录,Bootable 已归档);显示 logo、fastboot UI、下载模式都在这层;
  • U-Boot/EDK2:部分平台与虚拟设备(如 cuttlefish 用 U-Boot,虚拟机直接用 VMM);
  • fastboot 协议:二级 bootloader 的分身,fastboot flash boot boot.img 刷的就是内核+ramdisk;fastboot oem 命令厂商自定义;
  • 交给内核前的关键动作:装配 kernel cmdline(console、androidboot.* 参数)、把 DTB 放到约定地址、加载 ramdisk(GKI 平台改用 vendor_boot/vendor_dlkm 与 bootconfig,不再依赖大 cmdline)。

出问题的典型症状:卡 logo 不进系统——多半是 boot/vendor_boot 验签失败或 DTB 不匹配,串口日志第一现场。

四、内核:命令行里藏着开机履历 ​

内核解压后第一件事是挂 ramdisk(first-stage ramdisk 在 boot.img 里),然后执行 /init——它就是 PID 1。

  • cmdline 上的 androidboot.hardware、androidboot.serialno、androidboot.mode=charger|fastboot 等 androidboot.* 参数会被 init 拆成 ro.boot.* 属性(第 02 页 property 机制);
  • GKI(Android 11 起通用内核)推荐 bootconfig(/proc/bootconfig、/sys/kernel/bootconfig)承载 androidboot.*,规避 cmdline 长度限制;
  • 内核日志是启动排查第一现场:adb shell dmesg,或 /sys/fs/pstore/(console-ramoops 保留崩溃前日志,上次死机的证据在这里);
  • 有条件一定接串口(UART):framework 日志要等 logd/zygote 活着才有,而串口从 bootloader 就在,是“链路最底层 witness”;
  • androidboot.hardware 决定 init 后续加载 init.<hardware>.rc(第 02 页),这是同一份 system 镜像适配不同板子的第一个分岔点。

五、init:一阶段挂载,二阶段拉起整机 ​

/system/core/init 的 main 分 first-stage / second-stage(Android 10 动态分区后正式分家):

  1. first-stage:只挂 super、解 dm-verity/dm-linear(动态分区映射表在 lpmeta),挂 system 等最小集,然后 switch_root 进完整 rootfs;
  2. second-stage:挂载 /data(触发 post-fs-data)、挂载 APEX(apexd,第 12 页)、加载 SELinux policy、解析 rc 文件链;
  3. rc 编排(细节第 02 页):early-init → init → late-init → post-fs → post-fs-data → boot-complete 一串 trigger,关键服务按 class 拉起:class_start main(zygote、surfaceflinger 等)、class_start hal;
  4. 最后阶段 init 触发 exec system_ready 类动作后,servicemanager、surfaceflinger、zygote 相继就绪。

每阶段验证命令:

阶段看什么命令
bootloader版本与状态getprop ro.boot.bootloader;fastboot 下 fastboot getvar all
内核cmdline/错误cat /proc/cmdline、dmesg 看首屏
一阶段分区映射ls /dev/block/dm-*、dmctl dump(需 root)
二阶段触发链getprop 过滤 boottime、dmesg 过滤 init
SELinuxenforcinggetenforce、dmesg 过滤 avc

六、zygote 与 system_server:Java 世界的黎明 ​

init 二阶段读到 /system/etc/init/zygote.rc 后拉起 zygote64(app_process64),ZygoteInit.main() 在 fork system_server 前完成预加载:类(preloaded-classes 系列清单)、资源(android.R 的预载)、JNI 注册、/dev/__properties__ 映射。随后 ZygoteInit.main() 通过 forkSystemServer() 派生 system_server,它加载 SystemServer 类走三阶段启动(第 03 页)。

时间账(AOSP 参考值,以实测为准):zygote 预加载通常占开机 300ms~1s;system_server 三阶段+开机广播可占 3~8s;Launcher 冷启动 1~3s。开机慢,多半慢在 system_server 服务串行启动与 IO 扫描(PMS 全量扫描,第 08 页)。

预加载的内容大致分四类:

预加载项清单/来源效果
热类preloaded-classes、脏页优化版、text-init 版fork 后直接命中,省去类加载
资源android.R 常用资源、主题、预载 Drawable首帧 inflate 成本大降
JNI/运行时JNI 注册、/dev/__properties__ 映射系统属性读取零拷贝
其他预热部分系统组件的预热钩子,具体清单以 AOSP 为准降低首次使用成本
java
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java(示意节选,非逐行源码)
public static void main(String[] args) {
    ...
    preload(...);                          // 预加载类/资源/JNI,fork 后全继承
    zygoteServer = new ZygoteServer(abiList); // 监听 /dev/socket/zygote*
    if (startSystemServer) {
        forkSystemServer(abiList);         // fork 出 system_server,子进程走 SystemServer.main
    }
    Runnable r = zygoteServer.runSelectLoop(abiList, null); // 此后永久监听孵化请求
}

七、Launcher 出场:HOME 解析 ​

system_server 走完 startOtherServices 后调用 ActivityManagerService.systemReady() 收尾,链路上由 ActivityTaskManagerService 发出 HOME intent(Intent.ACTION_MAIN + CATEGORY_HOME),经第 06 页的进程启动链孵化或复用 Launcher 进程,ResumeActivityItem 下发,Launcher 首帧上屏。期间用户看到的是 bootanimation(/system/media/bootanimation.zip 或 OEM 定制,由独立 bootanimation 进程直绘 SurfaceFlinger,不依赖 system_server 全量就绪)。

boot 完成的最后一棒:AMS 发 ACTION_BOOT_COMPLETED 广播(仅系统应用与注册了开机广播的应用可收),并把 sys.boot_completed 置 1——fastboot/开机度量脚本都以它为零点。

验证三件套:

bash
adb shell dumpsys activity | grep -e "Resumed" -e "mResumedActivity"  # 当前前台是否 Launcher
adb shell getprop sys.boot_completed                                   # 应为 1
adb shell dumpsys activity | grep -i "displayed"                       # 各 Activity 上屏耗时

Displayed 行是 Google 官方推荐的启动耗时口径(framework 统计的首帧),例如 Displayed com.android.launcher/.Launcher +812ms。

八、另外三扇门:charger、recovery 与安全模式 ​

正常链路之外,同一台设备还有三个启动分身:

  • charger 模式:cmdline 带 androidboot.mode=charger 时,init 只拉起充电相关 class,画面由 rootfs 里的 charger 二进制直绘,不碰 zygote;验证:getprop ro.boot.mode;
  • recovery 模式:Android 9+ recovery 从 boot.img 拆成独立分区,里面是另一套精简 ramdisk + update_engine/updater;经典 A/AB 全量包走 recovery 或 sideload,Virtual A/B 则完全不走 recovery,由后台 update_engine 在正常系统内安装 snapshot;
  • 安全模式(safe mode):Android 13+ 开机时长按音量下可进,禁用第三方应用,是处理“开机循环由某个坏 App 引起”的标准逃生通道。

这三扇门共同的特点:都不依赖完整 framework,所以它们是 framework 彻底瘫痪时仅剩的修复面。刷机、清数据、OTA 回滚都发生在这里,而不是在 Android 系统内部。

九、首次开机与 OTA 后的开机:两套时间线 ​

  • 首次开机(首次进桌面前的“初始化仪式”):/data 刚创建,PMS 需要全量扫描分区并首次写 /data/system 下的包状态;ART 对预装应用可能触发 dex2oat;多用户/工作资料初始化;所以首开机比日常开机慢好几秒很正常;
  • 后续开机:PMS 直接读持久化的包状态缓存,跳过全量解析(扫描与缓存机制见第 08 页);大部分包命中 profile 的 speed-profile,不重新编译;
  • OTA 后首次开机:Classic A/B 只是换槽回滚;Virtual A/B 需要在开机早期做 snapshot merge,期间 IO 风暴,boot_completed 后的“假卡顿”多源于此;
  • 排查建议:比较两台设备开机速度前先对齐“首开/非首开/OTA 后”这三种场景,否则数据没有可比性。

十、bootstat 与时间账本 ​

bootstat(system/core/bootstat)在开机各里程碑打点并落入 bootcomplete_event/boot_event log 事件:

  • adb shell bootstat -p boot_complete:上次开机事件属性(含 subreason、duration);
  • getprop | grep boottime:ro.boottime.init 等一干内核/服务起点时间;
  • bugreport 的 BOOTSTAT 与 ps -p 1 -o lstart 可以交叉还原整机时间线;
  • 死机取证:/sys/fs/pstore/console-ramoops + /data/tombstones + last_kmsg(部分内核保留)。

十一、常见故障模式与定位 ​

症状大概率区间第一现场
完全无显示、电流无变化BootROM/电源电流表、JTAG/串口
卡第一屏 logobootloader/AVB/DTB串口、fastboot 是否可进
进 recovery/fastboot 循环boot/vendor_boot 验签或 dm-verity 失败fastboot 重刷、dm-verity corrupt 内核日志
卡开机动画init 二阶段→zygote→system_server串口 init: ... starting service、logcat -b all(zygote 死后才有 framework 日志)
动画完黑屏/桌面不出Launcher 崩溃/HOME 解析失败logcat 过滤 AndroidRuntime、dumpsys activity activities
反复 system_server 重启Watchdog/关键服务 NPElogcat 过滤 SystemServer/Watchdog、dropbox SYSTEM_RESTART

十二、版本注记 ​

  • Android 8(API 26):Treble 引入,init 出现 vendor rc 链;AVB 2.0 起步。
  • Android 9(API 28):AVB2.0 强制、vbmeta 独立分区;recovery 与 boot 解耦(recovery 独立分区)。
  • Android 10(API 29):动态分区(super/lpmeta)、first-stage 与 second-stage init 分家、APEX 登场。
  • Android 11(API 30):GKI 通用内核起步、bootconfig 替代部分 cmdline;VNDK 快照。
  • Android 12(API 31):boot image v4、Virtual A/B(VAB)OTA;vendor_boot 镜像拆分。
  • Android 13~16(API 33~36):HIDL HAL 清零推进;GKI 2023+ 内核版本基线抬升;Mainline 模块继续从 system 搬走能力(第 12 页)。

本页小结 ​

本页小结:开机是一条单向信任链:BootROM 验 bootloader、AVB 验镜像、内核信 cmdline、init 信 rc、system_server 信服务、Launcher 信 HOME intent。任何一环断掉,症状都会「向上冒泡」成卡 logo、卡动画或黑屏,而定位思路永远是先问自己:现在链路走到哪一层?串口/ro.boottime.*/Displayed 分别在三个高度等着你对号入座。

参考 ​

  • AOSP 启动流程文档:source.android.com/docs/core/architecture(Boot flow 章)
  • init 源码与 README:cs.android.com/android/platform/system/core/+/main/init/README.md
  • ZygoteInit 源码:cs.android.com/android/platform/frameworks/base/+/main/core/java/com/android/internal/os/ZygoteInit.java
  • AVB/libavb 源码:cs.android.com/android/platform/external/avb

基于 Android 16 / API 36 · 内容为原创整理,转载请注明出处