项目场景:
Android TV,Android R,盒子平台 1、打开Settings-> Display&Sound -> Advanced sound settings设置为Manual,打开Dolby Digital,Hdmitx连接着支持Dolby的TV,重启平台; 2、开机之后打开Exoplayer播放Dolby的码流问题描述:
surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby,TV显示盒子输出的是PCM原因分析:
frameworks/base/services/core/java/com/android/server/audio/AudioService.java
frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
只有Exoplayer有这个问题,是因为exoplayer获取Audio profile的方式还是通过老式的系统粘性广播获取
AudioDeviceInventory.configureHdmiPlugIntent函数中发送的粘性广播没有带上相关的surround format,导致exoplayer认为底层不支持,透传失败。configureHdmiPlugIntent调用在、onSetWiredDeviceConnectionState函数中的sendDeviceConnectionIntent
sendDeviceConnectionIntent
详细分析:
安卓的surround mode在开机AudioService构造的时候刷新到APM。如果安卓的surround format为Manual时,还会刷新surround format配置刷新到APM,分两个场景会执行:
刷新surround format:
- 在开机的时候
- Connect hdmitx的时候
- 切换surround mode为Manual的时候(开机过程不会触发此场景)
发送粘性广播给系统:
- Connect hdmitx的时候
- 切换surround mode为Manual的时候(开机过程不会触发此场景)
1、开机的时候
1.1、AudioService构造函数中调用readPersistedSettings
readPersistedSettings调用sendEnabledSurroundFormats
sendEnabledSurroundFormats中会判断档期surround mode(mEncodedSurroundMode)是否为manual
mEncodedSurroundMode的值第一次赋值是SettingsObserver构造函数中,SettingsObserver构造是晚于在晚于readPersistedSettings调用的,这会导致sendEnabledSurroundFormats函数判断为非manual直接return。
1.2、sendEnabledSurroundFormats刷新被执行
调用到audioserver进程的AudioPolicyManager::setSurroundFormatEnabled
里面会判断当前hdmitx是否接入,如果没有接入的情况下也不会刷新SurroundFormat。
2、Connect hdmitx的时候
- AudioDeviceInventory.onSetWiredDeviceConnectionState函数中的mDeviceBroker.checkVolumeCecOnHdmiConnection触发消息机制进行异步发消息postCheckVolumeCecOnHdmiConnection的方式更新surround format, 通过该函数AudioService.onCheckVolumeCecOnHdmiConnection。
- 此处异步方式可能会导致mDeviceBroker.checkVolumeCecOnHdmiConnection调用执行的消息的时间点晚于sendDeviceConnectionIntent (configureHdmiPlugIntent发粘性广播给系统)。特别是对于开机时期系统cpu资源loading大的时候。最后导致粘性广播中使用的manual的surround format都是默认值pcm。
postCheckVolumeCecOnHdmiConnection
onCheckVolumeCecOnHdmiConnection
3、总结:
- 根据打印分析,当前开机过程中,AudioService的surround format刷新早于connect hdmitx,导致surround format无法刷新到APM的mManualSurroundFormats变量;
- 同时,在连接hdmitx(场景2)时,surround format的更新线程晚于connect hdmitx的线程,导致read hdmitx profile的时候AudioPolicyManager::modifySurroundFormats使用的mManualSurroundFormatst一直是空;
解决方案:
1、AudioService的构造函数中,在readPersistedSettings之前先给mEncodedSurroundMode复制,这样就能顺利的通过sendEnabledSurroundFormats将Manual的surround format刷下去到APM;frameworks/base/services/core/java/com/android/server/audio/AudioService.java
2、去掉开机google判断hdmitx是否连接的条件,开机的时候让AudioService强制刷新surround format到APM;
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::setSurroundFormatEnabled