Android 7系统休眠唤醒(二)开机全链路—BootROM到Launcher

系列目录第一篇:电源管理架构全景图 | 第二篇:开机全链路---BootROM到Launcher | 第三篇:关机/重启全链路---ShutdownThread到kernel_power_off | 第四篇:休眠唤醒与开关机---核心差异深度对比 | 第五篇:休眠全链路---PMS到Kernel Suspend | 第六篇:唤醒全链路---Kernel Resume到屏幕点亮 | 第七篇:内核层---wakelock与autosleep机制 | 第八篇:内核层---Alarm定时唤醒与硬件唤醒源 | 第九篇:Native层---libsuspend与Power HAL | 第十篇:实战调试与问题排查


一、为什么要理解开机流程

要理解休眠唤醒为什么快,必须先理解正常开机有多慢。开机流程是一套"从零开始重建整个世界"的完整链路,涵盖硬件初始化、内核启动、用户空间进程孵化、系统服务启动、应用启动等六大阶段。

当你遇到以下问题时,理解开机流程是关键:

  • "为什么开机要 30 秒以上?"------ZygoteInit.preloadClasses() 需要从 /system/etc/preloaded-classes 预加载数千个类,这是最耗时的单步操作
  • "为什么某些系统服务在开机后不可用?"------该服务可能在 startBootstrapServices 阶段创建但在 systemReady() 阶段才完全就绪
  • "为什么 BOOT_COMPLETED 广播收到时某些服务还没初始化完?"------BOOT_COMPLETEDAMS.systemReady() 中发送,但 startOtherServices 中的服务可能尚未完成 systemReady()

二、开机流程全景概览

Android 开机可划分为六个阶段,每个阶段依赖于前一阶段的完成,形成严格的串行依赖链:

复制代码
BootROM → BootLoader → Linux Kernel → init → Zygote → SystemServer → Launcher
 (硬件)     (硬件)       (内核)       (init)   (Java孵化)  (框架服务)     (桌面)

三、阶段一:BootROM --- 芯片上电的第一段代码

BootROM 是固化在 SoC 内部 ROM 中的代码,不可修改,上电后由硬件自动执行。它的职责非常单一:

  1. 初始化最基本的硬件(时钟、栈指针、少量 SRAM)
  2. 从预设的存储介质(eMMC / UFS / NAND)中加载 BootLoader 的第一阶段(SPL,Secondary Program Loader)到内部 SRAM
  3. 验证 SPL 的签名(secure boot 使能时)
  4. 跳转到 SPL 执行

BootROM 代码由芯片厂商提供,不在 AOSP 开源范围内。不同 SoC 厂商实现差异很大,但职责相同。


四、阶段二:BootLoader --- 板级初始化与内核加载

4.1 LK (Little Kernel) 与 U-Boot

Android 设备常见的 BootLoader 有两种:

  • LK (Little Kernel):高通、MTK 等多数厂商使用
  • U-Boot:部分芯片厂商或开发板使用

以 LK 为例:

源码路径bootable/bootloader/lk/

LK 的核心启动路径:

复制代码
_start (arch/arm/crt0.S)
  → kmain() (kernel/main.c)
    → platform_early_init() --- 板级早期初始化(时钟、DDR、UART)
    → apps_init() --- 启动 LK 内建应用
      → aboot_init() (app/aboot/aboot.c)
        → boot_linux() --- 加载并启动 Linux 内核

4.2 boot.img 的结构

BootLoader 需要从存储分区中读取 boot.img。Android 的 boot.img 包含三部分:

复制代码
+-----------------+
|   boot header   |  页大小、kernel大小、ramdisk大小等元信息
+-----------------+
|   kernel        |  压缩后的 Linux 内核镜像 (Image.gz)
+-----------------+
|   ramdisk       |  cpio/gzip 压缩的初始根文件系统
+-----------------+
|   dtb (可选)    |  Device Tree Blob,硬件描述信息
+-----------------+

源码路径system/core/mkbootimg/mkbootimg.c

4.3 加载内核

LK 的 boot_linux() 函数完成:

  1. 将 kernel 解压到内存指定位置
  2. 将 ramdisk 加载到内存
  3. 设置内核启动参数(cmdline),如 console=ttyMSM0androidboot.hardware=qcom
  4. 设置 ATAGs 或 Device Tree
  5. 跳转到内核入口点,交出控制权

五、阶段三:Linux Kernel 启动

5.1 内核启动流程

内核入口为架构相关的汇编代码:arch/arm/kernel/head.S(ARM32)或 arch/arm64/kernel/head.S(ARM64)。

