Fitbit / bitgatt

The FitbitGatt API is designed to provide a strong state machine around all Android gatt operations with the aim of making Android BLE development across Android vendors as straightforward and side-effect free as possible.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GATT_INSUF_AUTHORIZATION

NathanRussak opened this issue · comments

Describe the bug
I am trying to connect to a BLE thermometer that has an "indicate" characteristic. When running my app with the debugger attached everything works perfectly. I can connect to the device, discover services, subscribe to the characteristic, get updates, etc. But anytime I run my app without the debugger my device connection is always severed after 2-3 seconds. The logs call out a GATT_INSUF_AUTHORIZATION error.

Here are logs from the setup process:

22:40:54.132 17493-17493 D/PeripheralScanner: Start High priority Scan
22:40:54.132 17493-17493 V/PeripheralScanner: Scan filter's size: 5
22:40:54.132 17493-17493 D/BluetoothAdapter: isLeEnabled(): ON
22:40:54.133 17493-17521 D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=9 mScannerId=0
22:40:54.136 17493-17493 V/PeripheralScanner: Starting scan, scan count in this 120000 ms is 1
22:40:54.136 17493-17493 I/FitbitGatt: On scan status changed true
22:41:00.439 17493-17493 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -51, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattConnectTransaction
22:41:00.441 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -51, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State DISCONNECTED, Success State CONNECTED
22:41:00.443 17493-17554 W/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -51, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] While this instance isn't in the cache, there is already a connection in the queue, please be careful not to create too many client_ifs #developerlove.
22:41:00.444 17493-17554 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -51, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Android BluetoothGatt was null, start a new Android BluetoothGatt instance connect to device
22:41:00.446 17493-17554 D/BluetoothGatt: connect() - device: D0:5F:B8:51:5A:E7, auto: false
22:41:00.446 17493-17554 D/BluetoothGatt: registerApp()
22:41:00.447 17493-17554 D/BluetoothGatt: registerApp() - UUID=c4c51102-4042-4d2a-add8-43a6e0531588
22:41:00.451 17493-17521 D/BluetoothGatt: onClientRegistered() - status=0 clientIf=10
22:41:00.791 17493-17521 D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=10 device=D0:5F:B8:51:5A:E7
22:41:00.795 17493-17521 V/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_ERROR
22:41:00.797 17493-17521 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_3
22:41:00.799 17493-17521 D/GattClientCallback: [TEMP]Connection state: Not-Connected
22:41:00.801 17493-17521 I/GattClientCallback: [TEMP] The connection state may have changed in error
22:41:00.804 17493-17521 D/GattClientCallback: [TEMP] Disconnection reason: GATT_CONN_UNKNOWN
22:41:00.806 17493-17521 W/GattClientCallback: [TEMP] disconnected, waiting 1000ms for full disconnection
22:41:00.806 17493-17521 D/BluetoothGatt: cancelOpen() - device: D0:5F:B8:51:5A:E7
22:41:01.850 17493-17552 D/BluetoothGatt: close()
22:41:01.850 17493-17552 D/BluetoothGatt: unregisterApp() - mClientIf=10
22:41:01.855 17493-17552 I/GattClientCallback: [TEMP] Full disconnection
22:41:01.859 17493-17552 W/GattTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] The transaction GattConnectTransaction failed, Result: Transaction Name: GattConnectTransaction, Gatt State: DISCONNECTED - State Type: IDLE, Transaction Result Status: FAILURE, Response Status: GATT_SUCCESS, rssi: -60, mtu: 0, Characteristic UUID: null, Service UUID: null, Descriptor UUID: null, Data: null, Offset: 0, txPhy: 1, rxPhy: 1, transaction results: []
22:41:01.861 17493-17552 W/GattTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Halting the execution chain because tx GattConnectTransaction failed
22:41:01.900 17493-17493 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattConnectTransaction
22:41:01.902 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State DISCONNECTED, Success State CONNECTED
22:41:01.904 17493-17554 W/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] While this instance isn't in the cache, there is already a connection in the queue, please be careful not to create too many client_ifs #developerlove.
22:41:01.905 17493-17554 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Android BluetoothGatt was null, start a new Android BluetoothGatt instance connect to device
22:41:01.906 17493-17554 D/BluetoothGatt: connect() - device: D0:5F:B8:51:5A:E7, auto: false
22:41:01.906 17493-17554 D/BluetoothGatt: registerApp()
22:41:01.907 17493-17554 D/BluetoothGatt: registerApp() - UUID=fa45b741-369e-4285-a20c-95fc8b0724e9
22:41:01.911 17493-17521 D/BluetoothGatt: onClientRegistered() - status=0 clientIf=10
22:41:02.044 17493-17521 D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=D0:5F:B8:51:5A:E7
22:41:02.048 17493-17493 I/LowEnergyAclListener: BT change received !
22:41:02.049 17493-17521 V/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_SUCCESS
22:41:02.051 17493-17493 I/LowEnergyAclListener: TEMP Device is now connected
22:41:02.051 17493-17521 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_3
22:41:02.053 17493-17521 D/GattClientCallback: [TEMP]Connection state: Connected
22:41:02.055 17493-17552 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattClientDiscoverServices
22:41:02.056 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State DISCOVERY_SUCCESS
22:41:02.056 17493-17554 D/BluetoothGatt: discoverServices() - device: D0:5F:B8:51:5A:E7
22:41:02.570 17493-17521 D/BluetoothGatt: onConnectionUpdated() - Device=D0:5F:B8:51:5A:E7 interval=78 latency=0 timeout=600 status=0
22:41:03.739 17493-17521 D/BluetoothGatt: onConnectionUpdated() - Device=D0:5F:B8:51:5A:E7 interval=6 latency=0 timeout=500 status=0
22:41:04.133 17493-17521 D/BluetoothGatt: onSearchComplete() = Device=D0:5F:B8:51:5A:E7 Status=0
22:41:04.135 17493-17521 V/GattClientCallback: [TEMP] onServicesDiscovered: Gatt Response Status GATT_SUCCESS
22:41:04.136 17493-17521 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_3
22:41:04.137 17493-17552 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: CompositeClientTransaction
22:41:04.138 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State IDLE
22:41:04.138 17493-17554 I/TransactionQueueController: Implicitly restarting queue
22:41:04.138 17493-17554 V/TransactionQueueController: Starting execution thread
22:41:04.140 17493-17635 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State ENABLE_CHARACTERISTIC_NOTIFICATION_SUCCESS
22:41:04.141 17493-17635 D/BluetoothGatt: setCharacteristicNotification() - uuid: 00002a1c-0000-1000-8000-00805f9b34fb enable: true
22:41:04.144 17493-17635 V/SubscribeToCharacteristicNotificationsTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Notification success on 00002a1c-0000-1000-8000-00805f9b34fb
22:41:04.144 17493-17635 V/StrategyProvider: The current device has properties: AndroidDevice[Google, Pixel 4a (5G), 30, bramble, google, bramble]
22:41:04.145 17493-17635 D/StrategyProvider: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Target android device does not match, no need for strategy
22:41:04.146 17493-17493 V/CompositeClientTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Transaction result: Transaction Name: SubscribeToCharacteristicNotificationsTransaction, Gatt State: ENABLE_CHARACTERISTIC_NOTIFICATION_SUCCESS - State Type: IDLE, Transaction Result Status: SUCCESS, Response Status: GATT_SUCCESS, rssi: 0, mtu: 0, Characteristic UUID: 00002a1c-0000-1000-8000-00805f9b34fb, Service UUID: 00001809-0000-1000-8000-00805f9b34fb, Descriptor UUID: null, Data: null, Offset: 0, txPhy: 1, rxPhy: 1, transaction results: []
22:41:04.147 17493-17635 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State WRITE_DESCRIPTOR_SUCCESS
22:41:04.168 17493-17521 V/GattClientCallback: [TEMP] onDescriptorWrite: Gatt Response Status GATT_SUCCESS
22:41:04.170 17493-17521 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_3
22:41:04.173 17493-17552 V/CompositeClientTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Transaction result: Transaction Name: WriteGattDescriptorTransaction, Gatt State: WRITE_DESCRIPTOR_SUCCESS - State Type: IDLE, Transaction Result Status: SUCCESS, Response Status: GATT_SUCCESS, rssi: -60, mtu: 0, Characteristic UUID: null, Service UUID: null, Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb, Data: null, Offset: 0, txPhy: 1, rxPhy: 1, transaction results: []
22:41:04.174 17493-17552 D/CompositeClientTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Finished running all transactions successfully, last result: Transaction Name: WriteGattDescriptorTransaction, Gatt State: WRITE_DESCRIPTOR_SUCCESS - State Type: IDLE, Transaction Result Status: SUCCESS, Response Status: GATT_SUCCESS, rssi: -60, mtu: 0, Characteristic UUID: null, Service UUID: null, Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb, Data: null, Offset: 0, txPhy: 1, rxPhy: 1, transaction results: []
22:41:04.176 17493-17552 V/TransactionQueueController: Stopping execution thread
22:41:04.177 17493-17552 V/GattClientTransaction: [TEMP] onDescriptorWrite not handled in tx: CompositeClientTransaction
22:41:04.178 17493-17635 D/GattTransaction: Transaction was interrupted while waiting for result, re-interrupting thread : CompositeClientTransaction
22:41:04.178 17493-17635 V/CompositeClientTransaction: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -60, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Transaction Transaction Name: SubscribeToCharacteristicNotificationsTransaction, Gatt State: ENABLE_CHARACTERISTIC_NOTIFICATION_SUCCESS - State Type: IDLE, Transaction Result Status: SUCCESS, Response Status: GATT_SUCCESS, rssi: 0, mtu: 0, Characteristic UUID: 00002a1c-0000-1000-8000-00805f9b34fb, Service UUID: 00001809-0000-1000-8000-00805f9b34fb, Descriptor UUID: null, Data: null, Offset: 0, txPhy: 1, rxPhy: 1, transaction results: [] was successful, moving on to index: 1
22:41:04.178 17493-17635 I/TransactionQueueController$ClientThread: Thread was stopped
22:41:04.224 17493-17521 D/BluetoothGatt: onConnectionUpdated() - Device=D0:5F:B8:51:5A:E7 interval=78 latency=0 timeout=600 status=0

