From c99eb068a5851fca3dd5e88196398dffbc641ef1 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Thu, 23 Apr 2026 14:39:54 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20watchdog=20GATT=20close=20+=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=A5=BC=20watchdog=20Thread=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=81=EC=A0=91=20=EC=8B=A4=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존: 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) --- .../medilightv2android/ble/BleManager.kt | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt index c799bf4..93f9f18 100644 --- a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt +++ b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt @@ -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 }