现象:手机连接车机,操作手机端暂停播放,偶现车机端播放状态不变化;或者偶现position进度条2s跳动一次。
问题处理:
1、初步分析
进度信息不更新:蓝牙btsnoop日志显示,问题时间,车机端异常不再注册position的通知,手机端就无法主动更新position信息给到车机,车机端主动通过AVRCP get play status为2s下发一次,所以就出现进度信息2s跳动一下。
播放状态不更新:问题时间车机不再注册EVENT PLAYBACK STATUS CHANGED的通知,车机端自然也就无法更新播放状态
2、修改
准备从get play status入手,蓝牙协议avrcp 指令 get play status 会获取到3个参数,一个是歌曲时长,当前播放位置时间,还有播放状态,只需要将这三个信息通过jni callback给到蓝牙service,更新给应用即可解决这两个问题,准备修改,然后翻了下蓝牙协议栈感觉get paly status,只是一个备选的指令,甚至并没有处理get play status中播放状态的逻辑,既然取到了这个参数,重新加个callback即可,获取时间也更改为1s每次,修改验证后问题解决。
3、深入分析
position通知为何车机端异常不再注册了?
进一步翻协议栈代码发现,avrcp中Get Capabilities会获取到对方支持的通知event,然后存在本地链表中,每当有对应event的change事件被车机端接收到,协议栈会遍历list再次注册通知,同时每次注册通知会启动一个2s的计时器,如果手机端 INTERIM(临时状态/中间状态)回复慢超过2s,
超时后会把该通知当做异常通知,直接从list中remove,后续遍历也无法重新注册通知,造成无法通过通知来更新position和play status;
查蓝牙avrcp核心协议,CT端注册通知,TG端需在200ms内回复interim
结合问题btsnoop,手机端回复interim间隔时间将近4s
得出结论:手机端协议不规范,为手机端异常
4、总结反思
没办法对手机端操刀,最后只能又把车机端协议栈interim回复慢remove 通知的逻辑去掉,问题也彻底解决。对于get play status获取的状态更新与 position和play status change的通知获取的信息是否冲突多余了?只要通知正常交互,完全可以不需要触发get play status指令,反之也是一样,两个同时存在的话,兼容性可能会好一点。