And here are logs when the connection is lost:

22:41:10.234 17493-17636 D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=10 device=D0:5F:B8:51:5A:E7
22:41:10.236 17493-17636 V/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_INSUF_AUTHORIZATION
22:41:10.238 17493-17636 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_5
22:41:10.241 17493-17636 D/GattClientCallback: [TEMP]Connection state: Not-Connected
22:41:10.242 17493-17636 I/GattClientCallback: [TEMP] The connection state may have changed in error
22:41:10.242 17493-17493 I/LowEnergyAclListener: BT change received !
22:41:10.243 17493-17493 I/LowEnergyAclListener: TEMP Device is disconnected
22:41:10.244 17493-17493 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattDisconnectionTransaction
22:41:10.244 17493-17636 D/GattClientCallback: [TEMP] Disconnection reason: GATT_CONN_UNKNOWN
22:41:10.245 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State DISCONNECTED
22:41:10.246 17493-17636 W/GattClientCallback: [TEMP] disconnected, waiting 1000ms for full disconnection
22:41:10.246 17493-17636 D/BluetoothGatt: cancelOpen() - device: D0:5F:B8:51:5A:E7
22:41:10.247 17493-17554 V/LowEnergyAclListener: Successful disconnection
22:41:10.247 17493-17554 I/LowEnergyAclListener: TEMP Notifying listeners of connection disconnected
22:41:10.307 17493-17493 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattConnectTransaction
22:41:10.309 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State DISCONNECTED, Success State CONNECTED
22:41:10.309 17493-17554 W/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] While this instance isn't in the cache, there is already a connection in the queue, please be careful not to create too many client_ifs #developerlove.
22:41:10.310 17493-17554 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Android BluetoothGatt has been used before, using an existing Android BluetoothGatt instance to connect to device
22:41:10.458 17493-17636 D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=D0:5F:B8:51:5A:E7
22:41:10.460 17493-17493 I/LowEnergyAclListener: BT change received !
22:41:10.461 17493-17493 I/LowEnergyAclListener: TEMP Device is now connected
22:41:10.461 17493-17636 V/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_SUCCESS
22:41:10.462 17493-17636 D/GattClientCallback: [TEMP][Threading] Originally called on thread : Binder:17493_5
22:41:10.463 17493-17636 D/GattClientCallback: [TEMP]Connection state: Connected
22:41:10.465 17493-17552 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattClientDiscoverServices
22:41:10.467 17493-17554 V/GattStateTransitionValidator: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Current State IDLE, Success State DISCOVERY_SUCCESS
22:41:10.467 17493-17554 D/BluetoothGatt: discoverServices() - device: D0:5F:B8:51:5A:E7
22:41:10.954 17493-17636 D/BluetoothGatt: onConnectionUpdated() - Device=D0:5F:B8:51:5A:E7 interval=78 latency=0 timeout=600 status=0
22:41:11.288 17493-17552 D/BluetoothGatt: close()
22:41:11.288 17493-17552 D/BluetoothGatt: unregisterApp() - mClientIf=10
22:41:11.291 17493-17552 I/GattClientCallback: [TEMP] Full disconnection
22:41:11.293 17493-17552 V/GattClientTransaction: [TEMP] onPhyRead not handled in tx: GattClientDiscoverServices
22:41:12.320 17493-17493 I/LowEnergyAclListener: BT change received !
22:41:12.325 17493-17493 I/LowEnergyAclListener: TEMP Device is disconnected
22:41:12.326 17493-17493 V/GattConnection: [[FitbitBluetoothDevice Address: D0:5F:B8:51:5A:E7, Name: TEMP, Rssi: -61, Advertising Data: 02010603 02F0FF09 FF4248E7 5A51B85F D0051240 00500002 0A000509 54454D50 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000, Device Origin: SCANNED]] Received transaction: GattDisconnectionTransaction

