diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CoreActivity.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CoreActivity.kt index 22ee140b..3c9a5704 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CoreActivity.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CoreActivity.kt @@ -4,14 +4,14 @@ import android.os.Looper /** Main thread: объединяет запросы активности экрана, звонка, приглашения рации и передачи файлов через OR. * Пока ядро не готово, сохраняет намерение владельцев. Новый SERVICE_STARTED повторно отправляет актуальный запрос. - * Кэш хранит последний нормально завершившийся JNI-вызов, а не подтверждённый режим: ядро применяет команду + * Кэш хранит последнюю принятую native-очередью команду, а не подтверждённый режим: ядро применяет команду * асинхронно и учитывает собственные удержания активности, например трансляции. */ object CoreActivity { private var visible = false private var call = false private var radioCall = false private var transfer = false - private var requested: Boolean? = null + private var queued: Boolean? = null fun visible(value: Boolean) { checkMain(); visible = value; sync() } fun call(value: Boolean) { checkMain(); call = value; sync() } fun radioCall(value: Boolean) { checkMain(); radioCall = value; sync() } @@ -20,7 +20,7 @@ object CoreActivity { /** Сбрасывает только кэш команды: владельцы сохраняются, следующий sync отправит актуальное намерение. */ fun reset() { checkMain() - requested = null + queued = null LogManager.addLog("DEBUG", "Activity", "activity request cache reset") } @@ -35,26 +35,30 @@ object CoreActivity { /** Новый экземпляр ядра ещё не получал состояние владельцев активности. */ fun onCoreStarted() { checkMain() - requested = null + queued = null LogManager.addLog("INFO", "Activity", "core started; resynchronizing activity") sync() } fun sync() { checkMain() if (!NativeLib.isReady()) { - requested = null + queued = null LogManager.addLog("DEBUG", "Activity", "activity request deferred: core is not ready") return } val active = visible || call || radioCall || transfer - if (requested == active) return - try { + if (queued == active) return + val accepted = try { NativeLib.setActive(active) } catch (e: Exception) { LogManager.addLog("ERROR", "Activity", "activity request failed active=$active: ${e.javaClass.simpleName}: ${e.message}") throw e } - requested = active - LogManager.addLog("INFO", "Activity", "core activity requested=$active visible=$visible call=$call radioCall=$radioCall transfer=$transfer") + if (!accepted) { + LogManager.addLog("WARN", "Activity", "activity request deferred active=$active: native queue rejected command") + return + } + queued = active + LogManager.addLog("INFO", "Activity", "core activity queued=$active visible=$visible call=$call radioCall=$radioCall transfer=$transfer") } } diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt index f1ce6ea0..daf7340a 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt @@ -95,8 +95,8 @@ object NativeLib { fun isResponsive(): Boolean = nativeIsResponsive() /* ── App foreground/background (Android lifecycle) ── */ - /** Асинхронный запрос ACTIVE/STANDBY; возврат JNI не подтверждает применение. Фактический режим учитывает stream hold ядра. */ - fun setActive(active: Boolean) { nativeSetActive(active) } + /** true — запрос ACTIVE/STANDBY поставлен живому worker; применение асинхронно и учитывает stream hold ядра. */ + fun setActive(active: Boolean): Boolean = nativeSetActive(active) /* ── External network activity (ConnectivityManager) ── */ fun notifyNetworkActive() { nativeNotifyNetworkActive() } @@ -386,7 +386,7 @@ object NativeLib { private external fun nativePing() private external fun nativeIsResponsive(): Boolean private external fun nativeIsRunning(): Boolean - private external fun nativeSetActive(active: Boolean) + private external fun nativeSetActive(active: Boolean): Boolean private external fun nativeNotifyNetworkActive() /* ── Channel members JNI ── */ diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index 53f665f1..54d8fcbc 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -2793,10 +2793,10 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeOnNetworkChanged( /* ── App foreground/background (Android lifecycle) → client_activity ── */ -JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSetActive( +JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeSetActive( JNIEnv* env, jobject thiz, jboolean active) { (void)env; (void)thiz; - utun_bridge_set_active(active ? 1 : 0); + return utun_bridge_set_active(active ? 1 : 0) == 0 ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeNotifyNetworkActive(