Android 13 关机流程分析:从上层触发到内核断电全链路
Android 13 关机流程分析这段时间在追一个关机相关的疑难问题把 Android 13 的关机流程从上层到内核完整梳理了一遍。说实话这个流程平时不会有人主动去读但一旦遇到“关机卡死”“重启不进系统”“关机动画黑屏”这类问题没有全局视角就很被动。这篇把我梳理的结论和排查思路完整写出来包括入口、核心线程、系统服务联动、底层参数传递以及几个常见的坑给同样需要跟这个流程的兄弟做个参考。1. 关机流程的整体骨架与三条触发路径先说结论Android 13 的关机流程不是一个“单线程”的线性过程而是分层的状态机协作。整个流程涉及 SystemUI、SystemServer 里的多个服务、Native 层、内核任何一层出问题表现出来的都是“关不掉”或者“关不干净”。从触发入口看日常会碰到的路径有三条用户长按电源键弹出电源菜单点击“关机”或“重启”。这是最常见的一条入口在 SystemUI。adb reboot或adb shell reboot命令触发。这个走的是 Shell 命令通道最终同样汇聚到 SystemServer 的 ShutdownThread。系统检测到关键错误比如 Watchdog 超时、电池温度过高触发保护由系统主动调用PowerManagerService.shutdown()或reboot()。这条路径不带 UI 提示直接执行。三条路径最终会汇合到一个核心类ShutdownThread。它位于 framework 层包名com.android.server.power是整个关机流程的“发动机”。无论从哪条路进来最后都会走到ShutdownThread.shutdown()或ShutdownThread.reboot()这两个静态方法。在研究流程前建议先在frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java这个文件里把整体骨架读一遍这个类不算长但信息密度很高。我建议按“入口方法 → 状态推进 → 广播通知 → 退出”的顺序去读不要上来就抠细节。// 入口之一PowerManagerService 中调用 public void shutdown(final String reason, boolean confirm) { // confirm 表示是否需要 UI 确认 ShutdownThread.shutdown(mContext, reason, confirm); }这里有一个关键点很多人会忽略confirm这个布尔值。当 confirm 为 true 时ShutdownThread 不会立即执行关机而是会先弹出关机确认对话框等用户确认后才真正开始。如果是在 AOSP 默认的 power menu 里SystemUI 已经做过一次确认了传给 PMS 的 confirm 一般是 false。但如果你在做差分改了 SystemUI 的电源菜单这里很容易出现“关机确认框重复弹两次”或者“点了关机没反应”的现象。另外要区分shutdown和reboot的差异。reboot 支持传入reason这个 reason 会作为ro.boot.bootreason的一部分传给内核也会被BootReceiver记录下来写入persist.sys.boot.reason而 shutdown 的 reason 相对简单。业界在分析“重启原因”时经常就是根据这个参数来判断是用户手动重启、OTA 重启还是 watchdog 触发所以排查类的项目里这两个入口要分开看。2. ShutdownThread 核心状态推进与动作编排ShutdownThread 里的核心方法是run()它决定了整个关机动作的执行顺序。Android 13 的代码里run() 的逻辑大体分这几个阶段检查并设置关机原因写入系统属性。发出ACTION_SHUTDOWN广播通知所有注册了这个广播的组件开始收尾。依次调用各关键服务InputManager、WindowManager、MountService 等执行预关闭动作。逐步降低屏幕亮度、关闭 UI 相关组件。调用底层接口真正断电或重启。把源码简化一下run() 的开头是这样的public void run() { ... // 阶段1检查重启原因并设置属性 if (mReboot) { ... rebootViaActions(mRebootReason); } else { shutdownViaActions(); } ... }这里我建议先看shutdownViaActions()和rebootViaActions()这两个私有方法。Android 13 里这两个方法是整个关机动作编排的核心里面有大量对“顺序”的依赖。比如必须先发ACTION_SHUTDOWN广播让所有 App 有机会保存数据然后才能关闭 MountService否则正在写存储的应用会直接丢数据。2.1 广播通知阶段为什么 ACTION_SHUTDOWN 那么重要系统在真正断电前会先发送一个全局有序广播Action 是Intent.ACTION_SHUTDOWN。这是一个 ordered broadcast意味着每个接收者执行完后才会轮到下一个系统会等待所有接收者完成。这一步的主要目的是让应用有机会做数据保存、释放资源、停止后台任务。Intent intent new Intent(Intent.ACTION_SHUTDOWN); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendOrderedBroadcastAsLooper(intent, null, mShutdownListener, ...);在实际分析中要注意这个广播是阻塞式的。如果某个应用在onReceive里做了耗时操作比如同步数据到云端关机流程会一直等它通常系统会有一个超时控制但超时时间比较长体感就是“卡在关机动画很久”。从 Android 12 开始系统对广播接收器的后台执行限制更严格了但ACTION_SHUTDOWN是系统级广播不受Background Execution Limits限制依然可以启动组件。这一点在兼容性测试中很关键如果你们的 App 在关机时没有收到广播或者收到后被杀需要重点检查是否在清单里显式声明了android:exported和权限保护。2.2 reboot 与 shutdown 的分叉点在rebootViaActions()中代码会根据重启原因决定走不同的子流程。private void rebootViaActions(String reason) { ... if (reason.equals(PowerManager.REBOOT_RECOVERY)) { // 重启到 Recovery } else if (reason.equals(PowerManager.REBOOT_BOOTLOADER)) { // 重启到 Bootloader } else { // 普通重启 } }调试时可以通过adb shell reboot recovery或adb shell reboot bootloader来验证这条分支。注意这里的字符串是固定的如果自己接三方工具或车机方案传参不一致会导致重启到错误分区。另外还必须说一个常见问题——reboot.override属性。这个属性在 OTA 相关流程中经常出现adb shell setprop reboot.override recovery adb shell reboot设置了reboot.override之后即使调用的 reboot 不带 reason底层也会强制按 override 指定的模式重启。分析时如果发现“明明是普通重启却进了 recovery”大概率就是这个属性被某个 OTA 或系统更新组件设置后没清掉。每次重启后系统应该清掉它但有些定制系统在异常重启时不会清理。3. 系统服务的联动与底层参数传递ShutdownThread 只是编排者真正干活的是各个系统服务。Android 13 中关机流程涉及的核心服务有这么几个PowerManagerService负责电源状态管理、重启原因的设置。InputManagerService在关机时屏蔽触摸事件防止用户误触。WindowManagerService关闭所有窗口、使其不可见。MountService卸载所有已挂载的存储设备避免数据损坏。BatteryService和BatteryLight配合在关机充电时显示电池状态。AlarmManagerService在重启后设置 RTC 闹钟。其中最容易出问题的就是 MountService 这一步。它会尝试对所有已挂载的卷执行 unmount如果有应用正占着文件句柄unmount 会失败或超时。Android 13 里对 timeout 的机制做了一些调整但问题依旧存在。3.1 PMS 层 shutdown 与 reboot 的三种实现PowerManagerService里和关机直接相关的方法有shutdown()进入关机流程不入 recovery不重启。reboot()执行重启可带 reason。rebootSafeMode()进入安全模式它内部也是调用 reboot但会设置一个特殊 reason。在实际代码里它们的调用关系大致是public void reboot(String reason) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.REBOOT, reboot); ... ShutdownThread.reboot(mContext, reason, false); }这里要注意权限检查。REBOOT权限是 signature 级别普通应用无法调用。如果是做系统级 App 或车机方案需要在 Manifest 里声明android:permissionandroid.permission.REBOOT才能调通。3.2 JNI 层与内核的交接当 Java 层的所有服务都完成收尾后ShutdownThread 会调用PowerManagerService.lowLevelShutdown()或lowLevelReboot()这两个方法通过 JNI 进入 Native 层最终调用reboot()系统调用。public static void lowLevelReboot(String reason) { if (reason null) { reason ; } nativeReboot(reason); }JNI 对应的实现在frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cppstatic void nativeReboot(JNIEnv* env, jclass clazz, jstring reason) { const char* reasonChars env-GetStringUTFChars(reason, NULL); reboot(ANDROID_RB_RESTART2, reasonChars); }这个reboot()最终会通过syscall触发内核的kernel_restart整个 Android 用户空间到此基本退出。在内核侧reboot系统调用会被kernel/reboot.c处理。如果带 reason内核会把它保存到restart_msg供 bootloader 读取。这一步直接决定重启后进入哪个分区所以车机或嵌入式方案里如果 bootloader 没正确读取restart_msg就会出现“重启后进了 fastboot”“重启后起不来”的问题。4. 关键日志与常见问题排查关机流程的排查本质上就是看日志和属性。我一般会先抓这几类logcat -b system -b events看 SystemServer 的关机日志。logcat -b crash看关机阶段有没有 crash。dmesg看内核日志确认最后一步是否执行。getprop | grep sys.boot看启动阶段的属性。4.1 常见问题速查表现象可能原因排查方法点击关机无反应SystemUI 电源菜单未回调 PMS或 confirm 参数异常抓 SystemUI 日志看点击事件是否调用了PowerManager.shutdown()关机动画卡死某个应用在ACTION_SHUTDOWN广播回调中耗时太长抓 events 日志看 ACTION_SHUTDOWN 的发送与接收时间戳重启后进入 recovery存在残留的reboot.override属性adb shell getprop reboot.override查看并清除重启后 bootloader 模式异常底层restart_msg传递不正确抓 dmesg确认reboot系统调用参数存储数据损坏MountService 卸载超时卷未正常 unmount检查 MountService 日志看 Vold 状态关机过程 ANR后台应用在主线程执行了磁盘 IO抓 ANR trace确认是哪个应用阻塞4.2 一个典型的关机 ANR 案例我之前遇到一个案子现象是关机动画播放到一半卡住大约 20 秒后系统强制杀掉了所有后台进程最终才完成关机。抓日志后发现某个第三方应用在ACTION_SHUTDOWN广播回调里做了数据库同步而且是在onReceive主线程里直接开的网络请求导致广播超时。这类问题的排查思路是抓取logcat -b events查看am_broadcast_discard或am_anr相关日志。如果看到Action: android.intent.action.ACTION_SHUTDOWN对应的进程一直没返回就基本锁定。再用kill -3 pid抓 ANR trace看堆栈是否卡在网络库或 IO。最后跟应用团队确认将所有耗时操作移到goAsync()或后台线程。Android 13 上这个问题的超时控制相比早期版本更严格了特别是对 BroadcastReceiver 的onReceive返回时间有要求。建议所有做系统应用的人在ACTION_SHUTDOWN回调里只做轻量操作重的活得放到goAsync()里并且设一个自己的超时保护。4.3 另一个坑ShutdownThread 卡在“等待 MountService”同样常见的是 ShutdownThread 等待 MountService 完成卸载但 vold 因为某个进程占用文件系统迟迟无法 unmount。这种情况下logcat里会看到反复打印ShutdownThread: Waiting for MountService ...解决方法分两层应用层排查哪些进程持有FileDescriptor一般是有 Daemon 进程或媒体扫描进程。系统层如果确认是某个系统组件导致可以调 ShutdownThread 里的超时时间。但这是治标不治本根本上还是要保证卸载流程通畅。还有一个容易忽略的是 Watchdog。ShutdownThread 在执行关机动作期间Watchdog 可能认为系统无响应而主动重启系统造成“关机中”又起了的现象。在排查时要同时关注 Watchdog 的日志特别是有没有打印WATCHDOG KILLING SYSTEM PROCESS。这种情况在低内存设备上更容易出现因为关机会占用大量资源。5. 实操复盘一次完整的关机日志采集与问题定位下面用我最近一次实操来演示怎么一步步把关机流程理清楚。5.1 准备阶段开启相关日志开关关机过程太快日志转瞬即逝所以第一步是预先打开日志缓冲和必要的调试选项。# 设置日志缓冲足够大避免旧日志被覆盖 adb shell logcat -G 16M # 开启 ShutdownThread 的 verbose 日志 adb shell setprop persist.sys.shutdown.debug true # 预先启动 logcat 到本地文件 adb shell logcat -b all -v threadtime /data/local/tmp/shutdown_log.txt 这里有个细节persist.sys.shutdown.debug不是 AOSP 标准属性是我在定制系统里加的调试开关。在 AOSP 上你可以用setprop sys.powerctl相关属性或者直接在 ShutdownThread 里加Log.v效果类似。5.2 触发关机并抓日志# 触发关机注意这里用 adb shell reboot 会直接重启而不是关机 adb shell reboot如果是抓关机流程建议用adb shell reboot而不是adb shell shutdown因为重启后logcat缓冲会保留重启前的日志更有对比价值。重启完成后第一时间把日志拉出来adb pull /data/local/tmp/shutdown_log.txt拿到日志后重点搜索以下关键字ShutdownThread核心流程看它走到了哪一步。ACTION_SHUTDOWN广播的发送和结束时间。MountService存储卸载的状态。vold底层卷管理的日志。boot_progress启动阶段的进度辅助判断上次关机是否干净。5.3 解读典型日志顺序一段正常的 ShutdownThread 日志大概是这样的ShutdownThread: begin shutdown ShutdownThread: Sending ACTION_SHUTDOWN broadcast ShutdownThread: Waiting for broadcast... ShutdownThread: Shutting down activity manager ShutdownThread: Shutting down mount service ShutdownThread: Shutdown complete, rebooting!如果有Sending ACTION_SHUTDOWN broadcast之后长时间没有Waiting for broadcast...输出说明卡在广播接收器上。这时要看am_broadcast_delivered对应的时间戳找到耗时最长的 receiver。真实项目中我见过一个更“隐晦”的情况广播正常发完了但ShutdownThread卡在Shutting down activity manager这是因为 AMS 在等待某些进程的stopLocked操作而那个进程的主线程被一个死锁卡住了。这种问题靠 logcat 不够通常要配合debuggerd和dumpsys activity才能定位。5.4 重启后的属性清理检查重启完成后务必要检查一次系统属性adb shell getprop sys.boot.reason adb shell getprop reboot.override正常情况下reboot.override应该是空sys.boot.reason的值类似reboot、shutdown、recovery或watchdog。如果sys.boot.reason显示的值和预期不符说明上层传递的 reason 有问题需要回溯 ShutdownThread 的入参。这里分享一个排查技巧把sys.boot.reason纳入日常 CI 检查很多“偶发重启”其实在重启原因里早就有线索了只是没人去看这个属性。批量抓设备上的sys.boot.reason能和常见异常模式快速对上号。6. 从 Android 13 出发的几点总结与后续思考这次完整走了一遍 Android 13 的关机流程我的整体感受是关机流程虽然历史悠久但每一代 Android 都在往“更安全、更可追踪”的方向调。Android 13 里对广播超时、服务调用顺序、属性记录的细节都比以前更严格这也意味着排查时必须更依赖日志而不是猜。几个我认为值得记住的点关机流程的入口很多但最终都汇聚到ShutdownThread分析时从它入手最靠谱。排查看日志日志看时间戳时间戳是理解关机流程顺序的钥匙。如果做定制系统可以从ShutdownThread里加自定义的上报点把每个阶段的耗时记下来这样线上问题才有据可查。最后说一个小建议如果你还没有完整读过ShutdownThread.java建议抽半天时间读一遍然后在模拟器上连续关机、重启几次把日志对照源码看一遍。这个流程读懂了以后遇到电源管理相关的疑难问题你至少知道从哪一层开始查。我后续还打算继续分析 Android 14 的关机流程差异以及 AOSP 与主流定制系统在关机时序上的不同实现。到时候再整理一篇对比出来。

