ipad蓝牙搜不到android,安卓源码避坑指南4——搜索中配对新设备失败

搜索中配对新设备失败

b54c1dc329ee4b874f213bba880b7610.png

有段时间没更新文章了,向各位朋友们抱拳了(主要这段时间项目比较忙,加班狗。。。)后续希望挤出更多时间来持续更新,那咱就赶紧开始本期的安卓避坑分享吧。

测试环境:android-9车机系统(高通源码)

测试步骤:

2. 搜索过程中点击搜索到的新设备进行配对连接

测试现象:配对连接失败

乍一看,操作步骤很正常啊,和大伙平常连接的操作是不是一模一样,怎么会失败呢?查看logcat如下:

7e013dc4dbf4c55d5457b33ca3fe0487.png

从红色框图明显看出配对请求远端设备的蓝牙名字失败,进而导致整个配对连接的过程失败。

根据error:0x2这条log,查看源码得出当前系统有一条读取远端名的命令正在执行中,所以配对过程中需要获取新设备的蓝牙名字时由于p_inq->remname_active为true,从而返回BTM_BUSY的status值。

这样的分析更让人头懵了,蓝牙服务层AdapterService.createBond()方法中,在配对之前已经下发了取消搜索的命令。

b6cae44f5d963bfc06be8ac46e6f25f0.png

按照常理来说,协议栈中配对流程开始时,相关变量应该已重置到初始值才对,那现在的问题就是:已经执行了cancel discovery操作,为啥p_inq->remname_active值还没重置为false?

要解决上述问题,那难免不追问一句p_inq->remname_active是何时置为true的,还是在源码中追踪,蓝牙协议栈源码中只有一处将上述变量置为true,也就是btm_initiate_rem_name()中下发读远端名HCI命令后,标志着正在读取一个设备的蓝牙名字。

蓝牙相关流程中涉及到读远端名操作的一个是配对流程,而另一个就是搜索中的Discovery流程。

应用层发起蓝牙搜索指令到达协议栈会分为两个阶段执行:inquiry + discovery

1.Inquiry:通知蓝牙芯片扫描周围环境中的蓝牙设备,并将扫描到的设备信息上报协议栈

2.Discovery:inquiry结束(一般为12.8s)后,协议栈会依次对扫描到的设备发起discovery流程,也就是请求蓝牙名字等设备相关信息。

至此我们大致清楚该问题发生的时间点:搜索蓝牙流程中正在对某一个扫描到的蓝牙设备请求远端名时,p_inq->remname_active=true,应用开启配对流程。

而p_inq->remname_active置为false也只有一处地方btm_process_remote_name(),有以下三种情况会调用到该函数:

1. 请求远端名超时

2. 上报请求远端名的状态事件时,status != success

3. 上报请求远端名的完成事件

正常都是第三种情况调用上述函数将p_inq->remname_active置为false的。

再次回到本文章的场景,应用层在底层有请求远端名的discovery流程时开启了配对流程。

蓝牙服务会优先将搜索流程取消掉,协议栈对应的动作就是下发取消读远端名的HCI命令;蓝牙服务层在下发完cancelDiscoveryNative(),就立即下发配对指令。而协议栈在下发完HCI_RMT_NAME_REQUEST_CANCEL后并不会立即将p_inq->remname_active置为false,需要收到远端名请求的完成事件才设置成false

3e918cb3e49d06a203cc3f9510f1f4c2.png

其对应的snoop交互为:

d7a11557b23eb9a51c1d92ec720cc0b8.png

配对流程发起的读远端名的操作时间点正好处于上面截图中完成事件之前,所以p_inq->remname_active依然为true,配对失败。

分析到这里想必大家都知道问题的根因了,这就是个时序导致的问题。清楚问题根因那解决方案也就水到渠成,暂时能想到的方案有如下几种。

解决方案:

A应用层发起配对前先停掉搜索,BluetoothAdapter.cancelDiscovery()

B蓝牙服务层在AdapterService.createBond()中调用完cancelDiscoveryNative()后延迟一段时间再继续下发配对指令

C协议栈在现有逻辑下,在收到取消读远端名的完成事件后,将p_inq->remname_active置为false

D协议栈在下发取消读远端名HCI命令成功后,将p_inq->remname_active置为false

上述 A、B、C这三种方案按照逻辑分析,还是存在该问题中的时序问题,但是概率能够极大降低。

方案D能够保证配对发起的读远端名操作时,p_inq->remname_active的值为false,不影响配对流程的进行。

欢迎大家留言一起讨论其他方案,本期是安卓源码避坑指南系列的第四篇文章,想了解更多安卓源码bug的同学可以翻看以前的系列文章,共同学习,一起进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值