文章目录
- 问题描述
- 问题分析
- 流程梳理
- 问题原因
问题描述
多屏设备,没有按照配置car_audio_configuration.xml配置输出。也即是每个屏幕播放的音频没有对应输出到想对应的bus设备。
问题分析
- 首先根据hal层的log,确认框架层配置的bus,确认框架配置的是主屏的bus0
- 确认userID displayID audioZoneId 三者之间的映射关系 userID 代表了每个屏幕对应的用户,zoneID 和 occupation ID 对应,occupation ID 和 display ID对应, zoneID 就和displayID 对应起来了。
zoneId=0 config={userId=10 displays={displayId=0 displayType=1} audioZoneId=0}zoneId=1 config={userId=11 displays={displayId=6 displayType=1} audioZoneId=1}zoneId=2 config={userId=12 displays={displayId=3 displayType=1} audioZoneId=2}zoneId=3 config={userId=13 displays={displayId=2 displayType=1} audioZoneId=3}zoneId=4 config={userId=14 displays={displayId=4 displayType=1} audioZoneId=none}zoneId=5 config={userId=15 displays={displayId=5 displayType=1} audioZoneId=none}
通过dumpsys car_service | grep user可以看到对应的关系
比如上面的代码可以看出audioZoneid -----> displayID ------> userID之间的关系, 这个映射关系是对的。
- 查看audio的信息
可以通过dumpsys audio 或者media.audio_policy(如果忘记命令可以dumpsys -l | grep audio)
dumpsys audio 可以看到usrID 和address的映射关系
Uid Device Affinities:UserId Device Affinities:UserId: 10Type: 0x1000000 Address: bus6_notification_outType: 0x1000000 Address: bus0_media_outType: 0x1000000 Address: bus2_voice_command_outType: 0x1000000 Address: bus1_navigation_outType: 0x1000000 Address: bus4_call_outType: 0x1000000 Address: bus3_call_ring_outType: 0x1000000 Address: bus7_system_sound_outType: 0x1000000 Address: bus5_alarm_outUserId: 11Type: 0x1000000 Address: bus100_audio_zone_1UserId: 12Type: 0x1000000 Address: bus200_audio_zone_2UserId: 13Type: 0x1000000 Address: bus300_audio_zone_3
dumpsys media.audio_policy可以看到所有注册到policy 中的mix路径。其中的critertion 代表路由到这个mix的规则
比如下面的表示usage是AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE 并且不是user 11 12 13的使用这个policyMix。
Audio Policy Mix 4 (0xb4000075f6ddab30):- mix type: MIX_TYPE_PLAYERS- Route Flags: MIX_ROUTE_FLAG_RENDER- device type: AUDIO_DEVICE_OUT_BUS- device address: bus1_navigation_out- output: 21- Criterion 0: RULE_MATCH_ATTRIBUTE_USAGE AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE- Criterion 1: RULE_EXCLUDE_USERID 11- Criterion 2: RULE_EXCLUDE_USERID 12- Criterion 3: RULE_EXCLUDE_USERID 13
- 查看显示的信息
可以通过dumpsys display 和 dumpsys SurfaceFlinger确认屏幕的类型, 比如下面surfaceflinger的信息可以看到某个屏幕的信息。 找到对应的屏幕。
isplayId=243, Connector 438, Type = DP-1, Connector state = DRM_MODE_CONNECTED
但这样也不容易看到,可以通过scrcpy --display 加上后面的displayId来确认哪个屏。 比如想要调试audioZoneId 为4 的,那么就是–display 2 这样。
流程梳理
-
根据经验路由的规则是由用户id决定的,一般路由不对,就是用户id配置的不对。但是通过上面的信息可以看到用户id 和 audioZone是对应的。查看policy 发现没有新加入的zone300 address 相关的路由。
-
从audioPolicyManager出发,看registerPolicyMixes 中注册了多少个mixes,manger中只注册了10个mix。 先略过中间的流程 从应用carAudioService开始
在添加mix 的地方确认,所有的mix 都加入总共11个。 那就是从应用加mix 到manager 中间少掉了一个mix。 -
上层路由添加流程: 是遍历所有group中的address, 每个address 生成一个mixingRule, 然后每个group 中的context 转成usage,对于每个usage 生成一个rule,这个rule添加到mix 的critertion中,android所有的有效的context总共10个,可以对应到20个usage,就是每个mix最高有20个critertion。
-
生成的每个mixrule 添加到audiopolicy 中。 这个audiopolicy 通过audioservice 注册到registerAudioPolicy框架中,在注册的调用中调用connectMixes 中
mAudioSystem.registerPolicyMixes(mMixes, true); 将mixer注册的system。 这个是通过android_media_AudioSystem_registerPolicyMixes的jni调用到AudioSystem::registerPolicyMixes audioSystem在调用到aps->registerPolicyMixes(mixesAidl, registration)其中aps是AudioPolicyService 也就是调用的
AudioPolicyService::registerPolicyMixes。最后这边调用到了AudioPolicyManager::registerPolicyMixes。 -
这整条链路中
android_media_AudioSystem_registerPolicyMixes
AudioSystem::registerPolicyMixes
AudioPolicyService::registerPolicyMixes
这三个地方都有mix的size判断。
问题原因
- carAudioService 中跟xml解析 构造好mix的rule 之后,将这些rule 注册到audiopolicymanager。
- 播放音频 创建track 获取输出设备的时候从注册的mix rule中找到符合输出的rule, 这个rule 包含了userid的信息。
- 因为框架中限制了外部注册的mix数量,导致最后一个usrid为13的 rule没有注册进去。
后面在找的时候找不到,就默认用了rule中的第一个了。