Merge "Fix long characteristic write concurrency bug."

This commit is contained in:
Johanna Ye
2021-07-09 15:39:32 +00:00
committed by Gerrit Code Review

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_DISCONNECTING = 3;
private static final int CONN_STATE_CLOSED = 4; 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; private List<BluetoothGattService> mServices;
/** A GATT operation completed successfully */ /** 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. */ /** Connection parameter update - Request low power, reduced data rate connection parameters. */
public static final int CONNECTION_PRIORITY_LOW_POWER = 2; 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. * No authentication required.
* *
@@ -428,9 +452,19 @@ public final class BluetoothGatt implements BluetoothProfile {
try { try {
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
mService.writeCharacteristic(mClientIf, address, handle, int requestStatus = GATT_WRITE_REQUEST_FAIL;
characteristic.getWriteType(), authReq, for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
characteristic.getValue()); 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++; mAuthRetryState++;
return; return;
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1228,14 +1262,26 @@ public final class BluetoothGatt implements BluetoothProfile {
if (device == null) return false; if (device == null) return false;
synchronized (mDeviceBusyLock) { synchronized (mDeviceBusyLock) {
if (mDeviceBusy) return false; if (mDeviceBusy) {
return false;
}
mDeviceBusy = true; mDeviceBusy = true;
} }
int requestStatus = GATT_WRITE_REQUEST_FAIL;
try { 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(), characteristic.getInstanceId(), characteristic.getWriteType(),
AUTHENTICATION_NONE, characteristic.getValue()); 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) { } catch (RemoteException e) {
Log.e(TAG, "", e); Log.e(TAG, "", e);
synchronized (mDeviceBusyLock) { synchronized (mDeviceBusyLock) {
@@ -1244,7 +1290,7 @@ public final class BluetoothGatt implements BluetoothProfile {
return false; return false;
} }
return true; return requestStatus == GATT_WRITE_REQUEST_SUCCESS;
} }
/** /**