summaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothGatt.java
diff options
context:
space:
mode:
authorJohanna Ye <xincheny@google.com>2021-06-30 17:31:01 +0200
committerJohanna Ye <xincheny@google.com>2021-07-01 10:51:03 +0200
commit8bc7d18ae11c21a37e7eb9cc034a69cc936bdea9 (patch)
tree4ed4e873336d074cc514c4ea37478efc8eb6ac38 /framework/java/android/bluetooth/BluetoothGatt.java
parent842f394c3d34f5e5779f027bdcde8fcaccd195bd (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.java58
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;
}
/**