Android 7系统休眠唤醒(一)电源管理架构全景图
2026/7/26 3:26:54 网站建设 项目流程

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


一、为什么要理解休眠唤醒

移动设备与 PC 在电源管理上有本质区别。PC 可以随时插电使用,而手机依赖电池供电,必须在"性能"和"续航"之间做精细平衡。Android 为此设计了一套从应用到内核、跨越四层软件栈的电源管理体系。

当你遇到以下问题时,答案都在这套体系之中:

  • “为什么 App 申请了 WakeLock,设备还是会休眠?”——WakeLock 的 level 可能不够高,或者 PMS 的mWakeLockSummary汇总时被覆盖了
  • “为什么设备休眠后无法通过 Alarm 唤醒?”——Alarm 的 type 可能不是RTC_WAKEUPELAPSED_REALTIME_WAKEUP
  • “为什么功耗测试显示设备从未进入 deep sleep?”——内核 wakelock 可能被某个驱动持锁,/sys/power/wake_lock可以排查

这套体系的核心思想:当用户不使用设备时,让它尽可能深地睡眠;当用户需要使用设备时,让它在一秒之内恢复


二、三种状态转移模型

Android 系统的电源状态可以抽象为三种粒度的转移:

2.1 宏观级别:关机 ↔ 开机

最彻底的状态切换。关机将操作系统完整卸载、硬件完全掉电;开机则从 BootROM 开始,经历 BootLoader → Kernel → init → Zygote → SystemServer → Launcher 的完整启动链。

维度说明
耗时开机 30-60 秒,关机 5-15 秒
状态保留无。所有内存数据、进程状态、寄存器上下文全部丢失
功耗关机后几乎为零(仅 RTC 时钟供电)

2.2 中观级别:休眠 ↔ 唤醒

这是本系列的核心。休眠时 CPU 进入深度睡眠状态(deep idle / suspend),仅保留 RAM 自刷新供电和外设唤醒源。唤醒时,从中断触发到屏幕点亮通常在 1 秒以内完成。

维度说明
耗时休眠 < 1 秒,唤醒 < 1 秒
状态保留完整。进程页表、ART 虚拟机堆、Activity 栈全部保留在 RAM 中
功耗仅 RAM 自刷新 + RTC + 唤醒源监听,功耗极低

2.3 微观级别:亮屏 ↔ 暗屏

最轻量级的切换,仅涉及DisplayPowerController控制屏幕背光和显示层,不涉及 CPU 挂起。通常由用户操作(触摸屏幕、按下按键)或接近传感器触发。


三、Android 电源管理四层架构

Android 电源管理跨越四层软件栈,每层有明确的职责边界:

┌──────────────────────────────────────────────────────┐ │ 应用层 (Application Layer) │ │ PowerManager API / WakeLock 申请与释放 │ │ frameworks/base/core/java/android/os/PowerManager │ ├──────────────────────────────────────────────────────┤ │ 框架层 (Framework Layer) │ │ PowerManagerService / DisplayPowerController │ │ Notifier / ShutdownThread │ │ frameworks/base/services/core/java/com/android/ │ │ server/power/ │ ├──────────────────────────────────────────────────────┤ │ Native 层 (Native Layer) │ │ libsuspend / suspend_blocker / Power HAL │ │ system/core/libsuspend/ │ │ hardware/libhardware/include/hardware/power.h │ ├──────────────────────────────────────────────────────┤ │ 内核层 (Kernel Layer) │ │ wakelock / autosleep / alarmtimer │ │ kernel/power/ │ │ drivers/rtc/alarm-dev.c │ └──────────────────────────────────────────────────────┘

3.1 应用层:PowerManager API

应用程序通过PowerManager.WakeLock通知系统"我正在做重要的事,不要休眠"。

源码路径frameworks/base/core/java/android/os/PowerManager.java

