Document JNI log encoding and failure containment contracts

This commit is contained in:
evgeny committed 2026-10-28 12:28:28 +01:00
1 parent c137ad89d1
commit e32e4be28b
2 files changed
+24 -1

No files matched your search

+19
View File
@@ -204,6 +204,23 @@ LogManager хранит последние 100000 строк в памяти п
video-фильтр через JNI. JNI callback получает уровни bridge 0=TRACE..4=ERROR,
а не числовые DEBUG_LEVEL_*; неизвестный уровень фиксируется предупреждением.
Строки логов передаются через `onNativeLog(int, byte[], byte[])` как обычный UTF-8:
это сохраняет кириллицу/emoji без ограничений Modified UTF-8 `NewStringUTF`.
Повреждённые UTF-8-байты Kotlin отображает как U+FFFD. На каждый вызов JNI берёт
свой local ref callback под mutex; замена/очистка global ref не инвалидирует
уже начатую доставку. Java-код вызывается после освобождения mutex. Указатель
C log callback читается/меняется атомарно; отключение не ждёт начатых вызовов.
init включает пересылку, Activity подписывается на экране логов и отключает её
при выходе; stop снимает C callback, destroy дополнительно освобождает global ref.
Ошибки JNI-доставки и повторный вход в callback того же потока фиксируются
напрямую в logcat, минуя debug hook, чтобы исключить рекурсию. Проверяются
attach, ссылки, method lookup, выделение/копирование массивов и Java callback.
Все свои local refs освобождаются; detach выполняется только после своего attach.
Исключение от собственной операции/callback описывается и снимается; исключение,
уже существовавшее при входе в logger, сохраняется, доставка этой строки пропускается.
Неудачная доставка не повторяется. Native logcat/файл/UDP работают независимо.
Экран логов показывает последние 10000 строк истории, обновляя снимок не чаще
кадра. StateFlow передаёт объединяемую ревизию, строки читаются из общей истории:
задержка UI и открытие экрана после последнего сообщения не теряют строки
@@ -223,6 +240,8 @@ subscribe/quit управляют клиентом, ряд команд даёт
Для Linux сетевых сценариев используются основной `src/utun`,
`[chatserver] headless_control_bind=127.0.0.1:9999` и `tools/chatcli`.
Для APK: `cd tools/chatgui-android && ./gradlew assembleDebug`.
На Linux `:app:testDebugUnitTest` также запускает 25 fault-сценариев настоящего
JNI logger через `:app:testJniLog`; окружение и границы модели: `tests/jni_log/README.md`.
Проверки native bridge/standby доступны в `tests/Makefile.am`;
проверка независимости media workers на устройстве описана в
`../tests/stream_worker_smoke/README.md` и не проверяет сетевую доставку/UI.
@@ -8,6 +8,9 @@
* reply_to в send/voice/photo/video для канала — обязательный указатель на 32 байта (нули = без ответа).
* request_id коррелирует канальную публикацию с CHAT_EVT_MSG_SUBMITTED; постановка в очередь не означает доставку.
* Аргументы строк/PCM заимствованы на вызов, асинхронные команды копируют их; сроки жизни файлов описаны ниже.
* JNI-логи передают обычный UTF-8 как byte[] в LogManager.onNativeLog(int, byte[], byte[]), а не через NewStringUTF.
* Каждый вызов удерживает свой local ref callback; замена/очистка global ref защищена mutex, пересылка C callback — atomic.
* Ошибки доставки/рекурсия идут прямо в logcat без debug hook. Свои Java-исключения снимаются, чужое pending exception сохраняется.
*/
#ifndef ANDROID_JNI_BRIDGE_H
#define ANDROID_JNI_BRIDGE_H
@@ -22,7 +25,8 @@ extern "C" {
/* ── Callback types (C → Kotlin) ── */
/* Native-поток; строки заимствованы на вызов. level: TRACE=0, DEBUG=1, INFO=2, WARN=3, ERROR=4. */
/* Вызывающий native-поток; category/message — NUL-строки UTF-8, заимствованные на вызов.
* level: TRACE=0, DEBUG=1, INFO=2, WARN=3, ERROR=4. Пересылка в JNI синхронна; отключение не ждёт уже начатый callback. */
typedef void (*utun_log_fn)(int level, const char* category, const char* message);
/* Отдельный C JSON-callback, вызываемый utun_bridge_event; это не бинарный CHAT_EVT_* callback JNI.