reboot/shutdown 场景热点行为全解
锚点案件:MANNPROB-2933(AI801/fermi reboot 重启前热点先关闭,2026-07-22 复现,分析定案 2026-08-17)。 单点分析全文:
车机JIRA/jira-data/MANNPROB-2933/analysis/root-cause.md;本文沉淀可复用的机制知识与取证方法。
1. 一条必须记住的因果链(adb reboot 路径)
adb reboot(reboot,shell)
→ init 分阶段停机:先 SIGTERM non-core daemon(hostapd/wpa_supplicant),core(zygote/system_server) 后停
→ 【相位差窗口】fermi A17 实测 ~820ms(daemon 死 44.95x → system_server 死 45.772)
→ system_server 眼里 daemon 死亡 = "崩溃"(adb 路径 framework 收不到任何 shutdown 信号:零 ACTION_SHUTDOWN/ShutdownThread)
→ AOSP 原生 WifiActiveModeWarden: "One of the native daemons died. Triggering recovery"(无 shutdown 抑制)
→ recovery teardown:MicarWifiService.stopSoftAp(LOHS 1st/2nd) → SoftApManager stop → WIFI_AP_STATE_CHANGED(DISABLED) 广播
→ 前台热点页(HotspotSettingActivity)如实清 UI → 用户灭屏前 ~440ms 看到"热点先关闭"
关键认知:热点物理停止是 reboot 固有(daemon 必死),可避免的是”中间态被广播到仍活着的 UI”。差集在 init 停机相位(A15+ 上游两阶段停机 vs A14 几乎同刻死亡),不是某平台 WiFi 栈丢了抑制。
2. persist 语义(MicarSoftApSettingsStore,framework 侧,settings 仓零代码)
- 开机读取打印:
mPersistLOHS1stState / mPersistLOHS2ndState / mPersistTetheredSoftApState;persist=1 的角色开机自动恢复(startStaAndAllAp → onStarted) - 写入规则(3/3 自然实验推断,强度中-强,缺平台源码 file:line):
MicarWifiService.stopSoftAp(role)显式 API 调用(=用户停用语义)→ 写 persist=0- recovery/teardown 驱动的 tracker 状态迁移(DisabledState.enter())→ 不写 persist
- 日志指纹
MicarWifiService: update settings value to disabled写的是另一个 Settings key,不是 persist store(三轮对照已排除它) - 衍生陷阱:App 侧任何”杂散显式 stop”(如 Switch 监听器被程序化回写击穿 → closeHotspot)都会被当成用户停用写 persist=0 → 重启后热点不恢复。MANNPROB-2933 里 185 包的监听器击穿就是靠”三轮 reboot 自然 A/B/A 实验”锁定为 persist clobber 元凶(页开+击穿→0;页关无击穿→1)。
3. 双机对照取证范式(强烈推荐)
同一代码不同平台表现不同时,差集即根因方向:
| fermi(A17/xring/MTK) | suiren(A14/qcom) | |
|---|---|---|
| init 停机 | 分阶段,相位差 ~820ms | system_server 与 daemon 同刻死 |
| daemon-death recovery | 触发并广播 AP_STATE | 不触发(无活进程可投递) |
| 热点页 UI | 清空 loading + 开关翻 false | 完整 ON 至灭屏 |
| 杂散 stop → persist | 有 → 0(不恢复) | 无 → 1(自动恢复 ✓) |
取证命令速查:
# reboot 触发点与方式(reboot,shell=adb;ShutdownThread=用户/系统路径)
grep -E "sys.powerctl|Reboot start|ShutdownThread|ACTION_SHUTDOWN" <milog_logcat>
# daemon 死亡与 recovery
grep -E "binder died|Triggering recovery|modeManagersBeforeRecovery|stopSoftAp|Soft AP is stopped|WIFI_AP_STATE" <milog_logcat>
# 停机相位差:hostapd Terminating 时刻 vs 老 system_server 最后日志时刻
# persist 读取(新 boot 后):主 txt grep MicarSoftApSettingsStore
# settings 侧响应:grep "HotspotSettingActivity: handleSwitch|setOnCheckedChangeListener"
# 杂散 stop 落点:MicarWifiService 侧 "ROLE_MICAR_SOFTAP_TETHERED stopSoftAp"(tid 为 binder 线程而非 wifi 线程)4. 视频逐帧对齐法(瞬态 UI 现象)
- 30fps 录屏先
fps=1粗抽 + 亮度(YAVG)曲线找灭屏帧,再对现象窗口fps=6+细抽 - 视觉事件与日志对齐锚点:页面清空帧 ≈
handleSwitch(10)时刻;灭屏帧 ≈ 显示下电;状态栏 WLAN 图标变灰 ≈ ClientModeImpl disconnectedstate - T1(UI翻转) ≈ T2(真实状态广播) → “如实刷新”非”UI 假象”(MANNPROB-2933 H4 假设因此排除)
5. 修复层级(本类问题通用)
| 层 | 动作 | 说明 |
|---|---|---|
| settings P0 | 消灭杂散显式 stop(程序化回写加 suppress 标志 + 发命令前实时态校验) | d40de696d 范式:setSwitchCheckedSilently + isSoftApEnable() 门控,堵 persist clobber |
| settings P1 | teardown 广播的 shutdown 抑制:读 sys.powerctl 非空即跳过 UI 清空 | 别用 ACTION_SHUTDOWN——adb reboot 路径根本没有该广播(已实证);system uid 可读 sys.powerctl |
| 平台根治 | ActiveModeWarden/SelfRecovery 触发 recovery 前检查 shutdown 进行态 | 或 init 把 core 排在 daemon 前停机(代价:framework 停机不干净) |
| 平台语义 | shutdown 路径的显式 stop 是否应跳过 persist 写入 | 关机时的 stop 不是用户意图 |
6. 误报判定提醒
“重启前热点先关闭”类单子不能判误报拆两层:①可见闪烁 = 真实瞬态的如实呈现(产品预期裁决层);②同窗口的杂散 stop → persist=0 → 重启后热点不恢复 = 确凿功能缺陷。字段「是否误报=误报」常与「故障原因=代码bug」矛盾,以后者+证据链为准。