Android 7系统休眠唤醒(三)关机_重启全链路—ShutdownThread到kernel_power_off

发布时间:2026/7/24 5:16:17
Android 7系统休眠唤醒(三)关机_重启全链路—ShutdownThread到kernel_power_off 系列目录第一篇电源管理架构全景图 | 第二篇开机全链路—BootROM到Launcher | 第三篇关机/重启全链路—ShutdownThread到kernel_power_off | 第四篇休眠唤醒与开关机—核心差异深度对比 | 第五篇休眠全链路—PMS到Kernel Suspend | 第六篇唤醒全链路—Kernel Resume到屏幕点亮 | 第七篇内核层—wakelock与autosleep机制 | 第八篇内核层—Alarm定时唤醒与硬件唤醒源 | 第九篇Native层—libsuspend与Power HAL | 第十篇实战调试与问题排查一、为什么要理解关机流程你有没有遇到过这些情况点击关机后屏幕卡在正在关机…对话框上十几秒用户以为死机了再按电源键也没反应拔电池强制关机后下次开机发现应用数据丢失甚至陷入正在优化应用的启动循环调试时发现ACTION_SHUTDOWN广播有时收不到有时收到了但onReceive()还没执行完设备就断电了这些问题的答案都藏在 ShutdownThread 到 kernel_power_off 这条关机链路的源码里。如果开机是从零开始重建世界那么关机就是有秩序地拆除这个世界——它并非简单的断电而是一条精心编排的资源回收链从用户层的广播通知到系统服务的逐一停摆到文件系统的安全卸载最后才调用内核接口彻底断电。本篇将完整拆解这条链路。二、宏观架构关机流程全景在深入源码之前先建立全局视角。一次完整的关机经过六大阶段从上到下跨越 Android Framework → Native → Kernel 三层用户操作长按电源键 / 应用调用 shutdown() │ ▼ ShutdownThread.start() │ 获取 PARTIAL_WAKE_LOCK防止关机中途休眠 │ ├─→ 阶段1: ACTION_SHUTDOWN 有序广播 │ │ 各 App 接收广播执行清理逻辑 │ ▼ ├─→ 阶段2: AMS.shutdown() │ │ 终止 Activity、回收栈、清理进程 │ ▼ ├─→ 阶段3: PKMS 收尾 │ │ 写入包状态、更新权限 │ ▼ ├─→ 阶段4: 系统服务逐一关闭 │ │ WMS → Bluetooth → Telephony → Connectivity → Audio → Alarm → PMS │ ▼ ├─→ 阶段5: vold 卸载文件系统 │ │ umount /data、/cachesync 确保数据落盘 │ ▼ └─→ 阶段6: reboot(RB_POWER_OFF) │ ▼ kernel_power_off() │ 设备驱动卸载、外设掉电 │ machine_power_off() ▼ 完全断电整个流程的核心调度者是ShutdownThread——它贯穿始终协调各阶段的执行顺序。下面按调用链顺序逐层拆解。三、关机触发入口关机有三种触发方式最终都汇聚到ShutdownThread.shutdown()。3.1 长按电源键用户长按电源键 →PhoneWindowManager.interceptKeyBeforeQueueing()捕获长按事件 → 弹出GlobalActions对话框 → 用户选择关机。源码路径frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java源码路径frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java3.2 应用层调用 PowerManager源码路径frameworks/base/core/java/android/os/PowerManager.javapublicclassPowerManager{finalIPowerManagermService;// Binder 代理指向 PowerManagerServicepublicvoidshutdown(booleanconfirm,Stringreason,booleanwait){mService.shutdown(confirm,reason,wait);}}任何持有android.permission.DEVICE_POWER权限的应用都可以调用此接口。最终通过 Binder 调用到PowerManagerService。关键设计PowerManager.shutdown()只是一个薄薄的 Binder 代理层真正的关机逻辑在PowerManagerService中最终汇聚到ShutdownThread。3.3 低电量自动关机BatteryService 监测到电量低于阈值后可以触发自动关机。源码路径frameworks/base/services/core/java/com/android/server/BatteryService.java四、ShutdownThread — 关机流程的核心调度者无论哪种触发方式最终都会调用到ShutdownThread.shutdown()。ShutdownThread 是一个 HandlerThread其run()方法中执行关机主逻辑。同时它持有PARTIAL_WAKE_LOCK确保在整个关机过程中 CPU 持续运行不会中途休眠。源码路径frameworks/base/services/core/java/com/android/server/power/ShutdownThread.javapublicclassShutdownThreadextendsThread{privatestaticfinalStringTAGShutdownThread;privatestaticShutdownThreadsInstance;// 单例全局只有一个关机线程privateContextmContext;privateStringmReason;// 关机原因shutdown / reboot / recovery 等publicstaticvoidshutdown(Contextcontext,Stringreason,booleanconfirm){// 显示关机进度对话框// 延迟短暂时间让对话框渲染// 启动 ShutdownThread 线程beginShutdownSequence(context);}privatestaticvoidbeginShutdownSequence(Contextcontext){sInstancenewShutdownThread(context,reason,...);sInstance.start();// 启动线程进入 run() 执行关机主逻辑}}关键设计ShutdownThread 是单例sInstance全局只有一个关机线程天然避免了重复关机请求导致的并发问题。五、关机六大阶段ShutdownThread.run() 内部按顺序执行六个阶段每个阶段完成一部分资源回收工作。5.1 阶段一广播 ACTION_SHUTDOWN关机第一步向系统中所有已注册的应用发送Intent.ACTION_SHUTDOWN有序广播。源码路径frameworks/base/services/core/java/com/android/server/power/ShutdownThread.javaIntentintentnewIntent(Intent.ACTION_SHUTDOWN);intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);mContext.sendOrderedBroadcastAsUser(intent,...);这是有序广播Ordered Broadcast按照 receiver 的优先级依次传递。每个 receiver 有机会在关机前做最后的清理工作保存未持久化的数据停止后台任务注销监听器向服务器发送离线通知关键设计使用有序广播而非普通广播保证高优先级 receiver 先执行如系统服务且任意环节出错不会导致后续停止——广播超时机制会兜底跳过超时未响应的 receiver。5.2 阶段二AMS 终止所有 Activity 和进程广播发送完成后调用ActivityManagerService.shutdown()。源码路径frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapublicclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{// ...publicbooleanshutdown(inttimeout){// 强制停止所有 Activity// 回收所有 Activity 栈// 清理 PendingIntent// 终止后台进程// 保存进程状态快照用于下次开机恢复}}AMS 此时执行的工作包括向所有正在运行的 Activity 发送onPause()→onStop()→onDestroy()清理所有 ActivityRecord 和 TaskRecord回收进程记录ProcessRecord但不立即 kill 所有进程——后续阶段还需要一些进程配合关键设计AMS 只回收 Activity 栈和进程记录不立即 kill 进程——后续阶段的文件系统卸载还需要 vold 等进程配合执行。5.3 阶段三PackageManager 收尾PackageManagerService 在关机前处理尚未完成的 APK 安装/卸载请求将包的元信息写回持久化存储。源码路径frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java具体操作包括处理待安装/待卸载的包、更新包的权限记录、刷新 PackageUsage 统计。Settings.writeLPw()将包的元信息写入/data/system/packages.xml。源码路径frameworks/base/services/core/java/com/android/server/pm/Settings.java5.4 阶段四系统服务逐一关闭这一阶段SystemServer 中注册的各个服务按依赖顺序逐一关闭服务关闭操作源码路径WindowManagerService释放所有 Surface断开与 SurfaceFlinger 的连接frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.javaBluetoothService断开蓝牙连接关闭蓝牙芯片frameworks/base/services/core/java/com/android/server/BluetoothManagerService.javaTelephonyRegistry关闭 RIL 连接注销 Modem 事件监听frameworks/base/services/core/java/com/android/server/TelephonyRegistry.javaConnectivityService断开网络连接关闭 WiFiframeworks/base/services/core/java/com/android/server/ConnectivityService.javaAudioService静音、关闭音频通路frameworks/base/services/core/java/com/android/server/audio/AudioService.javaAlarmManagerService取消所有待触发 Alarmframeworks/base/services/core/java/com/android/server/AlarmManagerService.javaPowerManagerService释放所有 WakeLock禁用 autosleepframeworks/base/services/core/java/com/android/server/power/PowerManagerService.java关键设计服务关闭顺序遵循依赖关系——先关闭依赖其他服务的上层服务如 WMS 依赖 SurfaceFlinger最后关闭被依赖的基础服务如 PMS。5.5 阶段五存储卸载voldVolume Daemon负责安全卸载所有挂载的文件系统。源码路径system/vold/umount/dataumount/cachesync# 强制将缓冲区数据刷入存储关键设计在卸载文件系统之前必须调用sync强制将所有脏页dirty pages从 Page Cache 刷入存储。如果跳过这一步直接断电未写入的数据将永久丢失可能导致文件系统损坏。5.6 阶段六内核层 — 调用 reboot() 系统调用最后一步ShutdownThread 调用 Linux reboot 系统调用。源码路径frameworks/base/services/core/java/com/android/server/power/ShutdownThread.javaSystemProperties.set(sys.powerctl,shutdown,reason);// 或者直接调用PowerManagerService.lowLevelReboot(shutdown);底层最终执行reboot(RB_POWER_OFF)触发内核的kernel_power_off()。源码路径kernel/reboot.cvoidkernel_power_off(void){kernel_shutdown_prepare(SYSTEM_POWER_OFF);// 调用所有注册的 reboot_notifier// 卸载所有设备// 执行 machine_power_off() → 硬件掉电}关键设计kernel_shutdown_prepare()会遍历所有注册的reboot_notifier链让各内核子系统文件系统、块设备、驱动等在最终断电前完成各自的清理工作。六、重启Reboot的特殊路径重启与关机的差异在于最后一步不是RB_POWER_OFF而是RB_AUTOBOOT。6.1 reboot 的原因码源码路径frameworks/base/services/core/java/com/android/server/power/ShutdownThread.javapublicclassShutdownThreadextendsThread{// ...publicstaticvoidreboot(Contextcontext,Stringreason,booleanconfirm){// reason 可以是// - (空字符串)普通重启// - recovery重启到 recovery 模式// - bootloader重启到 fastboot 模式// - download重启到下载模式}}关键设计reason参数通过sys.powerctl系统属性传递给内核内核根据不同的 reason 值选择不同的重启目标而前五个阶段的清理流程完全一致。6.2 重启时的日志保存重启前ShutdownThread 会写入一条重启原因记录到持久化存储SystemProperties.set(sys.boot.reason,reason);内核在重启前的kernel_restart_prepare()中会将最后的内核日志保存到 pstorePersistent Storage——这是一块在重启过程中不会被清零的 RAM 区域重启后可从/sys/fs/pstore/console-ramoops读取。源码路径fs/pstore/6.3 重启流程对比关机步骤关机重启ACTION_SHUTDOWN 广播✅✅AMS 终止 Activity✅✅服务关闭✅✅文件系统卸载✅✅reboot() 参数RB_POWER_OFFRB_AUTOBOOT内核行为kernel_power_off() → 断电kernel_restart() → 重新加载内核结果设备完全掉电设备重新开机七、关键设计考量7.1 有序广播的必要性关机广播不是普通广播而是有序广播。这保证了高优先级 receiver 先执行如系统服务优先于普通应用每个 receiver 可以延迟广播传递例如需要等待数据保存完成任意环节出错不会导致后续停止广播超时机制兜底跳过超时未响应的 receiver不会出现关机了一半 App 还在写文件的竞态问题7.2 为什么关机需要 PARTIAL_WAKE_LOCK关机的整个过程中设备处于正在使用中的状态——屏幕可能亮着显示关机进度服务在运行数据在写入。如果此时系统自动进入休眠关机流程将卡在半途——CPU 停止后后续的sync、umount、reboot()都不会执行。因此 ShutdownThread 在启动时获取 PARTIAL_WAKE_LOCK确保 CPU 在关机过程中持续运行直到最后一步调用reboot()系统调用为止。7.3 sync 的重要性在卸载文件系统之前必须调用sync系统调用强制将所有脏页从 Page Cache 刷入存储。如果跳过这一步直接断电未写入的数据将永久丢失可能导致文件系统损坏下次开机时触发fsck修复甚至丢失数据。八、关键源码文件索引文件层级角色PowerManager.javaFramework API提供shutdown()/reboot()公开接口ShutdownThread.javaFramework Service关机流程核心调度者六大阶段的执行引擎PhoneWindowManager.javaFramework Service拦截电源键长按事件ActivityManagerService.javaFramework Service终止所有 Activity 和进程PackageManagerService.javaFramework Service保存包状态到packages.xmlWindowManagerService.javaFramework Service释放 Surface断开 SurfaceFlingersystem/vold/Native卸载文件系统执行 synckernel/reboot.cKernelkernel_power_off()/kernel_restart()fs/pstore/Kernel保存重启前内核日志的持久化存储九、本篇总结关机流程是一个有序拆除的过程而非简单的拉闸断电。它包含六大阶段向所有应用广播关机通知AMS 终止所有 Activity 和进程PackageManager 保存包状态系统服务按依赖顺序关闭vold 安全卸载文件系统并 sync调用内核接口断电整个过程确保数据不丢失、文件系统不损坏、服务正常断开连接。下一篇Android 7系统休眠唤醒四休眠唤醒与开关机—核心差异深度对比 — 理解了关机的有序拆除再对比休眠唤醒休眠是把整个系统冻结在原地而非拆除这恰恰是它能在亚秒级恢复的根本原因。