BluetoothGatt: configure timeout for forceful termination for when remote device does not disconnect cleanly

77 views
Skip to first unread message

Christian Jensen

unread,
Feb 26, 2018, 12:23:30 PM2/26/18
to android-platform
Background
We build a SDK that uses Bluetooth LE to talk to specialised hardware devices. 
  • The hardware devices are mostly nrf-51 based. 
  • The hardware use the peripheral + GATT server role 
  • The SDK use the central + GATT client role. 
Description
My theory of the problem: when the remote device does not cleanly terminate the connection, the android device is left in a state that prevents it from functioning in subsequent connections to the same device. The device is kicked out of this state when a timeout kicks in the android bluetooth stack that triggers a forceful termination from the device end.

Symptoms
This manifests itself as: when we connect again to the same device before the timeout on our side has triggered, any attempt at performing service discovery fails. We can connect, we receive callback that the device has connected but when we then perform service discovery and receive the callback for that it is completed any call to BluetoothGatt.getService() returns null. We have attempted to detect this state and perform the connect and service discovery again. But we end up in the same place: BluetoothGatt.getService() returns null and we can not proceed.

Attempted mitigations
We discovered that additionally to the onConnectionStateChange() callbacks there are also the ACL_CONNECTED/ACL_DISCONNECTED broadcasts that better hints about the state of the connection from the bluetooth stacks point of view. In a normal session we receive these broadcasts at almost the same time as the callbacks to onConnectionStateChange(), but during this weird state we do not receive the ACL_DISCONNECTED until the aforementioned timeout triggers. So we have started to use these broadcasts to detect when the device ends up in this state to block any reconnection attempt to this particular device from the user. This way you can at least display a meaningful error that tells the user that this is not going to happen.

It appears as if the android device is still connected to the remote device. Any call to connect and discoverServices renders a callback much faster than when doing a "fresh" connect : on the order of 20ms compared to 300ms. 

Other information
We mainly experienced this issue on Samsung S8 where it tends to happen very often (although not consistently), which led us to believe that Samsung specific custom BLE code was the culprit. However, we also managed to reproduce the issue, albeit rarely, on a Nexus 6P, which suggests that the problem lies within OASP.

Questions
  • Is there anything we can do to massage the state in the bluetooth stack in AOSP to not behave like this?
  • Is there any anything we can do to forcefully terminate the connection from our end. At the moment we do disconnect followed by a close on the BluetoothGatt object.
  • Is this timeout configurable from the Android SDK layer?
    • the timeout appears to be ~20 seconds.

Natta Wa

unread,
Feb 27, 2018, 7:43:47 PM2/27/18
to android-platform
เมื่อ วันอังคารที่ 27 กุมภาพันธ์ ค.ศ. 2018 0 นาฬิกา 23 นาที 30 วินาที UTC+7, Christian Jensen เขียนว่า:
> Is there any anything we can do to forcefully terminate the connection from our end. At the moment we do disconnect followed by a close on the BluetoothGatt object.Is this timeout configurable from the Android SDK layer?the timeout appears to be ~20 seconds.

Reply all
Reply to author
Forward
0 new messages