相关新闻

房地产本体论解码·利益者与消费者体感的双重否定·社会内部破幻

房地产本体论解码·利益者与消费者体感的双重否定·社会内部破幻

BSD Step 226 ★★★★★ 中国房地产本体论解码利益者与消费者体感的双重否定社会主义叙事的内部破幻封闭性盲区的再次显化L1 层:06_全域结构学科 ​前承​:Step182(破社会主义幻与 Step170 破无神论幻平行固化幻 → 拥幻拥圣) St…

2026/10/17 2:49:40 阅读更多 →
Java 学习复盘:异常处理详解

Java 学习复盘:异常处理详解

哈喽各位 CSDN 小伙伴! 前面学完了面向对象、抽象类与接口,今天继续记录 Java 的异常知识点。写代码的时候总会遇到各种各样报错,有些是语法写错编译直接报错;还有一类是程序运行起来之后才出现的错误,比如空指针、数组…

2026/10/17 2:49:40 阅读更多 →
数据架构到底在“架”什么?从数据集成、加工、实时到交换,一篇讲透企业数据链路

数据架构到底在“架”什么?从数据集成、加工、实时到交换,一篇讲透企业数据链路

很多企业开始数字化建设以后,都会遇到一个共同的问题:系统越来越多,数据越来越丰富,但真正需要利用数据支撑经营决策时,却发现数据并没有想象中那么容易使用。销售订单记录在 ERP 系统中,客户信息沉淀在 CR…