To Reproduce
Steps to reproduce the behavior:

  1. Run your app without the debugger.
  2. Connect to a BLE device and subscribe to a characteristic.
  3. Wait a few seconds and observe the logs being written by Fitbit Gatt.

Expected behavior
The BLE device should remain connected until it is intentionally disconnected, turned off, or walks out of range.

Peripheral (please complete the following information):

Smartphone (please complete the following information):

  • Device: Google Pixel 4 5G
  • OS: Android R

Additional context
This seems to happen primarily on devices with "indicate" characteristics. In my testing, "notify" characteristics do not seem to be impacted.

@NathanRussak Can you provide the code you have in your application?

Just finished throwing together a simple demo activity that replicates the problem. You can find the source and logs within the attached ZIP.

Insuf_Auth_Demo.zip

@NathanRussak I've replicated the setup (except the pixel phone, used S10 with Android R) and was not able to replicate the issue.
Same services, characteristics and indication setup and running your demo app.

Both with or without the debugger the connection remains stable and am able to get changes indication.

Do you encounter this issue if you use a different phone model?

Sorry for the delayed response @ionutlepi. I actually have an S10 on hand. I'll give it a shot this weekend and provide feedback.

I was able to reproduce the issue on my S10.

My S10 was originally still running Android Q. I ran my sample app and was unable to replicate. I then applied a pending system update to bump it up to Android R and ran the app again. I was able to replicate the issue rather quickly. See the attached logs.

