diff --git a/TODO.md b/TODO.md index b06166bb6..c05937a7d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,38 +1,6 @@ # Remaining tasks before declaring 1.0 -- turning off Bluetooth on oneplus causes a harmless exception - devwork is null - - -06-29 08:47:10.007 29788-29812/com.geeksville.mesh D/BluetoothGatt: configureMTU() - device: 24:62:AB:F8:40:9A mtu: 512 -06-29 08:47:10.007 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Starting failsafe timer 5000 -06-29 08:47:10.014 29788-29812/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work reconnect is completed, resuming status=0, res=kotlin.Unit -06-29 08:47:10.016 29788-31466/com.geeksville.mesh I/com.geeksville.mesh.service.BluetoothInterface: Connected to radio! -06-29 08:47:10.016 29788-31466/com.geeksville.mesh D/BluetoothGatt: refresh() - device: 24:62:AB:F8:40:9A -06-29 08:47:10.220 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: reqMtu -06-29 08:47:15.009 29788-31466/com.geeksville.mesh E/com.geeksville.mesh.service.SafeBluetooth: Failsafe BLE timer expired! (exception none -06-29 08:47:15.011 29788-29859/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Starting failsafe timer 5000 -06-29 08:47:15.015 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: reqMtu -06-29 08:47:15.016 29788-31466/com.geeksville.mesh D/BluetoothGatt: configureMTU() - device: 24:62:AB:F8:40:9A mtu: 512 -06-29 08:47:15.028 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work reqMtu is completed, resuming status=4404, res=kotlin.Unit -06-29 08:47:15.029 29788-31466/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Scheduling reconnect because Giving up on setting MTUs, forcing disconnect com.geeksville.mesh.service.SafeBluetooth$BLEStatusException: Bluetooth status=4404 while doing reqMtu -06-29 08:47:15.034 29788-30155/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Forcing disconnect and hopefully device will comeback (disabling forced refresh) -06-29 08:47:15.034 29788-30155/com.geeksville.mesh I/com.geeksville.mesh.service.SafeBluetooth: Closing our GATT connection -06-29 08:47:15.035 29788-30155/com.geeksville.mesh D/BluetoothGatt: cancelOpen() - device: 24:62:AB:F8:40:9A -06-29 08:47:15.036 29788-30155/com.geeksville.mesh D/BluetoothGatt: close() -06-29 08:47:15.037 29788-30155/com.geeksville.mesh D/BluetoothGatt: unregisterApp() - mClientIf=5 -06-29 08:47:15.037 29788-29813/com.geeksville.mesh D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=24:62:AB:F8:40:9A -06-29 08:47:15.037 29788-29813/com.geeksville.mesh W/BluetoothGatt: Unhandled exception in callback - java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.BluetoothGattCallback.onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)' on a null object reference - at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:182) - at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70) - at android.os.Binder.execTransact(Binder.java:446) -06-29 08:47:16.040 29788-31466/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Attempting reconnect -06-29 08:47:16.041 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: connect -06-29 08:47:16.041 29788-31466/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: connect -06-29 08:47:16.043 29788-31466/com.geeksville.mesh D/BluetoothGatt: connect() - device: 24:62:AB:F8:40:9A, auto: false -06-29 08:47:16.043 29788-31466/com.geeksville.mesh D/BluetoothGatt: registerApp() - -- soyes sx ble problems (again) +- fix release build inclusion of firmware - Android frontend should refetch the android messages from backend service on Resume - disable software update button after update finishes - first message sent is still doubled for some people diff --git a/app/build.gradle b/app/build.gradle index e9010b104..6f06e641c 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 10782 // format is Mmmss (where M is 1+the numeric major number - versionName "0.7.82" + versionCode 10783 // format is Mmmss (where M is 1+the numeric major number + versionName "0.7.83" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { 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 6560919c4..92ba0eb7e 100644 --- a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt @@ -169,6 +169,7 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String * this is created in onCreate() * We do an ugly hack of keeping it in the singleton so we can share it for the rare software update case */ + @Volatile var safe: SafeBluetooth? = null } @@ -332,7 +333,10 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String delay(1000) // Give some nasty time for buggy BLE stacks to shutdown (500ms was not enough) reconnectJob = null // Any new reconnect requests after this will be allowed to run warn("Attempting reconnect") - startConnect() + if (safe != null) // check again, because we just slept for 1sec, and someone might have closed our interface + startConnect() + else + warn("Not connecting, because safe==null, someone must have closed us") } else { warn("Abandoning reconnect because safe==null, someone must have closed the device") } @@ -421,7 +425,7 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String override fun close() { if (safe != null) { - info("Closing radio interface service") + info("Closing BluetoothInterface") 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 diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 21daedcbb..3835ec0d6 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -398,7 +398,8 @@ class MeshService : Service(), Logging { } - override fun toString() = summaryString + // Note: do not override toString, it causes infinite recursion on some androids (because contextWrapper.getResources calls to string) + // override fun toString() = summaryString /** * Generate a new version of our notification - reflecting current app state 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 008fb0f99..ec3bf6dee 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -11,7 +11,6 @@ import com.geeksville.concurrent.CallbackContinuation import com.geeksville.concurrent.Continuation import com.geeksville.concurrent.SyncContinuation import com.geeksville.util.exceptionReporter -import com.geeksville.util.ignoreException import kotlinx.coroutines.* import java.io.Closeable import java.util.* @@ -122,6 +121,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD // Our own custom BLE status codes private val STATUS_RELIABLE_WRITE_FAILED = 4403 private val STATUS_TIMEOUT = 4404 + private val STATUS_NOSTART = 4405 private val gattCallback = object : BluetoothGattCallback() { @@ -311,7 +311,14 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD isSettingMtu = false // Most work is not doing MTU stuff, the work that is will re set this flag - logAssert(newWork.startWork()) + val started = newWork.startWork() + if (!started) { + errormsg("Failed to start work, returned error status") + completeWork( + STATUS_NOSTART, + Unit + ) // abandon the current attempt and try for another + } } } @@ -387,6 +394,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD */ private fun failAllWork(ex: Exception) { synchronized(workQueue) { + warn("Failing ${workQueue.size} works, because ${ex.message}") workQueue.forEach { it.completion.resumeWithException(ex) } @@ -676,10 +684,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD msecsLeft -= 100 } - if (gatt != null) { + gatt?.let { g2 -> warn("Android onConnectionStateChange did not run, manually closing") - gatt?.close() - gatt = null + gatt = + null // clear gat before calling close, bcause close might throw dead object exception + g2.close() } } catch (ex: DeadObjectException) { warn("Ignoring dead object exception, probably bluetooth was just disabled") @@ -703,10 +712,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD closeGatt() - ignoreException { - // Hmm - sometimes the "Connection closing" exception comes back to us - ignore it - failAllWork(BLEException("Connection closing")) - } + failAllWork(BLEException("Connection closing")) } /** diff --git a/geeksville-androidlib b/geeksville-androidlib index b2d359e2e..792b33a4a 160000 --- a/geeksville-androidlib +++ b/geeksville-androidlib @@ -1 +1 @@ -Subproject commit b2d359e2e1c9ed0a931eb6f2d909355b2fd93cff +Subproject commit 792b33a4a82316d0e15be1e15fcf2d777fdc41e0