2026/10/17 2:49:40 阅读更多 →

最新新闻

鸿蒙Flutter大规模列表优化:纯Dart工具list_utilities实战解析

鸿蒙Flutter大规模列表优化:纯Dart工具list_utilities实战解析

最近在做鸿蒙(HarmonyOS NEXT)列表页重构的时候,被一个老问题折磨得够呛:Flutter 生态里那些处理集合数据的工具库,拿到鸿蒙上要么编译不过,要么跑起来性能断崖式下跌。尤其是当数据量到十万级、还要做分组…

2026/10/17 3:34:53 阅读更多 →
变分信息瓶颈:让AI生成图像检测摆脱生成器指纹

变分信息瓶颈:让AI生成图像检测摆脱生成器指纹

1. 为什么"通用检测"是AI生成图像检测的硬骨头1.1 一条路走到黑的老路:绑定生成器指纹的分类器我做图像鉴伪这块有些年头了,前两年接到最多的需求是"帮我训练一个检测器,判断一张图是不是AI生成的"。当时最省事的做法&am…

2026/10/17 3:34:53 阅读更多 →
VB项目拆解OPC UA客户端:连接、读写与订阅全流程

VB项目拆解OPC UA客户端:连接、读写与订阅全流程

简介:这份压缩包提供基于VB(Visual Basic)编写的OPC UA客户端示例,并附带“OPC Helper 2.02”连接工具,面向工业自动化开发者与上位机编程学习者,帮助理解并实践OPC UA标准协议下的数据读写、订阅与安全认证…

