Files
utun2/tools/chatgui-android/doc/IMPL_PLAN.md
T

108 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# chatgui-android — этапы реализации и проверки
Документ описывает текущие точки входа и критерии проверки. Наличие реализации
не означает, что соответствующий сценарий выполнен на устройстве.
Архитектура и контракты: [ARCHITECTURE.md](ARCHITECTURE.md), заголовки `libutun_lite/` и `jni_bridge/`.
## 1. Сборка общего ядра
Реализовано: `utun_sources.cmake` использует общие `lib/` и `src/`, включая ETCP,
STCP, NCD и группы/BGP. Android не требует отдельной реализации chat_sync и
не исключает UDP/маршрутизатор. Источники голосового стека собираются отдельно
через `src/call/voice_sources.cmake`. Итог NDK — `libutun.so`.
Проверять состав и исключения по `app/src/main/cpp/CMakeLists.txt`, а версии SDK,
NDK, JVM и ABI — по `app/build.gradle.kts`. Не создавать второй lite-instance или
локальную схему БД ради Android. UTUN-сервис управляется `[gui] utun_enabled`.
Сборка из корня репозитория:
```bash
./build.sh --no-gui -j4
cd tools/chatgui-android
./gradlew assembleDebug
```
Критерий: обе сборки завершились успешно; APK появился в
`app/build/outputs/apk/debug/app-debug.apk`. Сборка APK не подтверждает работу на устройстве.
## 2. Lifecycle и JNI
Реализовано: NativeLib.init сохраняет callbacks, start передаёт INI и создаёт worker,
SERVICE_STARTED подтверждает готовность. Restart пересоздаёт ядро; updateSockets
согласует `[server:*]` без рестарта. Код stop ждёт worker до двух секунд, после
таймаута возврат не подтверждает освобождение ресурсов.
Проверять последовательно: init → установка event callback → start → SERVICE_STARTED →
рабочая команда → результат → остановка media workers → stop. Отдельно проверить
restart и смену интерфейсов через updateSockets. Возврат nativeRestart/nativeUpdateSockets
не является подтверждением применения конфигурации.
Критерий: события приходят в Kotlin, нет обращений по старым inst/ua, stop/restart
не пересекаются с внешними I/O workers. Проверять категории sys/socket/connection/chat
и сообщения lifecycle; при таймауте остановки сначала установить причину по логам.
## 3. Каналы, приглашения и личные беседы
Реализовано: Compose UI, ChatRepository с JSON/JNI и ViewModel/StateFlow;
SQLite принадлежит общему ядру. Room/отдельный Kotlin SQL-reader не используются.
InviteLink.kt вызывает общий native-кодек для предпросмотра и передаёт исходную
ссылку JOIN-port с request ID. connectNode остался логирующей заглушкой.
Проверять на двух узлах: создать канал → запросить invite → дождаться готовой ссылки →
JOIN → CONNECT_RESULT → синхронизация участников и сообщений. Для сетевого baseline
на Linux использовать основной `src/utun` и `tools/chatcli`, описание команд —
`../../chatcli_commands.txt`. Android-каталог `headless/` не запускает ядро и не подходит
для такого end-to-end сценария.
Критерий: request результата совпадает, сообщение появляется на другом узле,
готовность JOIN и READY групповой сессии различается в диагностике.
Для DM отдельно проверить поколения беседы: поздняя история/подготовленное вложение
после удаления беседы не должны появиться в новом поколении.
## 4. Вложения, звонки, рация и трансляции
Реализовано: file/photo для каналов, общий attachment_send для voice/video каналов и DM,
DM files, native голосовой стек звонка/рации, MediaCodec и независимые stream workers.
При проверке файлов учитывать владение: file/photo caller сохраняет до завершения
копирования; принятые video/DM-file запросы забирают временный cache-файл и удаляют
также при ошибке/отмене. Отказ постановки оставляет источник caller. Успешный return
не подтверждает публикацию или доставку; смотреть события подготовки и отправки.
Для звонка/рации проверять capture/playback, PTT/auto, смену маршрута и остановку I/O
до освобождения DSP. Для stream — KEY/revision, отдельные viewers, demand/pull,
GAP/CLOSED, завершение аудио/видео и wake/освобождение signal.
Существующие native-проверки из корня репозитория:
```bash
make -C tests test_android_bridge test_android_replies test_android_udp_log test_android_stream test_standby test_standby_transport test_group_connect_standby
(cd tests && ./test_android_bridge && ./test_android_replies && ./test_android_udp_log && ./test_android_stream && ./test_standby && ./test_standby_transport && ./test_group_connect_standby)
```
test_android_bridge проверяет владение config callbacks, повторный init/destroy и
покадровое/батчевое декодирование настоящих Opus-файлов (пять частот, mono/stereo, EOF).
Эти тесты проверяют отдельные native-контракты, не весь Android lifecycle.
Устройство с собранным APK: сценарий задержки video worker на 500мс, EOF/reset и
независимых аппаратных аудиочасов — [stream_worker_smoke](../tests/stream_worker_smoke/README.md).
Критерии и зависимости заданы там; сетевой путь этим тестом не проверяется.
## 5. Фоновый сервис и диагностика устройства
Реализовано: HeadlessService как foreground service, сеть через NetworkChangeMonitor,
уведомления activity через NetworkActivityMonitor и native standby ACTIVE/SLEEP.
Отдельный Linux headless control socket не встроен в этот Android-сервис.
Общий headless API ядра требует явного `[chatserver] headless_control_bind`; параметр
controlPort у NativeLib.init listener не открывает.
Проверять: foreground → background → SLEEP → timer/ранний wake → foreground;
затем смену сети и restart. Уровни категорий задать до повторного прогона, чтобы
логи показывали причину перехода и согласованный набор сокетов.
UDP-лог настроить через `[log_udp]`; приёмник запускать по инструкции `tools/logreceiver/`.
После shutdown/restart не должно оставаться таймера старого uasync.
Критерий: ядро продолжает обслуживать события, standby-ожидания корректно будятся
или отменяются, UI получает новое состояние; при ошибке причина видна в логах.
Проверки на физическом устройстве выполняются отдельно от сборки и Linux-тестов.