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
This commit is contained in:
Johanna Ye
2021-06-30 17:31:01 +02:00
parent e05b631948
commit 9eeafe9d52

View File

@@ -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 */
@@ -126,6 +129,27 @@ public final class BluetoothGatt implements BluetoothProfile {
/** Connection parameter update - Request low power, reduced data rate connection parameters. */
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.
*
@@ -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;
}
/**