fix: watchdog GATT close + 로그를 watchdog Thread에서 직접 실행

기존: handler.post 안에서 로그+disconnect → handler 블로킹 시 둘 다 안 됨
변경:
- debugLogger.error() → watchdog Thread에서 직접 호출 (CopyOnWriteArrayList 스레드 안전)
- gatt.disconnect()/close() → watchdog Thread에서 직접 호출 (GATT는 any thread OK)
- UI 업데이트 + reconnect만 handler.post로 전달

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 14:39:54 +09:00
parent 7ab3d878e7
commit c99eb068a5
@@ -371,10 +371,27 @@ class BleManager private constructor(private val context: Context) {
val silenceMs = System.currentTimeMillis() - lastRxTimestamp
if (silenceMs > watchdogTimeoutMs) {
// 직접 로그 기록 (handler 블로킹 무관)
debugLogger.error("WATCHDOG_TIMEOUT silence=${silenceMs}ms — forcing reconnect")
// GATT close는 어느 스레드에서든 호출 가능
watchdogRunning = false
try {
bluetoothGatt?.disconnect()
bluetoothGatt?.close()
} catch (_: Exception) {}
bluetoothGatt = null
txCharacteristic = null
rxCharacteristic = null
// UI 업데이트 + reconnect는 메인 스레드
handler.post {
logw { "Watchdog: no RX for ${silenceMs}ms — forcing disconnect + reconnect" }
debugLogger.error("WATCHDOG_TIMEOUT silence=${silenceMs}ms — forcing reconnect")
forceDisconnectAndReconnect()
stopBatteryPolling()
isConnected.value = false
isServiceReady.value = false
connectedDeviceName.value = ""
onUnexpectedDisconnect?.invoke()
scheduleAutoReconnect()
}
break
}