核心 C 入口:

源码路径init/main.c

复制代码
start_kernel()
  → setup_arch()           --- 架构相关初始化,解析 Device Tree
  → mm_init()              --- 内存管理子系统初始化
  → sched_init()           --- 调度器初始化
  → init_IRQ()             --- 中断子系统初始化
  → console_init()         --- 控制台初始化
  → rest_init()
      → kernel_thread(kernel_init)  --- 创建 init 内核线程
      → kernel_thread(kthreadd)     --- 创建内核守护线程
      → cpu_startup_entry()         --- 进入 idle loop

5.2 kernel_init --- 挂载根文件系统并启动 init

kernel_init() 的核心工作:

  1. do_basic_setup() --- 初始化设备驱动模型、加载内建驱动
  2. 挂载根文件系统(通常是从 ramdisk 挂载)
  3. 执行 /init------这是用户空间的第一个进程,PID = 1

关键kernel_init 启动 /init 后,控制权正式从内核态转移到用户态。此时内核已完成全部初始化,但用户空间的进程、服务、ART 虚拟机都还未创建。


六、阶段四:init 进程 --- 用户空间的"创世进程"

6.1 init 入口

源码路径system/core/init/init.cpp

init 进程的核心职责:

  1. 挂载基础文件系统:/proc/sys/dev/dev/pts
  2. 创建 /dev/kmsg 并重定向标准输入输出
  3. 初始化属性服务(property_service)
  4. 解析 init.rc 配置文件
  5. 按阶段执行 on early-init / on init / on late-init / on boot
  6. 进入事件循环,监听 property 变化、子进程退出等

6.2 init.rc --- 系统初始化的"剧本"

源码路径system/core/rootdir/init.rc

init.rc 使用 Android Init Language(AIL)编写,定义了系统启动的完整蓝图:

on early-init --- 设置内核参数、启动 ueventd

on init --- 创建目录结构、设置文件权限和 SELinux 上下文、挂载文件系统

on late-init --- 串行触发:

  • trigger early-fs --- 挂载早期文件系统
  • trigger fs --- 挂载主要文件系统
  • trigger post-fs --- 文件系统就绪后的初始化
  • trigger post-fs-data --- /data 分区可写后的初始化
  • trigger load_system_props_action --- 加载系统属性
  • trigger boot --- 进入 boot 阶段

on boot --- 启动核心守护进程:servicemanagervoldsurfaceflingernetdlogdhealthdinstalldmediaserver

6.3 属性服务

属性系统是 Android 进程间共享配置的关键机制:

源码路径system/core/init/property_service.cpp

  • 属性以 key-value 形式存储,key 前缀决定权限(ro. 只读,persist. 持久化)
  • 属性变更可触发 init.rc 中的触发器
  • 关键属性示例:ro.boot.hardware(硬件平台)、sys.boot_completed(启动完成标志)、ro.build.version.sdk(SDK 版本)

七、阶段五:Zygote --- Java 世界的孵化器

7.1 Zygote 的设计思想

Zygote 是 Android 中几乎所有 Java 进程的父进程。它先预加载常用类和资源,然后通过 fork 创建新进程。利用 COW(Copy-on-Write)机制,子进程共享预加载的内存页,大幅减少启动开销。

7.2 Zygote 启动

Zygote 在 init.rc 中定义:

源码路径system/core/rootdir/init.zygote32.rc

复制代码
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

app_process 入口:

源码路径frameworks/base/cmds/app_process/app_main.cpp

cpp 复制代码
int main(int argc, char* const argv[]) {
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    if (strcmp(arg, "--zygote") == 0) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}

关键设计AppRuntime 继承自 AndroidRuntimeruntime.start() 内部启动 ART 虚拟机,然后通过 JNI 回调到 Java 层的 ZygoteInit.main()------这是 C++ 到 Java 世界的关键跨越点。

AndroidRuntime.start() 启动 ART 虚拟机并调用 ZygoteInit.main()

源码路径frameworks/base/core/jni/AndroidRuntime.cpp

7.3 ZygoteInit.main() --- 核心初始化

源码路径frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

java 复制代码
public class ZygoteInit {
    public static void main(String[] argv) {
        // 1. 创建 zygote socket,监听 AMS 的 fork 请求
        registerZygoteSocket(socketName);

        // 2. 预加载(最耗时的阶段)
        preloadClasses();      // 从 /system/etc/preloaded-classes 加载数千个类
        preloadResources();    // 系统资源:主题、颜色、字符串
        preloadOpenGL();       // EGL/OpenGL 共享库

        // 3. fork SystemServer 进程
        if (argv[1].equals("start-system-server")) {
            startSystemServer(abiList, socketName);
        }

        // 4. 进入事件循环,等待 AMS 的 fork 请求
        runSelectLoop(abiList);
    }
}

