Skip to content

Commit

Permalink
Merge pull request #597 from NordicSemiconductor/bugfix/bonding-cance…
Browse files Browse the repository at this point in the history
…lled

Fixed handling cancelled bonding for read/write operations
  • Loading branch information
philips77 authored Oct 11, 2024
2 parents ec3332b + ba48a45 commit 3c9300a
Showing 1 changed file with 69 additions and 27 deletions.
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

0 comments on commit 3c9300a

Please sign in to comment.