conn_mgr: race connection probes and report call path with correct RTT

This commit is contained in:
evgeny committed 2026-10-01 00:42:47 +03:00
1 parent 1c51df039f
commit 111432aa64
26 files changed
+1112 -995

No files matched your search

@@ -21,7 +21,7 @@ object AppEventHandler : ChatEventCallback {
val events: SharedFlow<Pair<Int, ByteArray?>> = _events
override fun onEvent(type: Int, data: ByteArray?) {
if (type == 12 || type == 13 || type in 34..40 || type == 42) {
if (type == 12 || type == 13 || type in 34..40 || type == 42 || type == 44) {
mainHandler.post { CallController.onEvent(type, data) }
}
Log.d("utun-gui", "[EVENT] type=$type len=${data?.size ?: 0}")
@@ -198,7 +198,8 @@ object CallController : TelecomCallManager.Listener {
_route.value = AudioRoute.SPEAKER
_headset.value = false
_earpiece.value = true
_state.value = st.copy(phase = CallPhase.ENDED, reason = reason)
_state.value = st.copy(phase = CallPhase.ENDED, reason = reason,
connectionType = CallConnectionType.NONE, connectionNextHop = 0)
syncCoreActivity()
LogManager.addLog("INFO", "Call", "finished id=$id reason=$reason; audio/service/proximity released")
scope.launch {
@@ -253,7 +254,7 @@ object CallController : TelecomCallManager.Listener {
return
}
if (type == 13) { reset(); return }
if (type !in 34..40 && type != 42) return
if (type !in 34..40 && type != 42 && type != 44) return
if (!coreReady || !NativeLib.isReady()) {
LogManager.addLog("WARN", "Call", "ignore event=$type while core stopped/restarting")
return
@@ -285,7 +286,8 @@ object CallController : TelecomCallManager.Listener {
return
}
if (data == null || data.size < 8 || ((type == 37 || type == 38 || type == 40 || type == 42) && data.size < 9) ||
(type == 39 && data.size != 24)) { badEvent(type, data); return }
(type == 39 && data.size != 24) ||
(type == 44 && (data.size != 17 || (data[8].toInt() and 0xFF) > 3))) { badEvent(type, data); return }
val id = ByteBuffer.wrap(data, 0, 8).order(ByteOrder.LITTLE_ENDIAN).long
val st = _state.value
if (st == null || st.callId != id || !st.ongoing) {
@@ -328,6 +330,12 @@ object CallController : TelecomCallManager.Listener {
_state.value = st.copy(stats = CallStats(metric(), metric(), metric(), metric(), metric(), metric(), metric(), metric()))
}
42 -> _state.value = st.copy(bgpPath = String(data, 8, data.size - 8))
44 -> {
val connection = CallConnectionType.values()[data[8].toInt() and 0xFF]
val nextHop = ByteBuffer.wrap(data, 9, 8).order(ByteOrder.LITTLE_ENDIAN).long
_state.value = st.copy(connectionType = connection, connectionNextHop = nextHop)
LogManager.addLog("INFO", "Call", "connection id=$id type=$connection via=${nextHop.toULong().toString(16)}")
}
}
}
@@ -3,6 +3,11 @@ package com.utun.chat.data
/** Состояние единственной звонковой сессии; не зависит от Activity или ViewModel. */
enum class CallPhase { NONE, OUTGOING, RINGING, INCOMING, ACTIVE, ENDED }
/** Значения CONN_TYPE_* общего ядра. */
enum class CallConnectionType(val label: String) {
NONE("нет подключения"), DIRECT("прямое"), REVERSE("reverse"), INDIRECT("indirect")
}
data class CallStats(
val rttMs: Int, val bufferMs: Int, val tempoX100: Int, val dropped: Int,
val underruns: Int, val minMs: Int, val maxMs: Int, val reserveMs: Int
@@ -18,7 +23,9 @@ data class CallState(
val durationSeconds: Int = 0,
val bgpPath: String = "",
val stats: CallStats? = null,
val startedAtElapsedRealtime: Long = 0
val startedAtElapsedRealtime: Long = 0,
val connectionType: CallConnectionType = CallConnectionType.NONE,
val connectionNextHop: Long = 0
) {
val ongoing: Boolean get() = phase != CallPhase.NONE && phase != CallPhase.ENDED
}
@@ -169,6 +169,9 @@ fun CallScreen(
color = Color(0xFFAEBCC8),
fontSize = 16.sp
)
Spacer(Modifier.height(8.dp))
Text("Подключение: ${st?.connectionType?.label ?: "нет подключения"}",
color = Color(0xFFAEBCC8), fontSize = 13.sp)
val bgpPath = st?.bgpPath ?: ""
if (bgpPath.isNotEmpty()) {
Spacer(Modifier.height(8.dp))
@@ -50,6 +50,8 @@ fun IncomingCallDialog(
Text(name, color = Color.White, fontSize = 22.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.height(6.dp))
Text("Входящий звонок…", color = Color(0xFFAEBCC8), fontSize = 14.sp)
Spacer(Modifier.height(6.dp))
Text("Подключение: ${st.connectionType.label}", color = Color(0xFFAEBCC8), fontSize = 13.sp)
Spacer(Modifier.height(28.dp))
Row(horizontalArrangement = Arrangement.spacedBy(48.dp)) {