Skip to content

Commit 607fcfd

Browse files
Staacksclaude
andcommitted
The connect retry gets a budget instead of three tries.
Three attempts were not enough. A refused connection (GATT_ERROR 133) comes back in about 0.35 s, so the whole budget was spent in under three seconds, and the bench kept reaching the end of it: two connects in 34 on 2026-08-28 needed all three attempts, which puts the next one along - the connect that would need a fourth - at about one in forty. That is the transfer flake the BLE suite was still reporting after the first fix, at 1 of 38 connects. Six attempts now, bounded by CONNECT_TOTAL_BUDGET_MS rather than by counting, because the two failures cost very different amounts of time. A refusal answers in 0.35 s; a device that is switched off gives no callback at all and burns the full CONNECT_TIMEOUT_MS. Counting alone would have left the cheap case barely faster and turned the expensive one into a minute in front of a progress dialog. With the clock bound a burst of refusals gets all six attempts in about four seconds, and a board that is simply off still reports in twenty-five. Two green passes followed, 35 connects with no failure, two of them recovering on the third attempt - each one a single bad draw from failing under the old ceiling, and one of them the connection engine rather than the transfer, which is the first time that retry has been seen to save anything. Honest limit: the flake itself did not reproduce here - the pass before this change was green too, and the per-attempt 133 rate visibly varies with how long a phone has been running. The case for the number rests on the measured cost of an attempt and on the observed depth of the retries, not on a before-and-after rate measured in one afternoon. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent ee1819b commit 607fcfd

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

app/src/main/java/de/rwth_aachen/phyphox/Bluetooth/Bluetooth.kt

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import android.os.Build
1515
import android.os.Handler
1616
import android.os.HandlerThread
1717
import android.os.Looper
18+
import android.os.SystemClock
1819
import android.util.Log
1920
import android.view.LayoutInflater
2021
import android.widget.TextView
@@ -329,6 +330,7 @@ open class Bluetooth(
329330
queue = BleCommandQueue(gattIo, bleScope) { onLinkDead() }
330331

331332
var result = false
333+
val connectDeadline = SystemClock.elapsedRealtime() + CONNECT_TOTAL_BUDGET_MS
332334
for (attempt in 1..CONNECT_ATTEMPTS) {
333335
val connected = CompletableDeferred<Boolean>()
334336
connectionEvent = connected
@@ -351,8 +353,10 @@ open class Bluetooth(
351353
Log.w(TAG, "connect attempt $attempt of $CONNECT_ATTEMPTS failed (status $lastConnectionStatus)")
352354
btGatt?.close()
353355
btGatt = null
354-
if (attempt < CONNECT_ATTEMPTS)
355-
runBlocking { delay(CONNECT_RETRY_DELAY_MS) }
356+
if (attempt >= CONNECT_ATTEMPTS ||
357+
SystemClock.elapsedRealtime() + CONNECT_RETRY_DELAY_MS >= connectDeadline)
358+
break
359+
runBlocking { delay(CONNECT_RETRY_DELAY_MS) }
356360
}
357361
if (!result) {
358362
throw BluetoothException(context.resources.getString(R.string.bt_exception_connection), this)
@@ -991,11 +995,30 @@ open class Bluetooth(
991995
* also covers the board that has not finished releasing the previous connection yet:
992996
* the experiment connects immediately after the transfer let go of the same device,
993997
* and a peripheral that serves one central at a time needs that moment.
998+
*
999+
* Three was not enough. A refused attempt comes back in about 0.35 s, so the whole
1000+
* budget is spent in under three seconds, and the bench kept hitting the end of it:
1001+
* two connects in 34 needed all three attempts on 2026-08-28, which puts the next
1002+
* one along - the connect that would need a fourth - at about one in forty. That is
1003+
* the transfer flake the suite was still seeing. Each additional attempt costs under
1004+
* a second and only when the previous one failed, so the budget is set by
1005+
* CONNECT_TOTAL_BUDGET_MS rather than by counting.
9941006
*/
995-
const val CONNECT_ATTEMPTS = 3
1007+
const val CONNECT_ATTEMPTS = 6
9961008

9971009
/** pause before another connection attempt, to let the stack and the device settle */
9981010
const val CONNECT_RETRY_DELAY_MS = 500L
1011+
1012+
/**
1013+
* ...but stop retrying once this much time has gone into it, however many attempts
1014+
* are left. The two failures cost very different amounts of time: a refused
1015+
* connection answers in about 0.35 s, while a device that is simply switched off
1016+
* gives no callback at all and burns the full CONNECT_TIMEOUT_MS. Counting attempts
1017+
* alone would make the cheap case barely slower and the expensive one a minute of
1018+
* staring at a progress dialog, so the retrying is bounded by the clock and the
1019+
* attempt count is only the ceiling.
1020+
*/
1021+
const val CONNECT_TOTAL_BUDGET_MS = 25000L
9991022
const val RSSI_INTERVAL_MS = 1000L
10001023
const val TOAST_THROTTLE_MS = 5000L
10011024
const val RECONNECT_INITIAL_BACKOFF_MS = 1000L

app/src/main/java/de/rwth_aachen/phyphox/Bluetooth/BluetoothExperimentLoader.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import android.bluetooth.BluetoothProfile
1010
import android.content.Context
1111
import android.net.Uri
1212
import android.os.Build
13+
import android.os.SystemClock
1314
import android.util.Log
1415
import de.rwth_aachen.phyphox.R
1516
import de.rwth_aachen.phyphox.helper.Helper
@@ -168,6 +169,7 @@ class BluetoothExperimentLoader(private val ctx: Context, private val callback:
168169
*/
169170
private suspend fun connect(device: BluetoothDevice) {
170171
connecting = true
172+
val deadline = SystemClock.elapsedRealtime() + Bluetooth.CONNECT_TOTAL_BUDGET_MS
171173
try {
172174
for (attempt in 1..Bluetooth.CONNECT_ATTEMPTS) {
173175
val connected = CompletableDeferred<Boolean>()
@@ -187,8 +189,11 @@ class BluetoothExperimentLoader(private val ctx: Context, private val callback:
187189
+ " (status $lastConnectionStatus)")
188190
gatt?.close()
189191
gatt = null
190-
if (attempt < Bluetooth.CONNECT_ATTEMPTS)
191-
delay(Bluetooth.CONNECT_RETRY_DELAY_MS)
192+
//Bounded by the clock as well as the count: see CONNECT_TOTAL_BUDGET_MS.
193+
if (attempt >= Bluetooth.CONNECT_ATTEMPTS ||
194+
SystemClock.elapsedRealtime() + Bluetooth.CONNECT_RETRY_DELAY_MS >= deadline)
195+
break
196+
delay(Bluetooth.CONNECT_RETRY_DELAY_MS)
192197
}
193198
} finally {
194199
connecting = false

0 commit comments

Comments
 (0)