我和 AI 一起修电视:索尼 CEC 失效排查实录

TL;DR:电视的 HDMI-CEC 全链路瘫痪,根因是某根 HDMI 线把 CEC 总线(13 脚)拉死,导致电视开机时 CEC 初始化失败。而 mIsCecAvailable 这个标志一旦为 false 就不会自愈,所以后续怎么重启、怎么改设置都没用。

修复动作只有一个组合:拔光所有 HDMI 线 → 重启电视(不是待机)→ 插回设备。顺序不能反。

这篇文章除了讲技术,还想讲清楚一件事:这整个过程是我和一个 AI 智能体一来一回干完的。它负责敲命令、读 dumpsys、分析日志,我负责拔线、看画面、以及在关键时刻纠正它的误判。


〇、开场:我把 adb 交给了 AI

事情很简单:家里的 SONY XR-65X91J 接 Apple TV 4K,以前电视遥控器切到 HDMI3,Apple TV 自动亮,遥控器还能直接控制它。某天开始,这套流程全废了:

  • 切到 HDMI3,Apple TV 没反应,屏幕黑着
  • 电视遥控器按下去,Apple TV 毫无响应
  • 得先摸出 Siri Remote 按一下,Apple TV 才醒

按以前的习惯,这种问题我会自己开终端,一条条 adb shell 试。但那天太晚了,我换了种干法——直接把电视的 adb 连接交给 WorkBuddy 里的智能体(小智),让它自己查。

我的开场白只有一句:

我:我的电视的 HDMI3 连接的是 Apple TV,分析一下为什么我将信号源切换到 HDMI3 的时候没有唤醒 Apple TV。

它回得也很干脆:

小智:我先连电视,把 HDMI-CEC 的实际配置和切换 HDMI3 时的日志抓出来,再下结论。

然后它就开始自己跑命令了。下面整个过程,都是真实发生的交互。


一、第一回合:AI 交上来的"体检报告"

它做的第一件事不是猜,是分层取证——先查 settings 三层,再查服务,再查 dumpsys 状态机,最后翻 logcat。

几分钟后它给出的核心结论只有一行:

mIsCecAvailable: false

再往下是设备表:

mDeviceInfos:
  CEC: logical_address: 0x00 device_type: 0 ... display_name: TV

只有电视自己(地址 0x00),一个下游设备都没有。

以及报文历史:

CEC message history:
  [S] time=2026-06-05 18:35:46 message=<Report Physical Address> 0F:84:00:00:00
  [S] time=2026-06-05 18:35:48 message=<Device Vendor Id> 0F:87:08:00:46
  [S] time=2026-06-05 18:35:54 message=<Active Source> 0F:82:00:00
  ...

12 条记录,全是 [S](Send),一条 [R](Receive)都没有。

它给我的解释是:

小智:CEC 是双向总线协议。一条 [R] 都没有,意味着这块电视从来没有成功接收过任何 CEC 报文。这不是"Apple TV 没开某个开关"能解释的。

同时它发现 HAL 层在刷屏:

E/CEC_HAL: Tx notify NOT coming, Timeout  return
W/HdmiCecController: Failed to send <Active Source> 0F:82:00:00 with errorCode=2

到这里,它给了一个初步判断,而且是错的:

小智:从首次开机起每条发送就都是 errorCode=2……这台电视的 CEC 可能一直就没工作过,只是你之前没用过这个功能。


二、第二回合:我的一句话,把方向掰回来了

它问了我一个关键问题:

小智:顺便问一句,你用 Apple TV 遥控器能开关电视或者调电视音量吗?如果完全没反应,基本就坐实是 CEC 整条链路的问题。

我的回答同时也否掉了它前面的推测:

我:能,以前用电视遥控器切换到 HDMI3,会唤醒 Apple TV,然后用电视遥控器也能够控制 Apple TV,现在不行了。

它立刻改了判断:

小智:这条信息很关键。既然以前能用,那说明这不是"出厂即坏",我收回"一直没工作"的判断。CEC 硬件是好的,现在处于卡死状态。

这是整个排查的转折点。

