Android 系统如何从按下电源走到桌面
Android 系统如何从按下电源走到桌面
设备停在开机动画时,能否判断 system_server 已经启动?不能。开机动画、桌面首帧和 BOOT_COMPLETED 分属不同链路,只凭屏幕现象无法确定 Framework 走到了哪一步。
排查启动问题更可靠的办法,是先找到最后一个有证据的成功节点,再进入对应阶段。以 AOSP Android 14 android-14.0.0_r75 为基线,冷启动主线可以压缩成下面七个节点:
Boot ROM → Bootloader → Linux Kernel → init → Zygote
→ system_server → Launcher / BOOT_COMPLETED这不是一个函数从头执行到底。前一阶段准备运行环境,再通过跳转、exec、启动服务或 fork 把控制权交给下一阶段。
每一段到底交出了什么
Boot ROM 是芯片固化代码,它只完成足以找到下一阶段加载器的初始化。Bootloader 随设备和 芯片平台变化很大,稳定职责是选择启动目标、校验并装载内核、ramdisk、设备树和启动参数, 然后跳到内核入口。这里没有 Binder,也没有 Android Java 运行时。
Linux Kernel 接管 CPU 后建立内存管理、调度和驱动环境,并运行第一个用户空间程序 /init。init 成为 PID 1,挂载文件系统、初始化属性服务,并依据 rc 配置拉起 Native 服务和 Zygote。
Zygote 已经装载 Android Runtime 和一批公共类、资源。它收到创建系统进程的请求后通过 fork 产生 system_server;父进程继续充当孵化器,子进程进入 SystemServer 的 Java 启动逻辑。system_server 再创建 AMS、WMS、PMS 等服务,并按启动阶段逐步通知服务进入 可用状态。
这几次交接的语义不同:Bootloader 的跳转把 CPU 控制权交给内核入口;内核运行 /init 是在新建的用户空间里装入程序映像;Zygote 的 fork 则复制现有进程上下文,产生新的 Linux 进程。把它们都称作“调用下一层”,会丢掉最关键的进程边界。
“开机完成”没有唯一时刻
至少要区分三个里程碑:
| 证据 | 能证明什么 | 不能证明什么 |
|---|---|---|
| 关键系统服务进入 ready 阶段 | Java Framework 主干已运行 | Launcher 已提交首帧 |
| Launcher 桌面可见 | Home 已启动并产生可见画面 | 目标应用已收到开机广播 |
目标进程收到 BOOT_COMPLETED | 该用户下的接收者已获通知 | 所有应用初始化任务都已结束 |
三者受用户解锁状态、设备性能和厂商策略影响,不能机械地用同一个时间点代表。开机动画也 只能证明显示链具备了一部分工作条件,不足以证明 SystemServer 已完成服务启动。
用最后成功节点缩小范围
先记录最后成功里程碑,再按下面的分段进入对应专题:
| 可见现象或证据 | 优先检查阶段 |
|---|---|
| 没有任何 Logo 或早期输出 | 供电、固件、Boot ROM、Bootloader |
| 厂商 Logo 后没有内核进展 | 镜像验证、Kernel 交接、早期内核 |
system_server PID 反复变化 | Zygote 之后的 SystemServer 启动 |
system_server 稳定但没有桌面 | Home 解析、Activity 启动、窗口首帧 |
| 桌面可见但开机任务未执行 | 用户状态、广播送达、应用自身条件 |
上电后没有任何画面时,先检查供电、固件与 Bootloader;停在厂商 Logo 时,再结合串口或 早期内核日志判断是否已跳到 Kernel。出现开机动画但 system_server PID 反复变化,范围已 经收敛到 Zygote 创建系统进程之后,应检查 SystemServer 崩溃和服务启动失败。若 system_server 稳定而 Home 不出现,则继续看 Home 解析、Activity 启动和窗口首帧。
桌面已经可见但开机任务没有执行,不应回头怀疑 Bootloader。此时应核对当前用户是否已解锁、 接收者是否匹配、广播是否送达,以及应用自身是否又设置了启动条件。
这些判断都需要日志、进程、属性或 trace 交叉证明。屏幕只是帮助选择采样位置的线索,不能 单独定责。
源码从哪里进入
本文只画启动地图,源码入口按阶段分开:
| 阶段 | AOSP 入口 |
|---|---|
| 启动验证与槽位信息 | external/avb/、system/core/bootloader_message/ |
| Kernel 到 Android 用户空间 | 内核源码、system/core/init/ |
| init 启动配置 | system/core/rootdir/ |
| Zygote | frameworks/base/core/java/com/android/internal/os/ |
| SystemServer 与系统服务 | frameworks/base/services/ |
Boot ROM 和具体 Bootloader 不由 AOSP 完整定义,不能把某个平台的实现路径推广到所有设备。 后续可沿 Bootloader、Kernel、 init、Zygote 和 SystemServer 五篇逐段跟进。
排查启动故障时,先写下“最后一个已被证据证明成功的节点”。这句话比“卡在开机动画”更能 决定下一步该读哪段日志和源码。