publicfinalclassPowerManager{// WakeLock 级别(从低到高)publicstaticfinalintPARTIAL_WAKE_LOCK=0x00000001;// 仅保持 CPU 运行publicstaticfinalintSCREEN_DIM_WAKE_LOCK=0x00000006;// 保持 CPU + 暗屏publicstaticfinalintSCREEN_BRIGHT_WAKE_LOCK=0x0000000a;// 保持 CPU + 亮屏publicstaticfinalintFULL_WAKE_LOCK=0x0000001a;// 保持 CPU + 亮屏 + 键盘publicWakeLocknewWakeLock(intlevelAndFlags,Stringtag){returnnewWakeLock(levelAndFlags,tag,mContext.getOpPackageName());}publicfinalclassWakeLock{publicvoidacquire(){...}// 获取锁,阻止休眠publicvoidacquire(longtimeout){...}// 带超时的获取publicvoidrelease(){...}// 释放锁}}

关键设计WakeLock默认非引用计数(setReferenceCounted(false)),多次acquire()只需一次release()即可释放。如果设为引用计数模式,则必须acquire()release()次数匹配。

3.2 框架层:PowerManagerService

PowerManagerService(PMS)是休眠唤醒的"中枢大脑",运行在 SystemServer 进程中。

源码路径frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

publicfinalclassPowerManagerServiceextendsSystemService{// 唤醒状态机:四种状态privateintmWakefulness;// AWAKE → DREAMING → DOZING → ASLEEPprivatebooleanmWakefulnessChanging;// 状态迁移中标志// WakeLock 聚合状态:所有活跃 WakeLock 的位掩码汇总privateintmWakeLockSummary;// 每个 bit 代表一种 WakeLock 类型// 脏标记:指示哪部分电源状态需要更新protectedintmDirty;// 位掩码,驱动 updatePowerStateLocked() 的增量更新}

关键设计:PMS 用mDirty位掩码驱动增量更新——当某个条件变化时(如 WakeLock 变化、亮度变化),只设置对应的 dirty bit,updatePowerStateLocked()根据 dirty bits 分阶段处理,避免全量重算。

Wakefulness 状态机沿固定方向迁移:

AWAKE ──→ DREAMING ──→ DOZING ──→ ASLEEP ↑ ↑ ↑ │ │ │ │ │ └─────────┴───────────┴───────────┘ (用户交互 / 唤醒事件)
  • AWAKE:屏幕亮,设备完全可用
  • DREAMING:屏幕变暗,可能进入屏保(Daydream)
  • DOZING:Doze 模式,限制网络和后台任务
  • ASLEEP:CPU 挂起,仅 RAM 自刷新

关键设计:状态迁移是单向的(AWAKE → ASLEEP),唤醒时直接跳回 AWAKE。mWakefulnessChanging标志在状态迁移过程中置位,防止并发状态变更。

3.3 Native 层:libsuspend 与 Power HAL

libsuspend是用户空间与内核休眠机制的桥梁。两种实现方式:

源码路径system/core/libsuspend/autosuspend_wakeup_count.c

  1. wakeup_count 方式:读取/sys/power/wakeup_count获取当前值,写入/sys/power/state为 “mem” 触发休眠。如果在读取和写入之间产生了新的唤醒事件,wakeup_count 不匹配,内核拒绝休眠并返回错误。

源码路径system/core/libsuspend/autosuspend_autosleep.c

  1. autosleep 方式:写入/sys/power/autosleep为 “mem”,内核在 autosleep 工作线程中自动尝试休眠,无需用户空间持续轮询。

Power HAL 定义硬件抽象层接口:

源码路径hardware/libhardware/include/hardware/power.h

关键接口:powerHint()— 向底层(cpufreq governor)传递电源提示;setInteractive()— 通知 HAL 交互模式变化。

3.4 内核层:wakelock 与 autosleep

Android 内核在 Linux 标准 suspend/resume 基础上,增加了 wakelock 和 autosleep 机制,确保在有活跃 wakelock 时不会错误休眠。

关键内核源码路径:

  • kernel/power/wakelock.c— wakelock 核心实现
  • kernel/power/autosleep.c— autosleep 工作线程
  • kernel/power/main.c— sysfs 节点注册(/sys/power/wake_lock/sys/power/wake_unlock
  • kernel/power/suspend.c— suspend 主路径(pm_suspend
  • kernel/power/process.c— 进程 freeze/thaw

四、休眠唤醒与开关机:核心区分

理解这四种流程的关键在于状态保持 vs 状态重建

关机→开机:状态完全重建 BootROM → BootLoader → Kernel → init → Zygote → SystemServer → Launcher 内核重载、进程全部冷启动、ART 堆清零重分配 休眠→唤醒:状态完全保持 内核仍在运行(仅 CPU 暂停) 进程被 freeze(冻结)而非 kill ART 虚拟机堆内存完整保留 Activity 栈原样保存 恢复时只需 thaw(解冻)→ 恢复外设 → 点亮屏幕

关键:休眠唤醒的核心优势是"状态保持"——不需要重新加载内核、不需要重启进程、不需要重新初始化服务。这解释了为什么唤醒只需不到 1 秒,而开机需要 30-60 秒。


五、关键源码文件索引

层级文件本文涉及内容
Frameworkframeworks/base/services/core/java/com/android/server/power/PowerManagerService.javaPMS 核心,Wakefulness 状态机、mDirty 增量更新
Frameworkframeworks/base/services/core/java/com/android/server/power/Notifier.java电源状态广播(SCREEN_ON/OFF)
Frameworkframeworks/base/services/core/java/com/android/server/power/ShutdownThread.java关机/重启调度
Frameworkframeworks/base/core/java/android/os/PowerManager.java应用层 WakeLock API
Nativesystem/core/libsuspend/autosuspend.c自动休眠核心实现
Nativesystem/core/libsuspend/autosuspend_wakeup_count.cwakeup_count 方式休眠
Nativesystem/core/libsuspend/autosuspend_autosleep.cautosleep 方式休眠
HALhardware/libhardware/include/hardware/power.hPower HAL 接口定义
Kernelkernel/power/wakelock.c内核 wakelock 实现
Kernelkernel/power/autosleep.c内核 autosleep 线程
Kernelkernel/power/suspend.cSuspend 主路径
Kernelkernel/power/process.c进程 freeze/thaw

六、系列阅读路线

第 1 篇(本篇)全景图 │ ├─→ 第 2 篇:开机全链路(建立"全量启动"的基准认知) │ │ │ └─→ 第 3 篇:关机/重启全链路(理解"全量销毁"的代价) │ │ │ └─→ 第 4 篇:休眠唤醒 vs 开关机 对比(核心交汇点) │ │ │ ┌───────────┼───────────┐ │ │ │ │ 第 5 篇:休眠全链路 第 6 篇:唤醒全链路 │ (Framework → Kernel) (Kernel → Framework) │ │ │ │ └───────────┬───────────┘ │ │ │ 第 7 篇:内核wakelock 第 8 篇:Alarm唤醒源 │ │ │ 第 9 篇:Native 层 & Power HAL │ │ └─────────── 第 10 篇:实战调试与问题排查
  • App 开发者:重点读第 1、4、5、6、10 篇,理解 WakeLock 的申请释放与功耗影响
  • Framework 开发者:通读全系列,核心是第 2-6 篇
  • 驱动/Kernel 开发者:重点关注第 4-8 篇,特别是第 5、6、7、8 篇

七、小结

本篇建立了 Android 电源管理的顶层认知:

概念说明
三种状态转移关机↔开机(全量重建)、休眠↔唤醒(状态保持)、亮屏↔暗屏(仅背光)
四层架构应用层(WakeLock API)→ 框架层(PMS 状态机)→ Native 层(libsuspend)→ 内核层(wakelock/autosleep)
核心区分状态保持(休眠唤醒)vs 状态重建(开关机)

后续篇章将逐层深入——下一篇从"开机"开始,走完从 BootROM 到 Launcher 的完整启动链路,为理解"休眠唤醒跳过了什么"打下基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询