One interesting variance I noticed. When it fails on the Pixel I see this:

V/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_INSUF_AUTHORIZATION

When it fails on the S10 I see this:

E/GattClientCallback: [TEMP] onConnectionStateChange: Gatt Response Status GATT_ERROR

Different error codes.

I don't believe the update to Android R caused this. I think that was purely coincidence. I didn't test enough before upgrading to Android R. The bug doesn't happen 100% of the time but it does happen rather frequently. Typically, if it doesn't happen right away just disconnecting/reconnecting the BLE device or restarting the app will trigger it.

This issue has been, so far, observed on a:

  1. Pixel 2XL (Android 11)
  2. Pixel 4a 5G (Android 11)
  3. Samsung Galaxy S10 (Android 11)
  4. Samsung Galaxy Tab A (Android 10)
  5. Motorola Moto G5+ (Android 8.1)

@NathanRussak thanks for the fresh information will check it out

Checking back in on this.. any update @ionutlepi? Do you require anything further from me to diagnose or replicate the problem?

@NathanRussak checking the S10 log it seems that in this case S10 cannot even connect initially but than manages to connect and the logs end so a little different from the pixel behavior

But based logs i don't see an issue with how bitgatt handless the transactions but rather something going wrong at a lower level.

You can use something the nRF Connect for Mobile to validate the peripheral behaviour outside this library context.

Is your device bonded by any chance? An instability in the bond link could explain this as well.

Thank you

@ionutlepi

Are you referring to CreateBondTransaction? If so then no. My demo app was not attempting to establish a bond. I faintly remember trying this in the past to see if it improved my connectivity issues but gave up on it for some reason.

If this is what I'm missing I can give it another shot. Could you confirm a few things first?

Transaction Limitations

My app needs to be able to connect to 1+ BLE devices. The readme states:

because of the many shifts in connection interval and the other changes that occur it is wise to not try to attempt other gatt operations while a bond attempt is in progress.

  • Is it ok to leave a high priority scan running while bitgatt is attempting to create a bond to "device A"?
  • Is it still safe to perform a gatt operation on a connection belonging to any other device? For example, sending a message to "device A" while bitgatt is attempting to bond with "device B"?

