ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RK3576 Android 14 HDMI插拔后媒体无声?音频路由与焦点问题排查指南

RK3576 Android 14 HDMI插拔后媒体无声?音频路由与焦点问题排查指南 插上HDMI线之后盒子或者开发板上的媒体声音突然就没了屏幕上还时不时弹一个音频输出切换的提示框点掉也不行重启有时候能好有时候又复发。最近不少做RK3576方案的朋友都撞上这个问题而且现象高度一致Android 14系统HDMI Hotplug事件一切换媒体音频直接哑火。这篇东西不打算泛泛讲“什么是弹窗问题”直接拆解我在这个平台上排查和修复的完整过程包括音频路由机制、焦点抢占、Hal策略这几个真正藏雷的地方手把手把日志分析和代码改法都过一遍希望能帮正在调这块的同行省几天时间。1. 问题表象拆解这其实是个“弹窗路由”的复合问题1.1 弹窗类型与触发场景很多人在RK3576开发板上遇到“弹窗问题”时第一反应是去查PowerDialog、手机管家或者某个App的通知权限但实际上在Android 14的TV/Box类设备上真正频繁出现的弹窗就那么几类。音频输出切换提示插入HDMI后系统检测到新音频输出设备弹一个“音频输出已切换”或“当前使用HDMI输出”的提示这类弹窗通常由SystemUI或AudioService触发行为上更像“路由通知”而不是传统意义的对话框。权限申请弹窗某些预置App申请“附近设备”或“通知使用权”在Android 14里权限策略收紧后插拔HDMI这种硬件事件反而容易触发连锁申请干扰用户操作。应用崩溃弹窗HDMI插入导致音频焦点变化部分不兼容的播放器在AudioManager接口异常时崩溃出现“XX已停止运行”。把视线拉回开发阶段大家抱怨最集中的其实是一插HDMI媒体声音消失伴随一个路由通知弹窗焦点被通知类声音抢走播放器暂停或静音。1.2 无媒体声音的真正痛点弹窗只是表象核心痛点是“音频为什么没走HDMI”。在常见开发板上HDMI既负责显示又承载音频信号插上后理论上应该自动把媒体声音切换到HDMI声道。但Android 14对于音频策略做了一轮调整加上RK3576的HAL层音频拓扑比较复杂导致路由切换没有按预期执行现象就是“电视有画面但没声音”。这个问题的本质可以拆成两个层面系统层面AudioPolicyManager在处理HDMI插拔时是否需要真正切换设备还是保持当前输出同时让HDMI作为备用设备应用层面当前媒体播放器是否响应AudioFocus变化是否在失去/获得焦点时错误地暂停或调低音量。1.3 为什么Android 14上更容易暴露Android 14相比旧版本在音频框架上引入了更多状态监听特别是对设备切换事件的处理更激进插入HDMI后AudioPolicyManager会尝试建立新的输出流如果新的AudioPatch创建失败或者路由策略里没有配置HDMI输出系统会退回原输出路径但是UI上已经把设备状态切过去了这时候播放器收到异常回调就会出现“设备显示已连接但无声”。另外Android 14对AudioManager的全局音量做了更严格的分区管理媒体音量、铃声音量、闹钟音量彻底分离很多定制ROM在适配时忘记给HDMI输出配置独立的音量曲线导致硬件上已经切换了但音量曲线映射到0听起来就像完全没有声音输出。2. 深入机制HDMI插拔、音频焦点与路由策略2.1 事件链路从物理插拔到音频设备切换先捋一下整个事件链路。当你插入HDMI线底层驱动会触发一个uevent事件经过AudioService的处理最终反应到音频设备和路由状态。熟悉这条链路后面的排查才有章法。底层检测HDMI的Hotplug状态由显示驱动和音频驱动共同上报通常是/dev/switch或/sys/class/switch/hdmiRK平台一般会在drivers/video/rockchip/hdmi底层驱动里上报状态变化。框架层接收WiredAccessoryManager或AudioService收到设备插拔广播后会调用AudioSystem.setDeviceConnectionState。路由决策AudioPolicyManager根据当前音频配置决定新的音频输出设备组合。它需要查audio_policy_configuration.xml里是否有HDMI对应的输出端口和混音策略。输出流切换如果决策结果是把HDMI加入活动输出设备audio HAL层会打开对应的HDMI声卡设备建立AudioPatch。应用感知AudioService同步发送ACTION_AUDIO_BECOMING_NOISY等广播并且处理AudioFocus变化通知上层App。多数无声音的问题都出在第3步和第4步之间策略决策了但HAL层操作失败或者输出流参数不匹配。这部分在Android 14里比旧版更容易触发因为新架构对音频设备组合的校验更严格。2.2 弹窗如何“杀掉”媒体声音弹窗本身不产生声音但弹窗会引起AudioFocus请求。Android 14里系统通知音和路由提示音往往使用AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK或AUDIOFOCUS_GAIN_TRANSIENT如果某个App申请了AUDIOFOCUS_GAIN并且指定了延迟焦点一场“焦点战争”就开始了。常见的表现是这样的用户插HDMI系统弹出路由提示同时播放一段提示音。提示音应用获得Transient焦点正在播放的媒体App被迫暂停。提示音响完焦点应该归还给媒体App但如果媒体App在Android 14上使用了AudioFocusRequest的新接口而忘记设置setWillPauseWhenDucked等参数就可能造成焦点归还失败播放器一直处于暂停状态。媒体声音就这样消失了不是硬件问题而是焦点管理被弹窗打断。2.3 Android 14的“路由通知”行为Android 14在SystemUI里增加了一个“音频输出切换通知”的功能类似手机上的媒体控制栏。它会在检测到新的音频设备时弹出一个小通知用户可以手动切换输出设备。在手机上这是加分项但在TV/Box上反而是负担。尤其是RK3576这类方案默认输出是HDMI插入HDMI这种“开机就要用”的操作根本不需要弹窗提示多余的交互反而把应用焦点带乱。调试阶段系统弹出的设备切换通知会频繁暂停正在播放的视频让测试人员误以为是没声音。3. 定位实操一份能直接落地的排查清单3.1 复现与日志收集不要一上来就改代码先拿到完整日志。复现步骤建议固定开机 - 启动媒体播放器YouTube、本地播放器都可以- 播放一个连续音频/视频 - 插入HDMI线 - 观察声音消失时间点 - 拔掉HDMI - 再次观察。日志收集分几路并行logcat -s AudioService AudioPolicyManager AudioFlinger AudioTrack跟踪音频服务和路由决策日志。dumpsys audio查看当前音频设备连接状态、输出流和音频焦点持有者。dumpsys media.audio_policy查看策略引擎里的设备组合和路由状态。cat /proc/asound/cards确认HDMI声卡是否被内核识别。tinymix或tinyhal相关命令检查HAL层声卡路由和Mixer控件状态。日志要保留插入前后的完整片段重点看从WiredAccessoryManager或AudioService收到设备连接变化到AudioPolicyManager完成Mixer配置这一段。3.2 复现场景中的关键日志解读实际抓日志时优先搜索这些关键字setDeviceConnectionState确认系统有没有收到HDMI设备插入事件。getDeviceForStrategy确认决策引擎是否为媒体流选择了正确的设备。startOutput确认音频输出流是否被建立。AudioPatch或createAudioPatch确认底层patch有没有创建成功。focus或AudioFocus确认焦点变化路径谁申请了焦点、谁释放了焦点。如果在日志里看到设备切换成功了但startOutput用的device参数还是原来的Speaker或耳机那说明策略配置有问题。如果createAudioPatch失败需要检查audio_policy_configuration.xml里HDMI的端口定义和mixport配置。3.3 快速检查设备与焦点状态的命令# 查看当前音频设备连接状态 adb shell dumpsys audio | grep -E Devices:|state: # 查看音频策略设备组合 adb shell dumpsys media.audio_policy | grep -A 20 strategies # 查看当前持有音频焦点的应用 adb shell dumpsys audio | grep -A 30 Audio Focus # 查看声卡设备列表 adb shell cat /proc/asound/cards拿到这些信息基本能判断声音是死在HAL层、死的策略层还是死在应用层。4. 修复思路RK3576平台上的几个落地方向4.1 调整audio_policy_configuration.xml的HDMI输出声明如果日志显示媒体流没有路由到HDMI多半是策略配置里媒体策略没有声明HDMI输出设备。在RK3576的Android 14 SDK里默认配置一般在device/rockchip/rk3576/audio/audio_policy_configuration.xml。需要确认audioPolicyConfiguration里包含hdmi输出端口AUDIO_DEVICE_OUT_HDMI。mixPorts里定义了hdmi输出并且全局配置中允许Media策略使用该端口。常见配置片段如下mixPort namehdmi rolesource profile name formatAUDIO_FORMAT_PCM_16_BIT samplingRates48000 channelMasksAUDIO_CHANNEL_OUT_STEREO/ /mixPort devicePort tagNameHDMI Out typeAUDIO_DEVICE_OUT_HDMI rolesink profile name formatAUDIO_FORMAT_PCM_16_BIT samplingRates48000 channelMasksAUDIO_CHANNEL_OUT_STEREO/ /devicePort route typemix sinkHDMI Out sourceshdmi/然后检查attachedDevices里有没有HDMI Out。如果没有加上attachedDevices itemHDMI Out/item /attachedDevices改完配置后要重新编译并push到/vendor/etc/然后重启音频服务或整机重启。这类修改影响整机路由千万别只改一半就上产线很容易把不插HDMI时的Speaker声音也搞坏。4.2 修改或抑制AudioFocus抢占如果日志显示焦点管理混乱更直接的办法是减少系统中不必要的焦点申请。首先检查是否有预置应用在插入HDMI时触发语音助手或通知音。这类应用往往用旧接口requestAudioFocus来申请不需要的焦点。若有代码权限建议去掉这层请求。其次定制SystemUI时可以在AudioOutputDialog或相关路由通知组件里移除自动播放提示音的逻辑。这是最多余的设计插入HDMI本来就是常用操作每次插都“叮”一声听感不好还会把媒体播放器焦点带走。如果不想改Java层代码可以尝试在AudioService里把路由提示音的声音流类型改成STREAM_SYSTEM并设置低音量但这种方式收益有限焦点冲突的本质问题还在。4.3 处理音量曲线映射问题前面提到设备切换后无声还有一种可能是音量曲线映射异常。RK平台一般会在vendor/rockchip/hardware/audio或hardware/rockchip/audio下有一个音量曲线相关的参数文件比如AudioVolumes.xml。确认STREAM_MUSIC的默认音量映射有没有覆盖HDMI设备。如果配置了不同设备使用不同音量曲线而HDMI对应的一列是空的或者数值为0那么即使在UI上调大音量底层实际衰减仍是0声音出不来。对比一下正常Speaker设备和HDMI设备的volume映射volume streamSTREAM_MUSIC deviceCategoryDEVICE_CATEGORY_OUTPUT point0,0/point point100,100/point /volume如果写入100还是没声音多半不是曲线问题而是Hal层Mixer控制没打开。4.4 验证HDMI ARC与Passthrough的特殊场景如果你验证的时候发现普通PCM有声音但插上支持ARC的电视后没声音那问题可能是出在音频直通Passthrough配置上。HDMI ARC模式下电视会把音频回传给盒子或开发板处理如果Android 14配置了passthrough的音频滤镜但rk3576 HAL不支持某些格式就会出现“直通格式无声音”。这种场景下可以尝试在audio_policy_configuration.xml里为HDMI输出禁用或减少Passthrough格式profile namevedio formatAUDIO_FORMAT_E_AC3 samplingRates48000 channelMasksAUDIO_CHANNEL_OUT_5_1/如果电视回传的是E-AC3但系统没有license输出就静音。调试阶段可以先把这类直通格式注释掉强制走PCM验证基础链路。4.5 从HAL层确认声卡路由如果代码层确认都没问题就要下沉到HAL层。用tinymix查一下HDMI声卡的路由寄存器重点看I2S或者DP音频输出是否被静音。adb root adb shell tinymix -D 0 adb shell tinymix -D 3我遇到过的情况是HAL层打开了HDMI声卡但某个Mixer控件比如HDMI/DPTX Audio Switch没有使能导致信号根本没送到编码器。RK平台每块板子声卡布局不一样用tinymix先把所有控件状态打印出来和正常工作时的状态做对比很快能找到差异。5. 常见问题与排查技巧实录5.1 插入HDMI后弹窗正常但完全没有声音这种情况优先怀疑“音量曲线”和“Mixer开关”。先去设置界面调大媒体音量同时切到HDMI输出通道再用dumpsys audio看当前实际音量数值是不是为0。注意Android 14里TV设备需要在设置里开启“固定音量”否则HDMI通道可能被CEBConsumer Electronics Control相关逻辑静音。若音量数值正常还是无声去查HAL层的Mixer状态。大多数情况下问题出在HDMI声卡的Playback Switch或Audio Select控件没有打开。5.2 插HDMI后弹窗不出现也没有媒体声音弹窗不出现说明设备连接事件可能没传到AudioService优先排查HDMI Hotplug事件是否真的上报到了框架层。可以在串口终端使用getevent或者在内核日志里查dwc-hdmi相关输出。如果上层根本没收到事件那问题在显示驱动和音频驱动的联动逻辑这部分和具体BSP关系很大需要结合你们的SDK版本去看hardware/rockchip/audio里有没有监听显示状态变化。5.3 拔掉HDMI后扬声器声音变很小这多半是音量曲线联动出了问题HDMI插入时系统将音量映射到了HDMI曲线HDMI曲线和Speaker曲线不一致拔掉HDMI后没有重新映射回来。可以在AudioService的setWiredDeviceConnectionState里检查音量持久化逻辑或者在Hal层通过setParameters做音量校准。5.4 HDMI插上后媒体播放器自动暂停无法恢复典型焦点抢占问题。使用dumpsys audio查看当前焦点持有者。如果持有者是AudioService或某个系统组件说明路由通知或提示音抢占焦点后没有释放。建议直接移除/禁用系统路由提示音并把媒体应用升级为使用AudioFocusRequest.Builder正确设置setAcceptsDelayedFocusGain和setWillPauseWhenDucked(false)。5.5 音频输出切换异常频繁有开发者在调试时发现插入HDMI后系统反复弹“音频输出已切换”状态在两个设备间抖动。这通常不是策略问题而是HDMI的Hotplug状态不稳定建议用示波器或串口日志看HPD引脚的电平抖动如果是硬件问题软件上再怎么调也是白费。可以先用dumpsys audio确认设备状态是否真在切换。6. 一些值得记录的实操心得RK3576这个平台在Android 14下的音频框架改动比较大修这种“插HDMI没声音”的问题最忌讳的就是没定位就直接改HAL。我建议的核心排查顺序是先看AudioService日志确认事件到了没有再看AudioPolicyManager确认策略选对了没有最后才轮到HAL层和音量曲线。日志要抓完整别只看插入后一段。很多问题的根源在插入前的音频状态上比如已经处于通话模式或者焦点被某个后台应用持有插入事件只是压垮骆驼的最后一根稻草。另外Android 14的路由弹窗在TV类设备上确实没什么正面作用定制系统时可以直接裁剪掉。这部分逻辑在SystemUI的AudioOutputMonitor相关代码里删掉后不会影响音频路由只是没有了提示音和UI切换媒体声音不会被抢焦点体感会稳定很多。如果你们产品需要支持HDMI ARC那就要额外关注音频Hal层对ARC回传格式的处理不要只看PCM通路。我见过用默认配置跑ARC导致电视端没声音的案例排查到最后发现是回传的E-AC3格式没拿对Hal层直接丢弃了。最后再分享一个小技巧调试期间不要频繁整机重启用adb shell stop、adb shell start重启安卓框架会比冷启动快得多而且很多路由状态是保存在AudioServer进程里的重启框架就能清掉异常状态复现和验证的效率都会高很多。
返回列表