From cc05be7d87256255ccc184e6fffbee37eab5629b Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 4 Jul 2020 11:02:18 -0700 Subject: [PATCH 1/5] bug #76 fix a related autobug from feh123's log Non-fatal Exception: kotlin.KotlinNullPointerException at com.geeksville.mesh.service.BluetoothInterface.doDiscoverServicesAndInit(BluetoothInterface.java:357) at com.geeksville.mesh.service.BluetoothInterface.access$doDiscoverServicesAndInit(BluetoothInterface.java:78) at com.geeksville.mesh.service.BluetoothInterface$onConnect$1.invokeSuspend(BluetoothInterface.java:429) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(BaseContinuationImpl.java:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.java:56) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:571) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.java:738) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.java:678) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.java:665) --- .../mesh/service/BluetoothInterface.kt | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt index 5a3cac3b7..235a6e58c 100644 --- a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt @@ -354,42 +354,46 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String private var isFirstTime = true private fun doDiscoverServicesAndInit() { - safe!!.asyncDiscoverServices { discRes -> - try { - discRes.getOrThrow() + val s = safe + if (s == null) + warn("Interface is shutting down, so skipping discover") + else + s.asyncDiscoverServices { discRes -> + try { + discRes.getOrThrow() - service.serviceScope.handledLaunch { - try { - debug("Discovered services!") - delay(1000) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null + service.serviceScope.handledLaunch { + try { + debug("Discovered services!") + delay(1000) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null - /* if (isFirstTime) { - isFirstTime = false - throw BLEException("Faking a BLE failure") - } */ + /* if (isFirstTime) { + isFirstTime = false + throw BLEException("Faking a BLE failure") + } */ - fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER) + fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER) - // We treat the first send by a client as special - isFirstSend = true + // We treat the first send by a client as special + isFirstSend = true - // Now tell clients they can (finally use the api) - service.onConnect() + // Now tell clients they can (finally use the api) + service.onConnect() - // Immediately broadcast any queued packets sitting on the device - doReadFromRadio(true) - } catch (ex: BLEException) { - scheduleReconnect( - "Unexpected error in initial device enumeration, forcing disconnect $ex" - ) + // Immediately broadcast any queued packets sitting on the device + doReadFromRadio(true) + } catch (ex: BLEException) { + scheduleReconnect( + "Unexpected error in initial device enumeration, forcing disconnect $ex" + ) + } } + } catch (ex: BLEException) { + scheduleReconnect( + "Unexpected error discovering services, forcing disconnect $ex" + ) } - } catch (ex: BLEException) { - scheduleReconnect( - "Unexpected error discovering services, forcing disconnect $ex" - ) } - } } private var needForceRefresh = true From 92b3fa8d1f1f53358e6854d7d8365ef35195d142 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 4 Jul 2020 11:17:11 -0700 Subject: [PATCH 2/5] bug #76 - old sonys can take a VERY long time for the setMTU operation to complete. Change timeout to 10 secs (units in the field were showing the mtu operation completing after 5 seconds. Also - don't throw an exception if we encounter a result when we've already killed things with the failsafe timer --- .../geeksville/mesh/service/SafeBluetooth.kt | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt index ee817b0e2..411956758 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -392,25 +392,30 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD // startup next job in queue before calling the completion handler val work = synchronized(workQueue) { - val w = - currentWork - ?: throw Exception("currentWork was null") // will throw if null, which is helpful (FIXME - throws in the field - because of a bogus mtu completion gatt call) - stopCurrentWork() // We are now no longer working on anything + val w = currentWork - startNewWork() + if (w != null) { + stopCurrentWork() // We are now no longer working on anything + + startNewWork() + } w } - debug("work ${work.tag} is completed, resuming status=$status, res=$res") - if (status != 0) - work.completion.resumeWithException( - BLEStatusException( - status, - "Bluetooth status=$status while doing ${work.tag}" + if (work == null) + warn("wor completed, but we already killed it via failsafetimer? status=$status, res=$res") + else { + debug("work ${work.tag} is completed, resuming status=$status, res=$res") + if (status != 0) + work.completion.resumeWithException( + BLEStatusException( + status, + "Bluetooth status=$status while doing ${work.tag}" + ) ) - ) - else - work.completion.resume(Result.success(res) as Result) + else + work.completion.resume(Result.success(res) as Result) + } } } @@ -607,7 +612,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueRequestMtu( len: Int, cont: Continuation - ) = queueWork("reqMtu", cont, 5 * 1000) { + ) = queueWork("reqMtu", cont, 10 * 1000) { isSettingMtu = true gatt?.requestMtu(len) ?: false } From f7ca63ed923fd7bf2d407b30875de522422840ec Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 4 Jul 2020 11:32:51 -0700 Subject: [PATCH 3/5] better error message if we can't find the update service --- .../java/com/geeksville/mesh/service/SoftwareUpdateService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt index d1f6957f1..9bf8e843b 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt @@ -268,7 +268,8 @@ class SoftwareUpdateService : JobIntentService(), Logging { fun doUpdate(context: Context, sync: SafeBluetooth, assetName: String) { try { val g = sync.gatt!! - val service = g.services.find { it.uuid == SW_UPDATE_UUID }!! + val service = g.services.find { it.uuid == SW_UPDATE_UUID } + ?: throw BLEException("Couldn't find update service") info("Starting firmware update for $assetName") From bc6fa0b1bb48e1c39d321d3bbdc7b946ccb3aca9 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 4 Jul 2020 11:33:24 -0700 Subject: [PATCH 4/5] If we have an exception thrown *back to us* complain and ignore it? --- .../java/com/geeksville/mesh/service/SafeBluetooth.kt | 9 ++++++++- geeksville-androidlib | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt index 411956758..1e7b6ea07 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -426,7 +426,14 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD synchronized(workQueue) { warn("Failing ${workQueue.size} works, because ${ex.message}") workQueue.forEach { - it.completion.resumeWithException(ex) + try { + it.completion.resumeWithException(ex) + } catch (ex: Exception) { + errormsg( + "Mystery exception, why were we informed about our own exceptions?", + ex + ) + } } workQueue.clear() stopCurrentWork() diff --git a/geeksville-androidlib b/geeksville-androidlib index 95c5a9aa9..99dbf61fa 160000 --- a/geeksville-androidlib +++ b/geeksville-androidlib @@ -1 +1 @@ -Subproject commit 95c5a9aa950f917857a3cc0c7cd84a4a56993032 +Subproject commit 99dbf61fad087db910be7f74867a8f14aba877a4 From 6c7d108545cff7b3ed0a550a666bb11d774ab030 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 4 Jul 2020 12:47:38 -0700 Subject: [PATCH 5/5] 0.7.89 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a200cd9c0..fd19ee04e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId "com.geeksville.mesh" minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) targetSdkVersion 29 - versionCode 10788 // format is Mmmss (where M is 1+the numeric major number - versionName "0.7.88" + versionCode 10789 // format is Mmmss (where M is 1+the numeric major number + versionName "0.7.89" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes {