From 6326f4a5b98e6f659b129e7ecec53c5dbdc47d31 Mon Sep 17 00:00:00 2001 From: darken Date: Tue, 3 Mar 2026 21:42:39 +0100 Subject: [PATCH] fix(monitor): Gate BLE scanning on permission state and stop retrying on SecurityException PodMonitor's retryWhen always returned true, causing infinite 3-second retry loops when BLUETOOTH_SCAN permission was missing (e.g. on emulators). Now the scan flow checks missingPermissions before starting, and SecurityException aborts retries since it requires user action. --- .../eu/darken/capod/monitor/core/PodMonitor.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/eu/darken/capod/monitor/core/PodMonitor.kt b/app/src/main/java/eu/darken/capod/monitor/core/PodMonitor.kt index 92e664a5..2e2d1378 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/PodMonitor.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/PodMonitor.kt @@ -59,8 +59,7 @@ class PodMonitor @Inject constructor( bluetoothManager.isBluetoothEnabled ) { missingPermissions, isBluetoothEnabled -> log(TAG) { "devices: missingPermissions=$missingPermissions, isBluetoothEnabled=$isBluetoothEnabled" } - // We just want to retrigger if permissions change. - isBluetoothEnabled + missingPermissions.isEmpty() && isBluetoothEnabled } .flatMapLatest { isReady -> if (!isReady) { @@ -76,9 +75,14 @@ class PodMonitor @Inject constructor( flowOf(sortPodsToInterest(devices)) } .retryWhen { cause, attempt -> - log(TAG, WARN) { "PodMonitor failed (attempt=$attempt), will retry: ${cause.asLog()}" } - delay(3000) - true + if (cause is SecurityException) { + log(TAG, WARN) { "PodMonitor failed due to missing permission, not retrying: ${cause.asLog()}" } + false + } else { + log(TAG, WARN) { "PodMonitor failed (attempt=$attempt), will retry: ${cause.asLog()}" } + delay(3000) + true + } } .onStart { emit(emptyList()) } .replayingShare(appScope)