关键设计preloadClasses() 是最耗时的单步操作------它需要加载数千个 Java 类。但正是因为 Zygote 在 fork 前完成预加载,每个 App 进程启动时无需重复这个过程,利用 COW 机制共享内存页,启动时间从数秒降至数百毫秒。


八、阶段六:SystemServer --- 框架服务的"总管家"

8.1 fork SystemServer

源码路径frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

Zygote 通过 Zygote.forkSystemServer() 创建 SystemServer 进程,子进程执行 handleSystemServerProcess(),最终调用 SystemServer.main()

8.2 SystemServer.run() --- 三阶段启动

源码路径frameworks/base/services/java/com/android/server/SystemServer.java

java 复制代码
public final class SystemServer {
    private void run() {
        Looper.prepareMainLooper();
        System.loadLibrary("android_servers");
        createSystemContext();

        startBootstrapServices();   // 第一阶段:引导服务
        startCoreServices();        // 第二阶段:核心服务
        startOtherServices();       // 第三阶段:其他服务

        Looper.loop();
    }
}

关键设计 :三阶段启动确保服务间的依赖关系------startBootstrapServices 创建 AMS/PMS/PKMS 等基础服务,startCoreServices 创建依赖它们的服务,startOtherServices 创建所有剩余服务。任何阶段的服务创建失败都会导致后续阶段无法启动。

8.3 startBootstrapServices() --- 引导服务

最基础的服务,后续服务依赖它们:

服务 功能 源码路径
Installer 与 installd 通信,负责 APK 安装 frameworks/base/services/core/java/com/android/server/pm/Installer.java
ActivityManagerService 四大组件管理、进程管理 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
PowerManagerService 功耗管理、休眠唤醒状态机 frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
LightsService 通知灯、背光灯控制 frameworks/base/services/core/java/com/android/server/lights/LightsService.java
DisplayManagerService 显示设备管理 frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
PackageManagerService 包管理、权限管理 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
UserManagerService 多用户管理 frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java

AMS 和 PKMS 此时创建但尚未完全就绪,systemReady() 在第三阶段调用。

8.4 startCoreServices() --- 核心服务

服务 功能 源码路径
BatteryService 电池状态监测 frameworks/base/services/core/java/com/android/server/BatteryService.java
UsageStatsService 应用使用统计 frameworks/base/services/core/java/com/android/server/usage/UsageStatsService.java
WebViewUpdateService WebView 组件更新 frameworks/base/services/core/java/com/android/server/webkit/WebViewUpdateService.java

8.5 startOtherServices() --- 其他服务

所有剩余服务在此阶段启动,主要包括:

服务 功能 源码路径
WindowManagerService 窗口管理、输入事件分发 frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
ConnectivityService 网络连接管理 frameworks/base/services/core/java/com/android/server/ConnectivityService.java
AlarmManagerService Alarm 定时器管理 frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
NotificationManagerService 通知管理 frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
BluetoothService 蓝牙管理 frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
InputMethodManagerService 输入法管理 frameworks/base/services/core/java/com/android/server/InputMethodManagerService.java
AudioService 音频管理 frameworks/base/services/core/java/com/android/server/audio/AudioService.java

8.6 systemReady() 回调链

所有服务创建后,依次调用 systemReady()

  1. AMS.systemReady() --- 启动 Launcher、恢复栈顶 Activity、发送 BOOT_COMPLETED 广播
  2. PKMS.systemReady() --- 完成待处理的包操作
  3. WMS.systemReady() --- 显示系统 UI
  4. PMS.systemReady() --- 初始化完成,启用自动休眠

九、Launcher 启动 --- 用户可见的第一屏

源码路径frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

AMS 在 systemReady() 中调用 startHomeActivityLocked() 启动 Launcher:

java 复制代码
boolean startHomeActivityLocked(int userId, String reason) {
    Intent intent = getHomeIntent();  // 构造 Intent.CATEGORY_HOME
    ActivityInfo aInfo = resolveActivityInfo(intent, ...);
    // 启动 Launcher 的 main Activity
    mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}

Launcher 启动后,AMS 发送 Intent.ACTION_BOOT_COMPLETED 广播------这是 App 开发者可接收的"开机完成"信号。

