+            // Note: To workaround https://issuetracker.google.com/issues/36995652
+            // Always call BluetoothDevice#connectGatt() with autoConnect=false
+            // (the race condition does not affect that case). If that connection times out
+            // you will get a callback with status=133. Then call BluetoothGatt#connect()
+            // to initiate a background connection.
This commit is contained in:
geeksville
2020-06-04 09:35:25 -07:00
parent 88bfc612a9
commit d526d11d20
2 changed files with 34 additions and 8 deletions

View File

@@ -580,12 +580,15 @@ class RadioInterfaceService : Service(), Logging {
} else {
if (safe != null) {
info("Closing radio interface service")
val s = safe
safe =
null // We do this first, because if we throw we still want to mark that we no longer have a valid connection
if (logSends)
sentPacketsLog.close()
if (logReceives)
receivedPacketsLog.close()
safe?.close()
safe = null
s?.close()
onDisconnect(isPermanent = true) // Tell any clients we are now offline
} else {
debug("Radio was not connected, skipping disable")

View File

@@ -208,6 +208,12 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
it.invoke()
}
// Note: To workaround https://issuetracker.google.com/issues/36995652
// Always call BluetoothDevice#connectGatt() with autoConnect=false
// (the race condition does not affect that case). If that connection times out
// you will get a callback with status=133. Then call BluetoothGatt#connect()
// to initiate a background connection.
// Queue a new connection attempt
val cb = connectionCallback
if (cb != null) {
@@ -457,21 +463,37 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
// see https://stackoverflow.com/questions/40156699/which-correct-flag-of-autoconnect-in-connectgatt-of-ble for
// more info.
// Otherwise if you pass in false, it will try to connect now and will timeout and fail in 30 seconds.
private fun queueConnect(autoConnect: Boolean = false, cont: Continuation<Unit>) {
private fun queueConnect(
autoConnect: Boolean = false,
cont: Continuation<Unit>,
isFirstAttempt: Boolean
) {
this.autoConnect = autoConnect
// assert(gatt == null) this now might be !null with our new reconnect support
queueWork("connect", cont) {
// Note: To workaround https://issuetracker.google.com/issues/36995652
// Always call BluetoothDevice#connectGatt() with autoConnect=false
// (the race condition does not affect that case). If that connection times out
// you will get a callback with status=133. Then call BluetoothGatt#connect()
// to initiate a background connection.
val autoNow = if (isFirstAttempt) false else autoConnect
val g =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
device.connectGatt(
context,
autoConnect,
autoNow,
gattCallback,
BluetoothDevice.TRANSPORT_LE
)
} else {
device.connectGatt(context, autoConnect, gattCallback)
device.connectGatt(
context,
autoNow,
gattCallback
)
}
if (g != null)
gatt = g
@@ -501,17 +523,18 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
cb
else
null
queueConnect(autoConnect, CallbackContinuation(cb))
queueConnect(autoConnect, CallbackContinuation(cb), true)
}
/// Restart any previous connect attempts
private fun reconnect() {
connectionCallback?.let { cb ->
queueConnect(true, CallbackContinuation(cb))
queueConnect(true, CallbackContinuation(cb), false)
}
}
fun connect(autoConnect: Boolean = false) = makeSync<Unit> { queueConnect(autoConnect, it) }
fun connect(autoConnect: Boolean = false) =
makeSync<Unit> { queueConnect(autoConnect, it, true) }
private fun queueReadCharacteristic(
c: BluetoothGattCharacteristic,