如果它继续沿着"硬件从来没工作过"推下去,结论会变成"主板故障,送修";而"曾经好过、现在坏了"这个前提,把方向引向了"后来发生了什么变化"——这才有了后面的隔离实验。

我后来复盘时觉得,这是人机协作里最值钱的部分:AI 能看到我看不到的数据,但它不知道我的生活史。有些信息只存在于人脑里,必须由人补给它。


三、第三回合:AI 自己设计并执行了五次"抢救"

确认是"后天失效"之后,它没有停在分析上,而是自己列了一串恢复手段,一条条试:

#手段命令结果
1CEC 开关重置cmd hdmi_control cec_setting set hdmi_cec_enabled 0 → 1❌ 无效
2ARC 通道重置cmd hdmi_control setarc off → on❌ 无效
3重启 CEC HAL 进程kill -9 <pid>❌ Operation not permitted(无 root)
4端口抖动检测10 秒 × 5 次采样❌ 四口状态恒定,非接触不良
5整机重启adb reboot❌ 无效

其中第 1 条实验,是它自己想到的,而且做得非常聪明:

23:52:19  setCecSettingIntValue hdmi_cec_enabled = 0    ← CEC 已关闭
23:52:20  E/CEC_HAL: Tx notify NOT coming, Timeout       ← 照样超时
23:52:22  E/CEC_HAL: Tx notify NOT coming, Timeout       ← 照样超时
23:52:24  setCecSettingIntValue hdmi_cec_enabled = 1    ← 再打开
23:52:26  E/CEC_HAL: Tx notify NOT coming, Timeout       ← 还是超时

它的解读是:

小智:CEC 在软件层都关掉了,驱动层还在每 2 秒报一次发送超时。这一条就够了——问题与 Android 的 CEC 状态机无关,与 BRAVIA Sync 的设置无关,是驱动/物理层的持续故障。

这是全篇最有说服力的一段证据。 我自己想不到这么试,一般人的思路是"打开看看",而它是"关掉看看——如果关了还在报错,说明报错的根本不是这一层"。


四、第四回合:它给不了手,于是给我造了把工具

到这一步它已经很明确了:问题在物理层,而物理层它碰不到。

小智:软件层能试的全试完了,四条路全堵死。剩下的必须动手了。我做了个实时监控,让你拔线的瞬间就能看到结果。

然后它写了两个脚本扔进项目目录:

./cec_live.sh      # 实时监控,每 2 秒一行
./cec_probe.sh 10  # 单次采样,输出完整体检报告

cec_live.sh 的输出长这样:

23:58:19  --       [重连中]
23:58:22  1        [总线异常]
23:58:24  1        [总线异常]

它的原理很简单——把 Tx notify NOT coming 的出现频率当成 CEC 总线的健康度指标。正常应该是 0 次,每当 2 秒出现 1 次,就说明有东西在拉着总线。

这个设计让我不用反复跑命令、翻日志,只要看着屏幕拔线就行。 这是我觉得 AI 在这类任务里最实用的能力:它能把"你去做物理动作,我盯着数据"这种配合变成现实。


五、第五回合:我拔线,它看数据

我按它说的,把四根 HDMI 线全拔了,然后截了张监控图发过去。

00:01:02  [总线异常]
...
00:02:12  [总线异常]
00:02:14  [总线正常]     ← 从这里开始,一次超时都没有了
...
00:03:01  [总线正常]

它的反应:

小智:这个结果很关键,四根线全拔掉后 TX 超时在同一瞬归零了。说明电视的 CEC 控制器本身没坏,问题出在外部。

它还注意到一个我没在意的细节:

小智:注意那个 70 秒的延迟——拔线之后不是立刻恢复,而是过了一分多钟才彻底安静。说明 CEC 控制器需要重新检测 HPD 状态、重新初始化才能脱离异常态。

这句话后来成了修复方案的关键。


六、第六回合:为什么之前那次重启没用

在等我的过程中,它自己去重启了一次电视(adb reboot),然后查状态——还是坏的。

它当时的解释:

小智:mIsCecAvailable 是开机时一次性判定的,一旦变成 false 就不会自愈,只有重启才能重新初始化。之前那次重启时,线还插着、总线还是坏的,所以重启后照样失败。必须先拔线、再重启,顺序反了就是白折腾。