Transaction Order

Can you confirm where in the connection process I should be attempting to bond? For example...

  1. Start a high priority scan.
  2. Run GattConnectTransaction against connection.
  3. Run CreateBondTransaction against connection.
  4. Connection should be all good now.. proceed with other misc things like GattClientDiscoverServicesTransaction, SubscribeToCharacteristicNotificationsTransaction, WriteGattDescriptorTransaction, etc.

@NathanRussak Was not referring to the transaction. With some devices you can bond directly from the android Bluetooth options and was thinking if that was happening

Scanning or running operations on another device should not affect running bond operations.

Did you get a chance to test the device connection also with nRF Connect for Mobile ?

Ah ok. No I don't believe I've tried that. I assumed that bitgatt handled the bonding if it were necessary.

Thanks for the feedback @ionutlepi. Let me try establishing a bond and experimenting with nRF Connect. I'll get back to you with feedback when I'm done.

@ionutlepi was finally able to check out nRF Connect for Mobile. It was able to establish a connection to the BLE thermometer and receive updates via the indicate characteristic. All without bonding.

Just in case it helps I've attached the logs from nRF Connect to this post.

At this point I'm running out of ideas of how to resolve this. The issue impacts only some of the BLE devices I'm interacting with and only in release builds.

@ionutlepi, I observed some interesting things tonight. In an act of desperation I completely removed bitgatt from my demo app and tried to directly use Android's Bluetooth APIs instead. Everything looked great while debugging but as soon as I ran my app without the debugger the same error started happening!

BluetoothProfile.STATE_DISCONNECTED was being sent to BluetoothGattCallback#onConnectionStateChange with a status code of 8. I did some searching and found this stackoverflow post. I tried delaying my call to BluetoothGatt#writeDescriptor as was recommended and the problem vanished!

You can check out the source code of my edits here

I went back to my original usage of bitgatt to apply a similar edit...

// Connect...
gatt.runTx(GattConnectTransaction(...)) {

    // Discover...
    gatt.runTx(GattClientDiscoverServicesTransaction(...)) {

        // Find my service/characteristic/descriptor
        val service: BluetoothGattService
        val characteristic: BluetoothGattCharacteristic
        val descriptor: BluetoothGattDescriptor

        // Delay a tiny bit...
        Handler(Looper.myLooper()).postDelayed({

            // Subscribe
            descriptor.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
            gatt.runTx(CompositeClientTransaction(this, listOf(
                SubscribeToCharacteristicNotificationsTransaction(...),
                WriteGattDescriptorTransaction(...)))) {
                // Should be good to go!
            }
        }, 500L)
    }
}

... and the problem disappeared.

There appears to be some kind of race condition happening in the Android Bluetooth stack that causes problems if you try to subscribe to a characteristic immediately after performing a service discovery. Having my app inject a delay between its calls to bitgatt solved the problem but this feels like a weird android Bluetooth nuance that bitgatt should be responsible for handling. What are your thoughts?

@NathanRussak great find.

The debugger slows everything down so that is why you may not be seeing during a debug session. Also debug builds contain more logs states so that may slow things a little as well.

Per Bitgatt you could set the IntraTransactionDelay by calling this

public void setIntraTransactionDelay(long txDelay) {

Let me know if this works for you.

As per root cause of this issue it could also stem from a combination of a certain peripheral bluetooth chip + Android (i don't think its os specific since you encountered it with different os versions/phones) . I was not able to replicate the issue for example with an nrf52840 DK board or with other internal testing.

For Android i would recommend filling a bug following this process https://source.android.com/setup/contribute/report-bugs and using the barebones android code as a sample for the bug.

As per bitgatt handle of this: IntraTransactionDelay should cover this as fixing the behaviour.

Not sure yet if bitgatt should contain more code specific for this issue as it seems to occur only with certain peripherals. But will consider it and think how the best approach would be.

Thank you for documenting this and all the information provided.

Ah, excellent callout on #setIntraTransactionDelay. I didn't know that property was available. It sounds like exactly what I need! Glad to see this is already part of bitgatt! I'll give it a shot and report my findings.

After leveraging #setIntraTransactionDelay I think I've seen enough improvement to consider this issue closed/resolved. Thanks again for hashing this out with me @ionutlepi.