Android-BLE-Library icon indicating copy to clipboard operation
Android-BLE-Library copied to clipboard

Make sure GATT INSUF AUTHORIZATION (8) does fail or repeat a request

Open chrislro2019 opened this issue 6 years ago • 4 comments

Hi, I use a method which writes a characteristic. I added also the with/fail/done calls for logging purposes.

writeCharacteristic(mCharacteristic, ControlPointData.reset())
				.with((device, data) -> { Log.v(TAG, "write data " + data); })
				.fail((device, status) -> { Log.v(TAG, "write fail "+ status); })
				.done(device -> { Log.v(TAG, "write done"); })
				.enqueue();

This works for other characteristics well. But this charateristic I am writing to currently returns GATT INSUF AUTHORIZATION (8) - which is intended. Nevertheless, I like to show in my app a message and/or react on this returned error code. nRF Connect on PC and nRF on Android do show this as a message resp. in the logs as Error 8.

I expected, that .fail() would be called on GATT errors and I would be able to switch/case the status value. But for my case I found out in onCharacteristicWriteSafe that onError() is called instead (if != BONDED_NONE), notifyFail() is called in the succeeding else path.

As my device is not yet bonded, so neither the onError() nor the notifyFail() in called at all. And also the request stays in the queue. I know that this is a special case with those GATT error codes, but at the end in my case my app is not able to receive the error in any way. I am not yet fully informed about the OS driven bond handling, but I think GATT INSUF AUTHORIZATION (8) is different (as it is not defined in Androids native classes at all).

How do I get the GATT error codes in this case? Would it make sense to publish such failure codes also with notifyFail()?

chrislro2019 avatar Jun 14 '19 13:06 chrislro2019

Hi, in theory, Android, at least from some version, should not report this error, but initialize bonding instead, and quietly repeat the write automatically. That's why there's no fail thrown for this error. But this is very not reliable. Some phones do that, other don't, and as far as I know it has changed at some point. It may also depend on whether the device supports bonding at all. For production, I would recommend explicit bonding using createBond, and not relying on error 8. But I agree, that this feature in the app needs more testing and improvements.

philips77 avatar Jun 15 '19 10:06 philips77

Thanks for the explanation. I confirm it's better to use createBond and I am planning to do so, but in my current scope I am before creating a bond. For my productive application I will use createBond method, but during development together with my BLE pheripheral device it would be good to raise a notification when accessing such characteristics returning such error codes. I understand that behavior depends on the phone type - as you said - I use a Pixel 3 with Android 9 - it does not start bonding in case of GATT error 8. So I just want to handle the error in my app.

Well, at the end it is not an real issue for me, but maybe you can think about optimizations on getting any feedback evaluatable by the calling unit.

chrislro2019 avatar Jun 15 '19 10:06 chrislro2019

@philips77 I believe that would be good to call fail callback anyway as not all the devices for sure repeat calls. What we have in our app is:

2021-01-21 17:31:31.046 D/MyBLEManager: Nordic|gatt.requestMtu(517)
2021-01-21 17:31:31.046 D/BluetoothGatt: configureMTU() - device: 80:91:33:63:F1:56 mtu: 517
2021-01-21 17:31:31.059 D/MyBLEManager: performConnect: connected
2021-01-21 17:31:31.059 D/MyBLEManager: performConnect: awaitDeviceDisconnected
2021-01-21 17:31:31.069 D/BluetoothGatt: onConfigureMTU() - Device=80:91:33:63:F1:56 mtu=517 status=0
2021-01-21 17:31:31.069 I/MyBLEManager: Nordic|MTU changed to: 517
2021-01-21 17:31:31.077 D/MyBLEManager: handleInitialization: before reading uuid
2021-01-21 17:31:31.080 D/MyBLEManager: Nordic|gatt.readCharacteristic(x)
2021-01-21 17:31:31.134 D/BluetoothGatt: onConnectionUpdated() - Device=80:91:33:63:F1:56 interval=36 latency=0 timeout=500 status=0
2021-01-21 17:31:31.134 I/MyBLEManager: Nordic|Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
2021-01-21 17:31:31.226 W/MyBLEManager: Nordic|Authentication required (137)
2021-01-21 17:31:34.286 D/BluetoothGatt: onClientConnectionState() - status=22 clientIf=6 device=80:91:33:63:F1:56
2021-01-21 17:31:34.287 D/MyBLEManager: Nordic|[Callback] Connection state changed with status: 22 and new state: 0 (DISCONNECTED)
2021-01-21 17:31:34.287 W/MyBLEManager: Nordic|Error: (0x16): GATT CONN TERMINATE LOCAL HOST
2021-01-21 17:31:34.287 I/MyBLEManager: Nordic|Disconnected
2021-01-21 17:31:34.290 D/MyBLEManager: Nordic|gatt.refresh() (hidden)

so we are just disconnected after reading characteristic and we are not aware of the reason Would be good to call some fail callback or have one more to provide additional information where error 137 would live.

yevhenii-rechun avatar Jan 21 '21 15:01 yevhenii-rechun

Hi, we faced this kind of error recently, with a write.await() call which got stuck (no timeout) due to an error on GATT INSUF AUTHORIZATION (8) on reconnexion (the device was already bonded). All following request were waiting for this one to finish. We had to reboot the handset so the library would be initialized again and the following reconnexion was successful. So it would have been nice to have some kind of "timeout" or callback for this. We ended up using write.enqueue() instead with a timeout in our application to detect this kind of behavior.

Chevalier-Maxime avatar Feb 22 '22 16:02 Chevalier-Maxime