关键设计BOOT_COMPLETED 广播在 Launcher 启动后才发送,但此时 startOtherServices 中的部分服务可能尚未完成 systemReady()。对于需要在开机后立即执行的任务,注册 BOOT_COMPLETED 广播是最可靠的时机,而非依赖 Launcher 的可见性。


十、开机流程完整时序图

复制代码
时间 →

BootROM (硬编码,上电自动执行)
  │
  ▼
BootLoader (LK/U-Boot)
  │ 初始化 DDR、UART、存储
  │ 加载 boot.img → kernel + ramdisk
  │
  ▼
Linux Kernel (start_kernel)
  │ 架构初始化、内存管理、调度器、中断
  │ 挂载 ramdisk → 执行 /init
  │
  ▼
init 进程 (PID 1)
  │ 解析 init.rc,按阶段执行
  │ 启动 servicemanager、vold、surfaceflinger 等守护进程
  │
  ▼
Zygote (app_process)
  │ 启动 ART,预加载类/资源/共享库
  │ fork SystemServer 进程
  │
  ▼
SystemServer
  │ startBootstrapServices → AMS, PMS, PKMS...
  │ startCoreServices      → BatteryService...
  │ startOtherServices     → WMS, Bluetooth, Telephony...
  │ systemReady()          → 启动 Launcher
  │
  ▼
Launcher 启动 → BOOT_COMPLETED 广播 → 用户可操作

十一、关键源码文件索引

文件 路径 本文涉及内容
init.cpp system/core/init/ init 进程入口、属性服务
init.rc system/core/rootdir/ 系统初始化脚本
app_main.cpp frameworks/base/cmds/app_process/ Zygote 入口
ZygoteInit.java frameworks/base/core/java/com/android/internal/os/ 预加载类、fork SystemServer
SystemServer.java frameworks/base/services/java/com/android/server/ 三阶段服务启动
ActivityManagerService.java frameworks/base/services/core/java/com/android/server/am/ Launcher 启动、BOOT_COMPLETED

十二、小结

开机流程本质上是一个"全量初始化"的过程。从 BootROM 的第一条指令到 Launcher 显示桌面,中间经历了多层抽象、数十个进程的创建、上百个系统服务的初始化。

阶段 核心工作 耗时占比
BootROM → BootLoader 硬件初始化、加载内核 ~5%
Kernel 启动 架构初始化、驱动加载 ~10%
init 进程 解析 init.rc、启动守护进程 ~10%
Zygote 预加载类/资源(最耗时) ~30%
SystemServer 启动上百个系统服务 ~40%
Launcher 启动桌面 ~5%

这一过程之所以漫长,核心原因在于 状态必须从零开始重建------每一个数据结构、每一个内存映射、每一个服务状态都必须从配置文件或持久化存储中重新加载并初始化。

理解这一点之后,再看休眠唤醒就会发现:休眠唤醒的"快"本质上是因为跳过了这整个重建过程------内核保持初始化完成的状态、进程只被冻结而非杀死、ART 虚拟机堆内存完整保留、系统服务无需重新启动。

下一篇Android 7系统休眠唤醒(三)关机/重启全链路---ShutdownThread到kernel_power_off --- 如果开机是"从零开始重建世界",关机就是"有秩序地拆除这个世界"。关机流程与开机形成镜像,完成"全量销毁"的闭环。

相关推荐
Mr YiRan2 小时前
Android NDK开发之统计到未被回收的图片
android
浮江雾3 小时前
Flutter第十七节-----路由管理(3)
android·开发语言·前端·javascript·flutter·入门
admin and root3 小时前
「移动安全」安卓APP 反编译&frida脱壳技巧分享
android·开发语言·python·web安全·微信小程序·移动安全·攻防演练
ihuyigui4 小时前
海外签收通知短信接口
android·java·开发语言·前端·数据库·后端
大尚来也5 小时前
老项目 PHP 5.6 升级 PHP 8 完整迁移步骤与兼容坑汇总
android·adb
Android研究员5 小时前
Android进阶之事件分发机制深度剖析
android·前端·面试
峥嵘life6 小时前
Android WiFi连接过程 wpa_supplicant 日志分析
android·开发语言·php
Android小码家7 小时前
OWASP 移动应用安全之授权(MASTG-DEMO-0090)
android·安全·frida
Summer-Bright8 小时前
消费者 AI 变现竞争:从“一家独大“到“iOS vs Android“,谁在为 AI 买单?
android·人工智能·ios·ai·自然语言处理·agi