Repository navigation
CarPToCarL 1.2.8 — 音频通道看门狗:有画面没声音不再干等 88 秒
有画面、没声音要等 88 秒——音频链路终于也配了看门狗
「等一会才连上车机,播放音乐也要等一段时间才出音频」——这句话背后其实是两件事。
连接慢那一半是引擎与 WiFi 的老账(见 1.2.6 的说明),声音迟到这一半是明确的漏配:音频通道没有看门狗。
一份实车日志(2026-11-01 09:01)把时间线摊开:
08:57:38 CARLIFE: 媒体 音频通道断开 - Connection reset ← 9240 死了
08:58:00 CARLIFE: TTS 音频通道断开 - Connection reset ← 9241 也死了
08:58:0x (视频看门狗重连 8240 → 车机上画面恢复)
09:00:22 CARLIFE: 媒体 音频格式宣告 44100Hz 2ch 16bit ← 88 秒后才出声
WiFi 入网把荣耀 CarLife 引擎重启,视频 / 媒体 / TTS 三条数据 socket 同时被 reset。
视频活下来了,因为它本来就有一条看门狗:每秒检查 socket 是否还在,死了就重连 8240 并重发编码初始化。
音频没有。audioReader() 读到异常只打一行日志就结束,sockets[9240] 还留在表里,没有任何代码会去重建它——
声音只能等引擎下一次自己复位推流。所以它「自己好了」,代价是 88 秒。
路径 A:socket 死了,立刻重连(本版主项)
媒体(9240)与 TTS(9241)各自挂一个通道状态,看门狗每秒检查一次;读线程退出即判死,随后重连该端口、重挂读线程。
断链重连不设次数上限(引擎冷启动期可能连续 reset),超过 3 次后每次多停 2 秒,避免把引擎打满——和视频看门狗同一套节奏。
一个容易踩的坑:重连要先把旧 socket close(),旧读线程随即走 finally;若无条件置死,就会把刚接上的新通道秒判死,
形成「重连 → 判死 → 重连」的死循环。现在每次挂读线程都递增一个「代次」,读线程只在自己这一代仍是最新时才允许置死。
路径 B:socket 活着但不出声,重连一次(带三重设限)
画面在动、音乐在播、9240 却连续零 PCM——这是「通道活着但流断了」,重连一次通常就能把引擎拉回来。
但这条判据必须设限,否则会比不修更糟:屏幕上没在放声音是常态,只按「静默」判会在每次停车等待时反复重连,自己把引擎的音频管道打断。
所以全部满足才动手:
连续无 PCM ≥ 20 秒 ← 音乐的自然停顿不会这么久
距通道建立 ≥ 20 秒 ← 刚接上要给引擎推流时间
视频 3 秒内有帧 ← 引擎活着,问题只在这条流上;视频也停了是会话层的事,别跟着乱动
引擎发过 0x30002 且未发 0x30003,或音乐会话正在播放
最多 3 次 ← 退避 20 / 40 / 60 秒,收到 PCM 即清零
TTS 只做路径 A:没开导航时 9241 本来就该长时间静默,按沉默判会天天误重连;但它的 socket 一样会随引擎重启而死。
还有一个必须保留的细节:格式宣告状态要跨重连保留。它原来是读函数里的局部变量,重连后新线程会以为「引擎没宣告过格式」,
给上层报一个 48kHz 立体声兜底值,把真实的 44.1kHz 覆盖掉——声音会变调。现在挂在通道状态上,重连不动它。
重连只换 socket 与读线程,上层的音频 sink 与发送端保持不动,所以车机侧的 RTP 流不会中断,听感是「卡一下」而不是「断一次」。
日志里怎么确认
CARLIFE: 媒体 音频通道断开 - Connection reset(看门狗会自动重连)
CARLIFE: 媒体 音频通道已重连(第 1 次断链重连)
CARLIFE: 媒体 音频通道 25 秒零 PCM(画面正在正常出帧)——重连 9240(第 1/3 次,20 秒后才会再试)
CARLIFE: 媒体 音频通道恢复(断流 25 秒,重连 1 次后恢复)
如果看到这条,说明引擎侧已经不推流了,此时该做的是重开 CarLife+ 的「无线连接」,而不是继续重连——
看门狗停在这里,把判断权交回给人:
CARLIFE: 媒体 音频通道连续 3 次重连仍无 PCM——停止重试
排查思路的完整梳理见 docs/audio-channel-watchdog.md。
装包说明:CarPToCarL-1.2.8.apk 为正式包(versionCode 10208)。可以直接覆盖安装,配置与已配对车机信息都会保留。