Hi ALL,
We found a issue on Android.
Andorid support service and characteristic cache to shorten the re-connection time.
The test setps:
1. Android APP scan the DA14580 and connect, service discovery.
2. Android APP bond the DA14580.
3. Android APP send data to characteristic A wihch is "write without response"
4. The application on DA14580 could received the data.
5. Link lost.
6. Andorid APP scan, connect, service discovery again.
7. Android APP send data to characteristic A wihch is "write without response"
8. The application on DA14580 could NOT received the data.
We checked the bluetooth OTA log and found that:
Step 6, the APP get service from Android cache, and there is not service discovery process on OTA log.
We tried service change from DA14580 for every conection, it worked well.
The bluetooth spec does not define that the service discovery process is mandatory before communication on characteristic.
Is it a issue on DA14580, and how to fix it?
Or what should we use the API of DA14580 to fix it?
Thanks and regards.
Hi ward wang,
There is no issue as far as we know, can you please check if the write_no_response packet leaves the android device by using a sniffer ? Also when you perform the second write is it with the same value as before?
Thanks MT_dialog
We have noticed this as well when we send a lot of write commands (called "write without response" in GATT) quickly. I think this is the same problem but cannot be 100% sure.
Anyway, the bug is in the Android source code and was introduced with these changes:
https://android.googlesource.com/platform/hardware/libhardware/+/9ef3c72...
https://android.googlesource.com/platform/packages/apps/Bluetooth/+/934d...
When the user sends a write command, the write command is sent to the bluetooth controller inside the phone which puts it in its outgoing queue and an onCharacteristicWrite is immediately sent back to the user which can then send another write command. However, the queue inside the bluetooth controller can only hold approximately 20-30 packets. They therefore have created a "congestion control" mechanism, which works like this: when the bluetooth controller queue is full, it does not send the onCharacteristicWrite directly, but waits until the bluetooth controller says its queue is not full anymore. This way, write commands ("write without response") on Android are reliable in the sense that packets are never dropped unless the link is disconnected. iOS however doesn't provide this great functionality but instead silently discards write commands sent by the iOS app when the bluetooth controller queue gets full without sending an error message back to the user.
The bug in the Android source code introduced above is that if the link is disconnected for any reason (link loss as well as normal disconnect) while it is congested (the bluetooth controller's queue is currently full), the callback indicating that there is now more room in the queue, is never sent up to higher layers, and they don't reset it when the device has reconnected which will make subsequent GATT operations never receive their onCharacteristic* callback which will put the gatt object in "busy" status, which means all gatt operations will fail and return false.
The workaround we currently use is, if we have a pending write command going on and we get a disconnect callback, we close this BluetoothGatt object and create a new one (using BluetoothDevice.connectGatt). Since the internal congested flag belongs to the BluetoothGatt object, it is set to false when a new object is created which solves the problem.
Hi Joacimwe,
Thanks for the indication, greatly appreciated.
MT_dialog