2026/10/17 3:34:53 阅读更多 →
.NET6生产级WebAPI:SQL Server+JWT+事务+软删除实战

.NET6生产级WebAPI:SQL Server+JWT+事务+软删除实战

简介:本资源是一套基于.NET 6构建的完整Web API实战项目,面向C#后端开发初学者与进阶者,聚焦企业级API开发核心能力训练——SQL Server数据库集成、JWT无状态身份认证及标准CRUD接口实现。项目采用分层架构(含Model、Service、BLL…

2026/10/17 3:34:53 阅读更多 →
文件I/O与存储优化:从page cache到io_uring的实践指南

文件I/O与存储优化:从page cache到io_uring的实践指南

文件I/O与存储优化,这话题我这些年反复碰到。早年间帮某在线交易系统查问题,数据库明明没几条数据,写磁盘却慢得像蜗牛,后来发现是日志文件写了几十个G,还是同步写。还有一次是某消息队列组件,吞吐死活上不…

2026/10/17 3:34:53 阅读更多 →
千笔AI降AI率实战指南:原理、实操与避坑全解析

千笔AI降AI率实战指南:原理、实操与避坑全解析

最近好多学弟学妹跑来问我:“千笔AI到底能不能降AI率?我看好多人都说它是本科生神器,是不是真的?”说实话,这个问题我太有发言权了。我刚读研那会儿,第一次查AI率就被标了40%多,当时整个人是蒙的…

2026/10/17 3:33:53 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →