Android N蓝牙BLE鼠标重连问题总结

本文详细分析了在Android N系统中,蓝牙BLE鼠标在取消和重新启用“输入设备”功能时遇到的重连问题。问题根源在于协议栈状态异常,导致设备连接状态混乱。解决方案是参照Android M设计,连接完成后释放通道,避免异常状态。但即使解决,仍可能出现鼠标晃动的重复现象,因为协议栈会持续尝试重连。
摘要由CSDN通过智能技术生成

问题现象

去掉蓝牙鼠标“输入设备”功能后,重新勾选“输入设备”后,蓝牙一直处于“正在连接”状态

复现概率

必现

复现步骤

  1. 开机
  2. 打开蓝牙
  3. 搜索蓝牙鼠标
  4. 连接蓝牙鼠标
  5. 连接成功后,正常使用鼠标
  6. 取消“输入设备”功能
  7. 移动鼠标多次
  8. 打开“输入设备”功能
  9. 观察

测试现象

  1. 执行第七步时,移动鼠标,还可以看见鼠标指针在屏幕上闪动,闪动几秒后鼠标不动或消失
  2. 执行第八步时,鼠标一直处于“正在连接”状态,不恢复。
  3. 如果取消第七步,第八步效果正常。

问题分析

  1. 第一次连接蓝牙鼠标后,GATT发起SDP扫描,Android建立gatt_conn_id = 1的channel。完成discovery后,该channel一直存在,没有关闭
  2. 取消“输入设备”功能,GATT断开conn_id=4后,判断当前app是否有hold更多的channel,发现conn_id=1仍在使用,故不disconnect整个链路。
  3. 移动鼠标,由于链路没有断开,协议栈收到鼠标发送的gatt notification。协议栈自动处理,发现该设备依然存在,状态为disconnect。协议栈自动open并init connection。GATT状态正常后,上报至Framework。上层通过判断,发现用户手动取消输入设备功能,所以拒绝本次请求,发送reject。此时输入设备驱动已经add,所以在reject完成之前所收到的GATT包就正常传递到驱动处理。所以屏幕还上能看到鼠标移动或晃动。
  4. Reject完成后,设备再次进入close状态。这时又收到gatt notification,又将重复之前自动重连的操作,由于驱动多次add和remove,协议栈hid设备状态将异常停止在Connected,并不再处理数据上报。此时上层认为设备未连接,驱动认为节点未生成,协议栈认为设备状态已连接。
  5. 重新打开“输入设备”功能,Framework发起connect请求,协议栈接受到init conn请求,但由于协议栈正处于connected状态,对init connect操作为空(ignore)。所以忽略本次请求。
  6. 上层界面邮局发送了connect,变处于connection状态,没有收到stack的回复,便一直处于connection,不能回复。

问题解决方案

该问题再商用7.0上有做对比,依然存在。如果需要修改,可以参照Android M设计。AndroidM在搜索完成后,或异常情况下,都会主动释放掉对应的channel。如果本次测试中,连接完成后就释放掉conn_id=1的channel。那么取消“输入设备”后,APP就不再hold住任何channel,stack便会主动disconnect掉链路。链路disconnect后便不再接受notification,也就没有后面协议栈状态异常问题。

问题思考

本次问题的根本原因还是协议栈状态异常,解决方案只是一种workaround。但是就算解决了协议栈状态异常问题,根据Android N的策略,不让链路断开,那么就会出现,取消“输入设备”功能后,移动鼠标,界面一样有反应,反应为鼠标晃动,停止,晃动不停的重复。因为协议栈一直会不停的重连,应用不停的拒绝。

Log记录

取消“输入设备”:

01-02 06:15:56.352  3489  3489 D BluetoothInputDevice: disconnect(E6:71:40:79:75:FD)
01-02 06:15:56.364  4729  4729 I bt_btif : BTHH: disconnect
01-02 06:15:56.364  4729  4750 I bt_btif : btif_hh_handle_evt: event=1
01-02 06:15:56.364  4729  4750 I bt_btif : btif_hh_handle_evt: event=1
01-02 06:15:56.364  4729  4761 I bt_btif : BTA got event 0x1701
01-02 06:15:56.364  4729  4761 D bt_btif : bta_hh_dev_handle_to_cb_idx dev_handle = 16 index = 0
01-02 06:15:56.364  4
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android中,创建Bluetooth Low Energy(BLE)服务的蓝牙socket连接可以通过以下步骤完成: 1. 配置蓝牙适配器:首先,需要获取设备的蓝牙适配器,并确保其已启用。可以使用BluetoothAdapter类的getDefaultAdapter()方法获取默认的蓝牙适配器实例,并调用isEnabled()方法检查其是否已启用。 2. 扫描设备:使用BluetoothAdapter的startLeScan()方法扫描附近的BLE设备。在回调函数onLeScan()中,可以获取到扫描到的设备列表。 3. 连接设备:在扫描到目标设备后,调用BluetoothDevice的connectGatt()方法来创建GATT连接。其中,GATT(Generic Attribute Profile)是BLE连接的框架。该方法返回BluetoothGatt对象,用于管理GATT连接。 4. 发现服务:连接成功后,调用BluetoothGatt的discoverServices()方法来发现设备提供的GATT服务。在回调函数onServicesDiscovered()中,可以获取到所有服务列表。 5. 获取服务和特征:在服务发现完成后,通过BluetoothGatt的getService()方法获取指定的GATT服务。然后,使用getService()方法获取指定服务中的GATT特征。 6. 创建并连接GATT服务器:使用Gatt连接连接函数连接设备服务器。 7. 连接成功后,可以使用BluetoothGatt的readCharacteristic()和writeCharacteristic()等方法来读取和写入GATT特征的值。 需要注意的是,BLE连接是异步的,所以在连接过程中需要实现相应的回调函数来处理连接和数据传输的事件。 以上是在Android中创建BLE服务的蓝牙socket连接的基本步骤。根据具体的使用场景和需求,可能还需要进一步处理异常情况、设置通知等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值