安卓源码避坑指南2—HF侧拨打蓝牙电话的ID号一直是 -1

安卓源码避坑指南2—拨打蓝牙电话的ID号一直是 -1

又到了喜闻乐见的环节——安卓源码避坑指南,同事使用android-9源码全编了个系统镜像,安装完成后在HF侧主动拨打一通蓝牙电话后发现电话的ID号一直为-1,AT命令中的“+CLCC”中的idx参数协议中明确规定是从1开始计数的,表示当前的蓝牙电话是第几路电话。现在应用层却收到一个第-1路的蓝牙电话,这就很莫名其妙了,那本篇文章我们就来扒一扒这个问题吧。
在这里插入图片描述

环境:Android-P系统

操作

  1. 车载蓝牙连接手机蓝牙成功
  2. 通过车载端的蓝牙电话应用主动拨打电话(以 10086 举例)
  3. 蓝牙电话应用层内监听如下截图的电话改变广播从而来切换电话状态显示:
    在这里插入图片描述

现象:蓝牙电话应用接收到广播后解析出广播中的BluetoothHeadsetClientCall,通过接口getId()获取当前电话的ID号都是-1,log打印见下图:
在这里插入图片描述

由于蓝牙电话改变的广播是由蓝牙服务对外进行广播的,所以蓝牙电话的ID号赋值为-1应该是在蓝牙服务层进行操作的。话不多说,先来简单了解下这块逻辑的时序图:
在这里插入图片描述

通过时序图可以看到蓝牙电话的处理大部分是在HFP-Client状态机中,上图中红色字体标注的两个变量就是本问题的根因所在。

  • mCalls:当前存在的所有蓝牙电话

  • mCallsUpdate:本次AT+CLCC命令后需要更新信息的蓝牙电话

追溯安卓源码,发现第一次出现ID为-1是在HeadsetClientService.dial()方法里,该方法构造出一个新值BluetoothHeadsetClientCall,表示当前拨打的蓝牙电话,其中的ID号使用的就是HeadsetClientStateMachine中的常量值HF_ORIGINATED_CALL_ID = -1,并将这个call随着DIAL_NUMBER 消息一起下发到状态机中,所以下发拨打电话指令后mCalls中保存的call的id为-1。

mCallsUpdate中保存的都是从蓝牙协议栈上报的电话信息,从HCI可以明显发现,上报的电话的ID号都是1(当前只有这一个 10086
处于通话中)
在这里插入图片描述

那这问题应该是出在queryCallsDone()中,更新电话状态时安卓源码开发人员没有考虑到这个情况?

继续查看该部分的源码,我的天,源码注释里已经考虑到这种情况了,那怎么广播出来的还是-1的ID号,一脸懵逼中…
在这里插入图片描述

继续分析源码更新的步骤,终于被我一双慧眼看出其中的猫腻,哈哈
在这里插入图片描述

到这里我就无耻地笑了,总算被我找到根因,从始至终call里的ID值都没有改变,这样不管后面的电话状态怎么变,ID号都为-1。

原因找到了,那我们就想想解决方案吧。我这边提供一种方案如下截图,嘻嘻
在这里插入图片描述

重新单编蓝牙服务模块Bluetooth.apk或者全编system.img,验证后问题得到解决。感兴趣的小伙伴欢迎私信留言其他好的解决方案,我们一起讨论。

更多互联互通技术,欢迎关注微信公众号:Connectivity
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章