From 155358551db0b44145e24243e97ace9e0189dd57 Mon Sep 17 00:00:00 2001 From: Anton Usmansky Date: Fri, 1 Nov 2024 10:10:42 +0300 Subject: [PATCH] [android] Feat: retry GATT_ERROR 133 on device.connectGatt fail (#34697) * feat: retry GATT_ERROR 133 on device.connectGatt fail * chore: add constant for error code 133 --- .../java/chip/platform/AndroidBleManager.java | 51 +++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/platform/android/java/chip/platform/AndroidBleManager.java b/src/platform/android/java/chip/platform/AndroidBleManager.java index 52b0052d409ef8..1ca02562236ff0 100644 --- a/src/platform/android/java/chip/platform/AndroidBleManager.java +++ b/src/platform/android/java/chip/platform/AndroidBleManager.java @@ -89,6 +89,7 @@ private static class BleMtuDenylist { private static final int MSG_BLE_SCAN = 0; private static final int MSG_BLE_CONNECT = 1; private static final int MSG_BLE_CONNECT_SUCCESS = 2; + private static final int MSG_BLE_CONNECT_RETRY = 3; private static final int MSG_BLE_FAIL = 99; private static final int BLE_TIMEOUT_MS = 10000; @@ -501,7 +502,10 @@ public void handleMessage(Message msg) { break; case MSG_BLE_CONNECT: stopBleScan(); - connectBLE(msg.obj); + connectBLE(new ConnectionGattCallback((BluetoothDevice) msg.obj)); + break; + case MSG_BLE_CONNECT_RETRY: + connectBLE((ConnectionGattCallback) msg.obj); break; case MSG_BLE_CONNECT_SUCCESS: bleConnectSuccess(msg.obj); @@ -567,20 +571,16 @@ private void stopBleScan() { } } - private void connectBLE(Object bluetoothDeviceObj) { - if (bluetoothDeviceObj == null) { - return; - } - + private void connectBLE(ConnectionGattCallback callback) { // Fail Timer reset. mConnectionHandler.removeMessages(MSG_BLE_FAIL); mConnectionHandler.sendEmptyMessageDelayed(MSG_BLE_FAIL, BLE_TIMEOUT_MS); @SuppressWarnings("unchecked") - BluetoothDevice device = (BluetoothDevice) bluetoothDeviceObj; + BluetoothDevice device = callback.getTargetDevice(); Log.i(TAG, "Connecting"); - BluetoothGatt gatt = device.connectGatt(mContext, false, new ConnectionGattCallback()); + device.connectGatt(mContext, false, callback, BluetoothDevice.TRANSPORT_LE); } class ConnectionGattCallback extends AndroidBluetoothGattCallback { @@ -588,7 +588,22 @@ class ConnectionGattCallback extends AndroidBluetoothGattCallback { private static final int STATE_DISCOVER_SERVICE = 2; private static final int STATE_REQUEST_MTU = 3; + /// Unfortunately GATT 133 is very generic, however among other things + /// it may also show up on device out of range or BLE being closed due to + /// background task termination, hence it is a candidate to retry connectivity. + private static final int kGattRetryableErrorStatus = 133; + private int mState = STATE_INIT; + private BluetoothDevice mDevice; + private int connectRetriesLeft = 3; + + public ConnectionGattCallback(BluetoothDevice device) { + mDevice = device; + } + + public BluetoothDevice getTargetDevice() { + return mDevice; + } @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { @@ -599,9 +614,27 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState mState = STATE_DISCOVER_SERVICE; gatt.discoverServices(); return; - } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + } + + if (newState == BluetoothProfile.STATE_DISCONNECTED + && status == kGattRetryableErrorStatus + && connectRetriesLeft-- > 0) { + Log.i(TAG, "Retries left: " + connectRetriesLeft + ". Retrying connect..."); + + gatt.close(); + + Message msg = mConnectionHandler.obtainMessage(); + msg.what = MSG_BLE_CONNECT_RETRY; + msg.obj = (Object) this; + mConnectionHandler.sendMessage(msg); + + return; + } + + if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Services Disconnected"); } + mConnectionHandler.sendEmptyMessage(MSG_BLE_FAIL); }