Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fixed handling cancelled bonding for read/write operations
  • Loading branch information
philips77 committed Oct 11, 2024
commit ba48a45201f81157acf811dd82d00956049a18a3
96 changes: 69 additions & 27 deletions ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,14 @@ public void onReceive(final Context context, final Intent intent) {
postCallback(c -> c.onBondingFailed(device));
postBondingStateChange(o -> o.onBondingFailed(device));
log(Log.WARN, () -> "Bonding failed");
if (request != null && (request.type == Request.Type.CREATE_BOND || request.type == Request.Type.ENSURE_BOND)) {
if (request != null && (
request.type == Request.Type.CREATE_BOND ||
request.type == Request.Type.ENSURE_BOND ||
// The following requests may trigger bonding.
request.type == Request.Type.WRITE ||
request.type == Request.Type.WRITE_DESCRIPTOR ||
request.type == Request.Type.READ ||
request.type == Request.Type.READ_DESCRIPTOR)) {
request.notifyFail(device, FailCallback.REASON_REQUEST_FAILED);
request = null;
}
Expand Down Expand Up @@ -2510,19 +2517,26 @@ public void onCharacteristicRead(@NonNull final BluetoothGatt gatt,
rr.notifySuccess(gatt.getDevice());
}
}
} else if (status == 137 /* GATT AUTH FAIL */) {
// Bonding failed or was cancelled.
Log.w(TAG, "Reading failed with status " + status);
// The bond state receiver will fail the request. Stop here.
return;
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION
|| status == 8 /* GATT INSUF AUTHORIZATION */
|| status == 137 /* GATT AUTH FAIL */) {
|| status == 8 /* GATT INSUF AUTHORIZATION */) {
// This is called when bonding attempt failed, but the app is still trying to read.
// We need to cancel the request here, as bonding won't start.
log(Log.WARN, () -> "Authentication required (" + status + ")");
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) {
// This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352
Log.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
postCallback(c -> c.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status));
}
// The request will be repeated when the bond state changes to BONDED.
return;
if (request instanceof final ReadRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
}
} else {
Log.e(TAG, "onCharacteristicRead error " + status);
Log.e(TAG, "onCharacteristicRead error " + status + ", bond state: " + gatt.getDevice().getBondState());
if (request instanceof final ReadRequest rr) {
rr.notifyFail(gatt.getDevice(), status);
}
Expand Down Expand Up @@ -2557,19 +2571,26 @@ public void onCharacteristicWrite(final BluetoothGatt gatt,
wr.notifySuccess(gatt.getDevice());
}
}
} else if (status == 137 /* GATT AUTH FAIL */) {
// This never happens for Write operations, for some reason.
Log.w(TAG, "Writing failed with status " + status);
// The bond state receiver will fail the request. Stop here.
return;
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION
|| status == 8 /* GATT INSUF AUTHORIZATION */
|| status == 137 /* GATT AUTH FAIL */) {
|| status == 8 /* GATT INSUF AUTHORIZATION */) {
// This is called when bonding attempt failed, but the app is still trying to write.
// We need to cancel the request here, as bonding won't start.
log(Log.WARN, () -> "Authentication required (" + status + ")");
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) {
// This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352
Log.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
postCallback(c -> c.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status));
}
// The request will be repeated when the bond state changes to BONDED.
return;
if (request instanceof final WriteRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
}
} else {
Log.e(TAG, "onCharacteristicWrite error " + status);
Log.e(TAG, "onCharacteristicWrite error " + status + ", bond state: " + gatt.getDevice().getBondState());
if (request instanceof final WriteRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
// Automatically abort Reliable Write when write error happen
Expand Down Expand Up @@ -2607,9 +2628,16 @@ public void onReliableWriteCompleted(@NonNull final BluetoothGatt gatt,
}

@Override
public void onDescriptorRead(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) {
final byte[] data = descriptor.getValue();
public void onDescriptorRead(final BluetoothGatt gatt,
final BluetoothGattDescriptor descriptor,
final int status) {
onDescriptorRead(gatt, descriptor, status, descriptor.getValue());
}

@Override
public void onDescriptorRead(final @NonNull BluetoothGatt gatt,
final @NonNull BluetoothGattDescriptor descriptor,
final int status, final @NonNull byte[] data) {
if (status == BluetoothGatt.GATT_SUCCESS) {
log(Log.INFO, () -> "Read Response received from descr. " + descriptor.getUuid() +
", value: " + ParserUtils.parse(data));
Expand All @@ -2623,19 +2651,26 @@ public void onDescriptorRead(final BluetoothGatt gatt, final BluetoothGattDescri
rr.notifySuccess(gatt.getDevice());
}
}
} else if (status == 137 /* GATT AUTH FAIL */) {
// Bonding failed or was cancelled.
Log.w(TAG, "Reading descriptor failed with status " + status);
// The bond state receiver will fail the request. Stop here.
return;
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION
|| status == 8 /* GATT INSUF AUTHORIZATION */
|| status == 137 /* GATT AUTH FAIL */) {
|| status == 8 /* GATT INSUF AUTHORIZATION */) {
// This is called when bonding attempt failed, but the app is still trying to read.
// We need to cancel the request here, as bonding won't start.
log(Log.WARN, () -> "Authentication required (" + status + ")");
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) {
// This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352
Log.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
postCallback(c -> c.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status));
}
// The request will be repeated when the bond state changes to BONDED.
return;
if (request instanceof final ReadRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
}
} else {
Log.e(TAG, "onDescriptorRead error " + status);
Log.e(TAG, "onDescriptorRead error " + status + ", bond state: " + gatt.getDevice().getBondState());
if (request instanceof final ReadRequest rr) {
rr.notifyFail(gatt.getDevice(), status);
}
Expand Down Expand Up @@ -2680,19 +2715,26 @@ public void onDescriptorWrite(final BluetoothGatt gatt,
wr.notifySuccess(gatt.getDevice());
}
}
} else if (status == 137 /* GATT AUTH FAIL */) {
// This never happens for Write operations, for some reason.
Log.w(TAG, "Writing descriptor failed with status " + status);
// The bond state receiver will fail the request. Stop here.
return;
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION
|| status == 8 /* GATT INSUF AUTHORIZATION */
|| status == 137 /* GATT AUTH FAIL */) {
|| status == 8 /* GATT INSUF AUTHORIZATION */) {
// This is called when bonding attempt failed, but the app is still trying to write.
// We need to cancel the request here, as bonding won't start.
log(Log.WARN, () -> "Authentication required (" + status + ")");
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) {
// This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352
Log.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
postCallback(c -> c.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status));
}
// The request will be repeated when the bond state changes to BONDED.
return;
if (request instanceof final WriteRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
}
} else {
Log.e(TAG, "onDescriptorWrite error " + status);
Log.e(TAG, "onDescriptorWrite error " + status + ", bond state: " + gatt.getDevice().getBondState());
if (request instanceof final WriteRequest wr) {
wr.notifyFail(gatt.getDevice(), status);
// Automatically abort Reliable Write when write error happen
Expand Down