【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]

项目场景:

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的方式还是通过老式的系统粘性广播获取
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第1张图片

【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第2张图片

AudioDeviceInventory.configureHdmiPlugIntent函数中发送的粘性广播没有带上相关的surround format,导致exoplayer认为底层不支持,透传失败。configureHdmiPlugIntent调用在、onSetWiredDeviceConnectionState函数中的sendDeviceConnectionIntent

【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第3张图片
sendDeviceConnectionIntent
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第4张图片

详细分析:

安卓的surround mode在开机AudioService构造的时候刷新到APM。如果安卓的surround format为Manual时,还会刷新surround format配置刷新到APM,分两个场景会执行:
刷新surround format:

  1. 在开机的时候
  2. Connect hdmitx的时候
  3. 切换surround mode为Manual的时候(开机过程不会触发此场景)

发送粘性广播给系统:

  1. Connect hdmitx的时候
  2. 切换surround mode为Manual的时候(开机过程不会触发此场景)

1、开机的时候

1.1、AudioService构造函数中调用readPersistedSettings

【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第5张图片
readPersistedSettings调用sendEnabledSurroundFormats
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第6张图片
sendEnabledSurroundFormats中会判断档期surround mode(mEncodedSurroundMode)是否为manual
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第7张图片
mEncodedSurroundMode的值第一次赋值是SettingsObserver构造函数中,SettingsObserver构造是晚于在晚于readPersistedSettings调用的,这会导致sendEnabledSurroundFormats函数判断为非manual直接return。
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第8张图片
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第9张图片

1.2、sendEnabledSurroundFormats刷新被执行

调用到audioserver进程的AudioPolicyManager::setSurroundFormatEnabled
里面会判断当前hdmitx是否接入,如果没有接入的情况下也不会刷新SurroundFormat。
【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第10张图片

2、Connect hdmitx的时候

  • AudioDeviceInventory.onSetWiredDeviceConnectionState函数中的mDeviceBroker.checkVolumeCecOnHdmiConnection触发消息机制进行异步发消息postCheckVolumeCecOnHdmiConnection的方式更新surround format, 通过该函数AudioService.onCheckVolumeCecOnHdmiConnection。
  • 此处异步方式可能会导致mDeviceBroker.checkVolumeCecOnHdmiConnection调用执行的消息的时间点晚于sendDeviceConnectionIntent (configureHdmiPlugIntent发粘性广播给系统)。特别是对于开机时期系统cpu资源loading大的时候。最后导致粘性广播中使用的manual的surround format都是默认值pcm。
    【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第11张图片
    postCheckVolumeCecOnHdmiConnection
    【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第12张图片
    onCheckVolumeCecOnHdmiConnection
    【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第13张图片

3、总结:

  • 根据打印分析,当前开机过程中,AudioService的surround format刷新早于connect hdmitx,导致surround format无法刷新到APM的mManualSurroundFormats变量;
    【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第14张图片
  • 同时,在连接hdmitx(场景2)时,surround format的更新线程晚于connect hdmitx的线程,导致read hdmitx profile的时候AudioPolicyManager::modifySurroundFormats使用的mManualSurroundFormatst一直是空;
    【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第15张图片

解决方案:

1、AudioService的构造函数中,在readPersistedSettings之前先给mEncodedSurroundMode复制,这样就能顺利的通过sendEnabledSurroundFormats将Manual的surround format刷下去到APM;

frameworks/base/services/core/java/com/android/server/audio/AudioService.java

【Bug-Fixes】【Android Audio】{surround mode设置Manual,打开DD/DDP之后重启平台,exoplayer播放Dolby输出是PCM} [OTT-41237]_第16张图片

2、去掉开机google判断hdmitx是否连接的条件,开机的时候让AudioService强制刷新surround format到APM;

frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::setSurroundFormatEnabled
在这里插入图片描述

你可能感兴趣的:(android,Audio,exoplayer)