这个因果链一说通,整件事就闭环了:

某根线把 CEC 总线拉死
      ↓
电视开机时 CEC 初始化失败 → mIsCecAvailable = false
      ↓
这个标志不会自愈,只有重启有机会翻盘
      ↓
重启的那一刻如果总线还是坏的 → 依然失败
      ↓
所以必须:先拔线制造干净环境,再重启

它甚至主动承认了这个顺序问题:

小智:这也是我一开始没让你先拔线就重启的原因——当时我还没排除"是电视本身坏了"。


七、第七回合:验证

四根线全拔 + 重启之后,我按它的要求,只插回 Apple TV 那一根。

它一查,电视立刻识别到了:

mDeviceInfos:
  CEC: logical_address: 0x04  device_type: 4  cec_version: 5
       vendor_id: 4346        display_name: Apple TV
       physical_address: 0x3000  port_id: 3
  • logical_address 0x04 → Playback Device 1
  • vendor_id 4346(0x10FA)→ Apple Inc.
  • physical_address 0x3000 → HDMI3

它自己的评价是:

小智:vendor_id 4346、physical_address 0x3000、device_type 4——它是一个完整、合法的 CEC 设备,被电视正常纳管了。

然后它直接发了个 intent 切到 HDMI3,抓下了修复后的完整握手:

00:08:55  [S] <Give Device Power Status> 04:8F     ← 问 Apple TV 状态
00:08:55  [R] <Report Power Status> 40:90:00       ← 答:我开着
00:08:56  [S] <Set Stream Path> 0F:86:30:00        ← ★ 关键报文,之前根本发不出去
00:08:56  [R] <Image View On> 40:04                ← Apple TV:收到,醒了
00:08:56  [R] <Active Source> 4F:82:30:00          ← Apple TV:我接管画面

mActiveSource: (0x04, 0x3000)    ← Apple TV 是当前活跃源
mActiveRoutingPath: 0x3000       ← 路由锁定 HDMI3

一步不缺,教科书级的 One Touch Play。


八、被忽略的技术细节:Routing Change 和 Set Stream Path 不是一回事

报告里有一段我觉得最值得单独拎出来的分析——为什么设备表为空的时候,切信号源更不容易唤醒设备。

它抓到了故障期间切 HDMI3 的轨迹:

23:43:52.995  TIS_HdmiControlHelper: portSelect() id: 3
23:43:53.006  HdmiControlService: portSelect: portId: 3
23:43:54.001  addAndStartAction RoutingControlAction
23:43:54      [S]: <Routing Change> 0F:80:00:00:30:00     ← 只发了这一条
23:43:56.003  removeAction: RoutingControlAction          ← 2 秒后放弃

两条报文的区别是致命的:

报文Opcode语义能唤醒设备吗
<Routing Change>0x80“我的路由要变了,通知你们一声”❌ 只是告知
<Set Stream Path>0x86“我要显示 3.0.0.0 的画面”✅ One Touch Play 的触发点

原因在 HdmiControlService 的逻辑:目标地址上的设备已知就发 <Set Stream Path> 精准投递,未知就只能广播 <Routing Change> 让设备自己宣告。

而故障期间设备表本来就是空的。所以形成了双重故障:

  1. CEC 物理层发不出报文
  2. 即使发得出,发的也是"通知"而不是"唤醒指令"

这一点在中文资料里几乎查不到,是它逐行对比修复前后的日志才发现的。


九、复盘:人机怎么分工才高效

这件事做完,我认真想了想这种协作的边界在哪。

AI 做得好、人做不了的部分

能力具体表现
批量取证十几分钟内跑了上百条 adb 命令,翻了 setting/secure/global 三层、包列表、dumpsys、logcat 全量
交叉验证从"设备表为空"和"零条 [R]"两个独立证据推出同一个结论
反向实验设计主动把 CEC 关掉,用"关了还报错"来证明问题不在这一层
自己造工具发现需要人配合做物理动作,当场写了监控脚本
不漏细节从一堆日志里挑出 70 秒延迟、errorCode=2、mConfigs 变空这些线索
不嫌烦凌晨一点,反复采样、反复对比,没有"差不多就这样吧"

