Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disconnection reason and events fixed #522

Merged
merged 1 commit into from Sep 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 27 additions & 8 deletions ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java
Expand Up @@ -513,6 +513,8 @@ void close() {
// the receiver must have been not registered or unregistered before.
}
synchronized (LOCK) {
final boolean wasConnected = connected;
final BluetoothDevice oldBluetoothDevice = bluetoothDevice;
if (bluetoothGatt != null) {
if (manager.shouldClearCacheWhenDisconnected()) {
if (internalRefreshDeviceCache()) {
Expand Down Expand Up @@ -540,6 +542,13 @@ void close() {
initialization = false;
bluetoothDevice = null;
connected = false;
connectionState = BluetoothProfile.STATE_DISCONNECTED;
mtu = 23;
interval = latency = timeout = 0;
if (wasConnected && oldBluetoothDevice != null) {
postCallback(c -> c.onDeviceDisconnected(oldBluetoothDevice));
postConnectionStateChange(o -> o.onDeviceDisconnected(oldBluetoothDevice, ConnectionObserver.REASON_SUCCESS));
}
}
}

Expand Down Expand Up @@ -1842,6 +1851,7 @@ private void notifyDeviceDisconnected(@NonNull final BluetoothDevice device, fin
if (!wasConnected) {
log(Log.WARN, () -> "Connection attempt timed out");
close();
// Close will not notify the observer as the device was not connected.
postCallback(c -> c.onDeviceDisconnected(device));
postConnectionStateChange(o -> o.onDeviceFailedToConnect(device, status));
// ConnectRequest was already notified
Expand Down Expand Up @@ -2124,12 +2134,18 @@ public void onConnectionStateChange(@NonNull final BluetoothGatt gatt,
final boolean wasConnected = connected;
final boolean notSupported = deviceNotSupported;
// ...because the next method sets them to false.
notifyDeviceDisconnected(gatt.getDevice(), // this may call close()
timeout ?
ConnectionObserver.REASON_TIMEOUT :
notSupported ?
ConnectionObserver.REASON_NOT_SUPPORTED :
mapDisconnectStatusToReason(status));

// notifyDeviceDisconnected(...) may call close()
if (timeout) {
notifyDeviceDisconnected(gatt.getDevice(), ConnectionObserver.REASON_TIMEOUT);
} else if (notSupported) {
notifyDeviceDisconnected(gatt.getDevice(), ConnectionObserver.REASON_NOT_SUPPORTED);
} else if (request != null && request.type == Request.Type.DISCONNECT) {
notifyDeviceDisconnected(gatt.getDevice(), ConnectionObserver.REASON_SUCCESS);
} else {
// Note, that even if the status is SUCCESS, the reported reason won't be success.
notifyDeviceDisconnected(gatt.getDevice(), mapDisconnectStatusToReason(status));
}

// Signal the current request, if any.
if (request != null) {
Expand Down Expand Up @@ -2809,12 +2825,15 @@ public void onReadRemoteRssi(@NonNull final BluetoothGatt gatt,

private int mapDisconnectStatusToReason(final int status) {
return switch (status) {
case GattError.GATT_SUCCESS -> ConnectionObserver.REASON_SUCCESS;
case GattError.GATT_CONN_TERMINATE_LOCAL_HOST ->
ConnectionObserver.REASON_TERMINATE_LOCAL_HOST;
case GattError.GATT_CONN_TERMINATE_PEER_USER ->
ConnectionObserver.REASON_TERMINATE_PEER_USER;
case GattError.GATT_CONN_TIMEOUT -> ConnectionObserver.REASON_TIMEOUT;
// When a remote device disconnects, some phones return the TIMEOUT error, while other
// just SUCCESS. Anyway, in both cases the device has not been disconnected by the
// user, so the reason should be the TIMEOUT.
case GattError.GATT_CONN_TIMEOUT, GattError.GATT_SUCCESS ->
ConnectionObserver.REASON_TIMEOUT;
default -> ConnectionObserver.REASON_UNKNOWN;
};
}
Expand Down