Android 7系统休眠唤醒(四)休眠唤醒与开关机—核心差异深度对比

📅 2026/7/27 20:23:24
Android 7系统休眠唤醒(四)休眠唤醒与开关机—核心差异深度对比
系列目录第一篇电源管理架构全景图 | 第二篇开机全链路—BootROM到Launcher | 第三篇关机/重启全链路—ShutdownThread到kernel_power_off | 第四篇休眠唤醒与开关机—核心差异深度对比 | 第五篇休眠全链路—PMS到Kernel Suspend | 第六篇唤醒全链路—Kernel Resume到屏幕点亮 | 第七篇内核层—wakelock与autosleep机制 | 第八篇内核层—Alarm定时唤醒与硬件唤醒源 | 第九篇Native层—libsuspend与Power HAL | 第十篇实战调试与问题排查一、为什么要理解四种流程的差异你有没有遇到过这些困惑为什么按电源键休眠后唤醒不到 1 秒而重启手机要等半分钟——休眠保持所有状态在 RAM 中开机却要从零重建一切为什么关机前手机会卡在正在关机…好几秒而休眠是瞬间黑屏——关机需要广播通知所有 App、sync 数据到磁盘、卸载文件系统为什么 App 在休眠唤醒后直接回到之前的界面而关机重启后要从 Splash 页面重新冷启动——休眠冻结进程原地保留开关机杀死进程全部清空前两篇分别拆解了开机的全量重建和关机的有序拆除。本篇将休眠和唤醒与开关机整合到同一个框架中进行多维度对比同时给出休眠和唤醒的顶层概览为后续的深度源码篇章做铺垫。核心结论休眠唤醒之所以比开关机快数十倍是因为它不做拆除和重建而只做冻结和解冻。二、休眠流程顶层概览休眠是将系统从正在使用转为静止待命的过程。从用户视角看就是按一下电源键、屏幕熄灭从内核视角看CPU 被挂起大部分外设掉电仅保留 RAM 自刷新和唤醒源监听。2.1 休眠的完整链路用户按电源键 / 超时无操作 │ ▼ PowerManagerService.goToSleep() │ mWakefulness: Awake → Dozing → Asleep │ 释放 Screen WakeLock │ ▼ DisplayPowerController → 屏幕关闭 │ ▼ nativeSetAutoSuspend(true) → libsuspend │ 写入 mem 到 /sys/power/state │ 或启用 /sys/power/autosleep │ ▼ Kernel: pm_suspend() │ freeze_processes() — 冻结所有用户进程 │ suspend_devices_and_irq() — 挂起外设 │ syscore_suspend() — 系统核心挂起 │ ▼ CPU 进入 deep idle state (WFI) │ 仅 RAM 自刷新 唤醒源监听 │ 功耗降至最低关键设计休眠的入口是 PMS 的goToSleep()但最终由内核的pm_suspend()执行硬件级别的挂起——Framework 只负责请求休眠Kernel 负责执行休眠。2.2 休眠的关键特征进程冻结而非杀死通过freeze_processes()内核向每个进程发送冻结信号进程进入不可中断睡眠TASK_UNINTERRUPTIBLE其内存映射、打开的文件、持有的锁全部保留RAM 持续供电所有进程数据、内核数据结构、页表全部保留在 RAM 中通过自刷新维持外设选择性下电除唤醒源电源键、RTC、Modem外其它外设屏幕、触摸屏、WiFi、蓝牙全部下电三、唤醒流程顶层概览唤醒是休眠的逆过程是系统从静止待命恢复到正在使用的过程。3.1 唤醒的完整链路唤醒源触发GPIO中断 / RTC Alarm / Modem来电 / USB插拔 │ ▼ 中断控制器 → CPU 退出 idle → 跳转到唤醒入口 │ ▼ Kernel: resume 流程 │ syscore_resume() — 恢复系统核心 │ resume_devices_and_irq() — 恢复外设 │ thaw_processes() — 解冻所有进程 │ ▼ libsuspend 检测到唤醒 → nativeSetAutoSuspend(false) → JNI 回调 │ ▼ PowerManagerService.wakeUp() │ mWakefulness: Asleep → Awake │ updatePowerStateLocked() 12 个 Phase │ ▼ DisplayPowerController → 屏幕点亮 │ ▼ PhoneWindowManager → 处理按键事件 / 显示锁屏关键设计唤醒的起点是硬件中断而非 Framework 的某个 API 调用——中断控制器唤醒 CPU 后内核先恢复硬件状态再通过 JNI 回调通知 Framework 层与休眠的调用链完全对称。3.2 唤醒的关键特征进程解冻而非重启thaw_processes()将被冻结的进程恢复到冻结前的调度状态进程无需重新初始化外设逐步恢复按依赖顺序恢复设备驱动状态先恢复总线控制器再恢复挂载其上的设备虚拟机无需重启ART/Dalvik 虚拟机在冻结期间完整保留堆内存解冻后直接恢复执行四、四流程全景时序对比将开机、关机、休眠、唤醒放在同一张时序图上对比时间轴 ──────────────────────────────────────────────────────────────→ 【开机】BootROM→BootLoader→Kernel→init→Zygote→SystemServer→Launcher ──────────────────────── 30~60s ──────────────────────── 【休眠】goToSleep→释放WakeLock→屏幕关→nativeSuspend→freeze→CPU idle ───── 1s ───── 【唤醒】中断→CPU恢复→devices_resume→thaw→wakeUp→屏幕亮→用户操作 ───── 1s ───── 【关机】广播→AMS终止→服务关闭→卸载文件系统→sync→kernel_power_off ───────────── 5~15s ─────────────────差距一目了然开机需要经历 BootROM 到 Launcher 整整七个阶段而唤醒只有一个阶段——从中断触发到解冻进程。五、九维度深度对比以下从九个维度逐一对比开机、关机、休眠、唤醒的核心差异。5.1 触发方式流程触发方式关键入口开机硬件上电 / 长按电源键 / 充电插入 / 复位BootROM 自动执行关机长按电源键→关机对话框 /PowerManager.shutdown()/ 低电量ShutdownThread.start()休眠电源键短按 / 屏幕超时 /PowerManager.goToSleep()PowerManagerService.goToSleep()唤醒GPIO 中断 / RTC Alarm / Modem 来电 / USB 插拔中断控制器 → 内核 resume5.2 内核状态流程内核状态核心函数开机从压缩镜像加载、解压、初始化所有子系统start_kernel()关机有序卸载所有驱动最终掉电kernel_power_off()休眠CPU 进入 deep idle / suspend内核数据结构保留在 RAM 中pm_suspend()→suspend_enter()唤醒中断唤醒 CPU按顺序恢复内核子系统suspend_devices_and_irq_resume()5.3 进程管理流程进程操作核心机制开机fork exec 创建所有新进程Zygote 孵化关机AMS 发送停止信号进程逐一退出AMS.shutdown()休眠freeze_processes() — 冻结而非杀死设置 TASK_UNINTERRUPTIBLE发送冻结信号唤醒thaw_processes() — 解冻恢复到之前的调度状态清除冻结标志唤醒等待队列源码路径kernel/power/process.c5.4 虚拟机ART/Dalvik流程虚拟机状态影响开机完整启动 ART 运行时 加载 boot.oat 预加载类最耗时数秒级别关机运行时销毁堆内存回收所有类加载缓存丢失休眠堆内存完整保留在 RAM 中GC 暂停唤醒后无需重新加载任何类唤醒堆内存直接可用GC 恢复进程可直接执行 Java 代码5.5 系统服务流程服务操作核心调用开机SystemServer 三阶段创建所有服务startBootstrapServices / startCoreServices / startOtherServices关机各服务 systemShutdown() → 释放资源按依赖顺序反向关闭休眠PMS 通知各服务进入休眠服务注册状态保持仅暂停主动工作唤醒PMS 通知各服务退出休眠服务无需重启仅恢复主动工作5.6 Activity 和 UI 状态流程Activity 栈用户可见开机Activity 栈为空冷启动 Launcher看到启动动画 桌面关机所有 ActivityRecord 清空看到关机动画休眠Activity 栈完整保留屏幕熄灭唤醒Activity 栈完整恢复栈顶 Activity 恢复在前台直接看到锁屏或休眠前的界面5.7 硬件外设流程外设操作功耗特征开机驱动逐一加载、设备逐一初始化启动瞬间功耗峰值较高关机驱动逐一卸载、外设逐一下电关机后功耗≈0仅 RTC休眠仅保留唤醒源供电其它外设下电功耗极低仅 RAM 自刷新 RTC唤醒外设逐步恢复供电和驱动状态恢复瞬间功耗短时升高5.8 完成耗时流程典型耗时耗时来源开机30 ~ 60s内核初始化、类预加载、服务启动关机5 ~ 15s广播等待、数据落盘、文件系统卸载休眠 1s进程冻结、设备挂起唤醒 1s中断延迟、设备恢复、进程解冻5.9 内存状态流程内存操作数据保留开机从 Flash 重新加载所有数据和代码❌ 全部丢失关机脏页 flush 到 Flash内存断电❌ 全部丢失休眠RAM 进入自刷新模式持续供电✅ 完整保留唤醒RAM 退出自刷新数据直接可用✅ 完整保留六、关键差异的本质状态保持 vs 状态重建通过以上九维度的对比可以提炼出一个根本性的差异。6.1 冻结/解冻模型休眠唤醒休眠前 系统正在运行 │ ▼ freeze冻结 休眠中 系统静止但一切保持原位 │ 进程原地冻结 │ 内存自刷新供电 │ 寄存器保存 │ ▼ thaw解冻 唤醒后 系统继续运行 —— 仿佛什么都没发生休眠唤醒的快来自三个层面的状态保持硬件层RAM 自刷新保持数据外设唤醒源持续监听内核层进程仅被冻结状态机暂停而非杀死和重建框架层服务保持注册状态Activity 栈完整保留6.2 拆除/重建模型开关机开机 从零开始 BootROM → BootLoader → Kernel → init → Zygote → SystemServer → 用户 关机 有序拆除 广播 → AMS终止 → 服务关闭 → 文件系统卸载 → 内核断电开关机的慢来自必须重建的一切内核必须重新初始化数百个子系统Zygote 必须重新预加载数千个 Java 类SystemServer 必须重新启动数十个系统服务每个 App 必须冷启动七、为什么移动设备选择休眠而非关机来省电理解了以上差异就可以回答一个经常被问到的问题为什么手机不直接关机来彻底省电7.1 体验优势休眠恢复 1s关机重启 30s用户期望手机瞬间可用而非等待半分钟7.2 后台任务保障休眠期间 Alarm 定时唤醒系统执行后台任务如同步邮件、更新位置关机后一切停止无法执行任何定时任务7.3 功耗可接受休眠功耗通常在几毫瓦级别RAM 自刷新功耗相比彻底关机0 功耗休眠功耗的增加在电池续航中占比极小Doze 模式Android 6 引入进一步优化了长期休眠的网络访问策略7.4 状态连续性用户不需要重新打开应用、恢复工作状态Activity 栈、输入焦点、滚动位置全部保持八、关键源码文件索引文件层级涉及流程PowerManagerService.javaFramework休眠/唤醒入口mWakefulness 状态机ShutdownThread.javaFramework关机流程核心调度ZygoteInit.javaFramework开机类预加载、fork SystemServerSystemServer.javaFramework开机三阶段服务启动ActivityManagerService.javaFramework进程管理、Activity 栈管理kernel/power/process.cKernel进程冻结/解冻kernel/power/suspend.cKernel内核挂起/恢复核心逻辑kernel/reboot.cKernel关机/重启系统调用九、本篇总结本文从触发方式、内核状态、进程管理、虚拟机、系统服务、Activity、硬件外设、耗时时长、内存状态九个维度系统对比了开机、关机、休眠、唤醒的差异。核心结论休眠唤醒是冻结/解冻模型— 系统原地暂停、原地恢复不做任何拆除和重建开关机是拆除/重建模型— 关机有序拆除一切开机从零重建一切移动设备选择休眠— 基于体验亚秒恢复、功耗毫瓦级、状态连续性不丢上下文的综合考量下一篇Android 7系统休眠唤醒五休眠全链路—PMS到Kernel Suspend — 从 Java 框架层的 PowerManagerService 开始一路下穿到 Linux 内核的pm_suspend()完整追踪一次休眠操作的调用链。