只有人能做的部分

能力为什么 AI 不行
拔线 / 插线物理世界没有 API
补充生活史"以前能用"这句话决定了整个排查方向,AI 无从得知
质疑结论它说"可能一直没工作过",我一句"以前能用"就把它掰回来了
看画面“切过去了但黑屏"和"切过去了有画面”,只能人眼判断
量电压万用表是它碰不到的东西

AI 在这件事里犯的两个错

写出来才有参考价值:

  1. 过早下结论:看到"首次开机就失败",就推断"从没工作过"。它缺的是时间维度的信息(用户的使用史),这个必须人补。
  2. 顺序搞错:先提议重启、后提出拔线。虽然它后来自己纠正了(“必须先拔线再重启”),但这个顺序问题导致了中间一次无效尝试,白等了 45 秒。

规律是:AI 在"信息完备的确定性推理"上极强,在"信息缺失时该不该下结论"上容易冒进。


十、技术总结:三条能省下几小时的经验

1. mIsCecAvailable 不会自愈

这个字段在 HdmiControlService 初始化时一次性判定,一旦为 false,后续无论开关 CEC、改设置、切输入都不会翻回来。唯一出路是重新初始化,也就是重启。

看到 mIsCecAvailable: false,别浪费时间调设置。

2. 必须"先拔线,再重启"

顺序反了等于白做。开着机的设备状态是"坏的快照",重启会把这个快照固化下来。

推广一下:任何"开机自检 + 状态锁死"型故障,都要先制造干净环境再重启。

3. cable_connection_status 字段不可信

排查中一度被它误导:明明线拔了,还是显示 cable_connection_status=1(已连接)。

可靠的判断依据是 mConfigs 数组:

mConfigs: []                                    ← 没信号
mConfigs: [TvStreamConfig {mStreamId=0;...}]   ← 有信号

前者是缓存值,只在特定事件刷新;后者反映真实的流配置状态。


十一、附:排查命令速查

# 1. CEC 总体状态(先看这个)
adb shell dumpsys hdmi_control | head -5

# 2. CEC 设备表(有没有识别到下游设备)
adb shell dumpsys hdmi_control | sed -n '/mDeviceInfos:/,/mCecController/p'

# 3. 报文历史([S] 发送 / [R] 接收,重点看有没有 [R])
adb shell dumpsys hdmi_control | sed -n '/CEC message history/,/mCec/p'

# 4. 发送失败日志
adb shell logcat -d | grep "Failed to send"

# 5. 物理层超时(CEC 总线健康度核心指标)
adb shell logcat -d | grep -c "Tx notify NOT coming"

# 6. HDMI 端口真实状态(看 mConfigs,别看 cable_connection_status)
adb shell dumpsys tv_input | grep TvInputHardwareInfo | grep hdmi

# 7. 切换输入时抓 CEC 报文
adb shell logcat -c
# ...在电视上切到目标输入...
adb shell logcat -d | grep -E "HdmiCecController|portSelect"

健康基线:

指标正常值故障值
Tx notify NOT coming0 次/分钟每 2 秒 1 次
Failed to send0每条报文都失败
[R] 接收记录有零
mDeviceInfos含下游设备只有 TV 自己
mIsCecAvailabletruefalse(需重启恢复)

十二、后记

这次真正花时间的不是找答案,而是证伪——把"Apple TV 设置问题"“固件 bug”"主板硬件故障"一个个排除掉。

而排除的过程,是人和 AI 交替推进的:

  • 它挖数据,我提供它拿不到的事实
  • 它试软件手段,我做物理动作
  • 它下结论,我负责质疑
  • 它写工具,我负责用

最有价值的两个技术动作,也正好一人一半:

  1. 看 [R] 记录(AI 发现)——一条接收都没有,比任何猜测都硬。
  2. 隔离变量,拔光所有线(人执行)——有时候"拔掉一切"比任何高级命令都有效。

至于到底是哪根线的问题,目前还没定论:HDMI2 上还有一台设备没插回去,可能是它,也可能只是某次插拔导致 13 脚接触劣化、重新插拔就恢复了。这类故障有复发风险,先把流程记下来,下次直接照做。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