diff options
author | Johanna Ye <xincheny@google.com> | 2021-06-30 17:31:01 +0200 |
---|---|---|
committer | Johanna Ye <xincheny@google.com> | 2021-07-01 10:51:03 +0200 |
commit | 8bc7d18ae11c21a37e7eb9cc034a69cc936bdea9 (patch) | |
tree | 4ed4e873336d074cc514c4ea37478efc8eb6ac38 /framework/java/android/bluetooth/BluetoothGatt.java | |
parent | 842f394c3d34f5e5779f027bdcde8fcaccd195bd (diff) |
Fix long characteristic write concurrency bug.
Tag: #stability
Test: Bramble (pixel phone) with test app
Bug: 169559728
Ignore-AOSP-First: Current security annotation parity
Merged-In: I3e3a5ff0965c1ca4f79e70e6163bc5d6917edbd1
Change-Id: Ia2d821c5d34d8d035fbbb0b33b9bf4fc8c08b354
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothGatt.java')
-rw-r--r-- | framework/java/android/bluetooth/BluetoothGatt.java | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index 1d08ddb65c..b3a7c8830d 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -75,6 +75,9 @@ public final class BluetoothGatt implements BluetoothProfile { private static final int CONN_STATE_DISCONNECTING = 3; private static final int CONN_STATE_CLOSED = 4; + private static final int WRITE_CHARACTERISTIC_MAX_RETRIES = 5; + private static final int WRITE_CHARACTERISTIC_TIME_TO_WAIT = 1000; // milliseconds + private List<BluetoothGattService> mServices; /** A GATT operation completed successfully */ @@ -127,6 +130,27 @@ public final class BluetoothGatt implements BluetoothProfile { public static final int CONNECTION_PRIORITY_LOW_POWER = 2; /** + * A GATT writeCharacteristic request is started successfully. + * + * @hide + */ + public static final int GATT_WRITE_REQUEST_SUCCESS = 0; + + /** + * A GATT writeCharacteristic request failed to start. + * + * @hide + */ + public static final int GATT_WRITE_REQUEST_FAIL = 1; + + /** + * A GATT writeCharacteristic request is issued to a busy remote device. + * + * @hide + */ + public static final int GATT_WRITE_REQUEST_BUSY = 2; + + /** * No authentication required. * * @hide @@ -428,9 +452,19 @@ public final class BluetoothGatt implements BluetoothProfile { try { final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; - mService.writeCharacteristic(mClientIf, address, handle, - characteristic.getWriteType(), authReq, - characteristic.getValue()); + int requestStatus = GATT_WRITE_REQUEST_FAIL; + for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) { + requestStatus = mService.writeCharacteristic(mClientIf, address, + handle, characteristic.getWriteType(), authReq, + characteristic.getValue()); + if (requestStatus != GATT_WRITE_REQUEST_BUSY) { + break; + } + try { + Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT); + } catch (InterruptedException e) { + } + } mAuthRetryState++; return; } catch (RemoteException e) { @@ -1228,14 +1262,26 @@ public final class BluetoothGatt implements BluetoothProfile { if (device == null) return false; synchronized (mDeviceBusyLock) { - if (mDeviceBusy) return false; + if (mDeviceBusy) { + return false; + } mDeviceBusy = true; } + int requestStatus = GATT_WRITE_REQUEST_FAIL; try { - mService.writeCharacteristic(mClientIf, device.getAddress(), + for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) { + requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(), characteristic.getInstanceId(), characteristic.getWriteType(), AUTHENTICATION_NONE, characteristic.getValue()); + if (requestStatus != GATT_WRITE_REQUEST_BUSY) { + break; + } + try { + Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT); + } catch (InterruptedException e) { + } + } } catch (RemoteException e) { Log.e(TAG, "", e); synchronized (mDeviceBusyLock) { @@ -1244,7 +1290,7 @@ public final class BluetoothGatt implements BluetoothProfile { return false; } - return true; + return requestStatus == GATT_WRITE_REQUEST_SUCCESS; } /** |