From 128af68a893fef13660fa45c3352323d2b1b3524 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 28 Oct 2026 17:11:58 +0100 Subject: [PATCH] Invalidate radio settings before reconfiguration and log failed attempts --- .../com/utun/chat/data/RadioAudioEngine.kt | 28 ++++++++++++++----- tools/chatgui-android/doc/ARCHITECTURE.md | 8 +++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt index d9291425..781fa8b5 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt @@ -250,15 +250,29 @@ class RadioAudioEngine { } } - /** Смена настроек сохраняет окно автоматики; явное включение открывает новое. */ + /** Смена настроек сохраняет окно автоматики; явное включение открывает новое. + * При отказе приём остаётся включённым, capture ждёт нового reconfigure/ACK; прежний ACK его не разрешает. */ fun reconfigure(restartAuto: Boolean = false) { val version = generation io.execute { if (!active || generation != version || audioTrack == null) return@execute - stopCapture() - loadCaptureSettings() - if (restartAuto) vadWindow.restart(SystemClock.elapsedRealtime()) - updateCapture() + var operation = "capture stop" + try { + stopCapture() + operation = "settings" + loadCaptureSettings() + if (restartAuto) vadWindow.restart(SystemClock.elapsedRealtime()) + operation = "capture update" + updateCapture() + } catch (e: Exception) { + settingsTimeout?.let { mainHandler.removeCallbacks(it) }; settingsTimeout = null + settingsReady = false; ++settingsRequest + LogManager.addLog("ERROR", "RadioAudio", "radio reconfigure failed operation=$operation group=$audioGroup " + + "generation=$version; capture disabled until retry: $e") + if (operation == "capture update") try { stopCapture() } catch (cleanup: Exception) { + LogManager.addLog("ERROR", "RadioAudio", "reconfigure rollback failed group=$audioGroup; retained for retry: $cleanup") + } + } } } @@ -310,11 +324,11 @@ class RadioAudioEngine { /* Настройки загружаются при включении/перенастройке, без DataStore в пути PTT. */ private fun loadCaptureSettings() { settingsTimeout?.let { mainHandler.removeCallbacks(it) }; settingsTimeout = null + settingsReady = false + val request = ++settingsRequest val provider = ChatApplication.instance.configProvider MediaAudioController.refresh() autoSettings = provider.getRadioAutoSettings() - settingsReady = false - val request = ++settingsRequest if (!autoSettings.valid() || !NativeLib.radioConfigure(request, autoSettings)) { LogManager.addLog("ERROR", "radio", "Cannot apply automatic transmission settings request=$request settings=$autoSettings") } else { diff --git a/tools/chatgui-android/doc/ARCHITECTURE.md b/tools/chatgui-android/doc/ARCHITECTURE.md index b3e6c591..3afe96c9 100644 --- a/tools/chatgui-android/doc/ARCHITECTURE.md +++ b/tools/chatgui-android/doc/ARCHITECTURE.md @@ -288,6 +288,11 @@ identity и исходное поколение до изменения сост Отказ таймера фоновой автоматики закрывает её окно; ручной PTT/измеритель могут сохранить захват в режиме OFF. Логи содержат группу, поколение, этап отказа и join. +Reconfigure инвалидирует прежний settings request до чтения новых настроек. +Ошибка чтения/применения/обновления capture логируется с этапом; приём остаётся +включённым, capture ждёт повторной перенастройки и нового ACK. Прежний ACK не +возобновляет захват после отказа. Частично созданный capture получает rollback. + `RadioTalkState` хранит отдельный снимок говорящих для активной группы. Включение/ смена канала создаёт новый снимок, выключение устанавливает groupId=0. Событие 43 разбирается строго как 19 little-endian байтов: group/node/stream/on; ID ненулевые, @@ -472,7 +477,8 @@ MediaAudioController с host-границами Android/JNI. Проверяет workers настоящие; звукового оборудования, DSP и сетевой передачи в модели нет. RadioAudioLifecycleTest проверяет отказы регистрации/очистки receiver и AudioTrack, зависимость release от detach lease, interruption, ошибки native/start/settings, -отложенные и повторно входящие callbacks, восстановление после звонка и отказы +отложенные и повторно входящие callbacks, восстановление после звонка, отказ +перенастройки с последующим старым ACK и отказы таймеров ACK/автоматики. Проверяется и сохранение владельцев после частичного эффекта API, и продолжение независимой очистки перед повторной попыткой. На Linux `:app:testDebugUnitTest` также запускает 25 fault-сценариев настоящего