diff --git a/app-glasses-vm/src/main/kotlin/pw/binom/rayneovm/glasses/VmService.kt b/app-glasses-vm/src/main/kotlin/pw/binom/rayneovm/glasses/VmService.kt index 70237a9..da34fd2 100644 --- a/app-glasses-vm/src/main/kotlin/pw/binom/rayneovm/glasses/VmService.kt +++ b/app-glasses-vm/src/main/kotlin/pw/binom/rayneovm/glasses/VmService.kt @@ -174,6 +174,16 @@ class VmService : LifecycleService() { */ private val currentConn = java.util.concurrent.atomic.AtomicReference(null) + /** + * Все живые WS-сессии. Связь с телефоном считаем живой, пока жива ХОТЬ ОДНА. + * + * Нельзя вешать `NoConnection` на закрытие конкретной сессии: помимо телефона сюда + * прилетают короткоживущие сессии (mDNS-фоллбек телефона делает полный WS-апгрейд + * для проверки кандидата и сразу рвёт соединение). Из-за этого экран очков залипал + * в «Нет связи», хотя телефон был подключён и команды доходили. + */ + private val liveConns = java.util.concurrent.ConcurrentHashMap.newKeySet() + /** Ресивер `ACTION_SCREEN_ON/OFF`: сообщаем телефону реальное состояние экрана очков. */ private var screenReceiver: BroadcastReceiver? = null @@ -186,7 +196,8 @@ class VmService : LifecycleService() { handleIncoming(connId, json) }, onConnected = { connId -> - Log.i(TAG, "Phone connected: $connId") + liveConns.add(connId) + Log.i(TAG, "Phone connected: $connId (всего сессий: ${liveConns.size})") currentConn.set(connId) // Переподключение: снять залипшее «Нет связи с телефоном». controller.onPhoneConnected() @@ -196,11 +207,15 @@ class VmService : LifecycleService() { lifecycleScope.launch { sendScreenState(connId) } }, onDisconnected = { connId -> - Log.i(TAG, "Phone disconnected: $connId") - if (currentConn.compareAndSet(connId, null)) { + liveConns.remove(connId) + Log.i(TAG, "Session closed: $connId (осталось: ${liveConns.size})") + // «Push»-сессию переводим на любую живую, если ушла именно она. + if (currentConn.get() == connId) { + currentConn.set(liveConns.firstOrNull()) + } + // Экран гасим ТОЛЬКО когда не осталось ни одной сессии. + if (liveConns.isEmpty()) { controller.setState(GlassesScreenState.NoConnection) - } else { - Log.i(TAG, "Ignoring disconnect of stale session $connId") } }, )