Added setting to show more call stats

This commit is contained in:
Sylvain Berfini 2026-01-21 11:36:40 +01:00
parent 8cb883a978
commit 14f8273588
8 changed files with 187 additions and 1 deletions

View file

@ -197,6 +197,13 @@ class CorePreferences
config.setBool("app", "auto_answer_video_send_receive", value)
}
@get:AnyThread @set:WorkerThread
var showAdvancedCallStats: Boolean
get() = config.getBool("ui", "show_advanced_call_stats", false)
set(value) {
config.setBool("ui", "show_advanced_call_stats", value)
}
// Conversation related
@get:AnyThread @set:WorkerThread

View file

@ -21,8 +21,10 @@ package org.linphone.ui.call.model
import androidx.annotation.WorkerThread
import androidx.lifecycle.MutableLiveData
import org.linphone.LinphoneApplication.Companion.corePreferences
import kotlin.math.roundToInt
import org.linphone.R
import org.linphone.core.Address
import org.linphone.core.Call
import org.linphone.core.CallStats
import org.linphone.core.MediaDirection
@ -36,6 +38,8 @@ class CallStatsModel
val audioBandwidth = MutableLiveData<String>()
val lossRate = MutableLiveData<String>()
val jitterBuffer = MutableLiveData<String>()
val audioIce = MutableLiveData<String>()
val audioIpFamily = MutableLiveData<String>()
val isVideoEnabled = MutableLiveData<Boolean>()
val videoCodec = MutableLiveData<String>()
@ -43,12 +47,20 @@ class CallStatsModel
val videoLossRate = MutableLiveData<String>()
val videoResolution = MutableLiveData<String>()
val videoFps = MutableLiveData<String>()
val videoIce = MutableLiveData<String>()
val videoIpFamily = MutableLiveData<String>()
val fecEnabled = MutableLiveData<Boolean>()
val lostPackets = MutableLiveData<String>()
val repairedPackets = MutableLiveData<String>()
val fecBandwidth = MutableLiveData<String>()
val showAdvancedStats = MutableLiveData<Boolean>()
init {
showAdvancedStats.postValue(corePreferences.showAdvancedCallStats)
}
@WorkerThread
fun update(call: Call, stats: CallStats?) {
stats ?: return
@ -96,6 +108,18 @@ class CallStatsModel
"$jitterBufferSize ms"
)
jitterBuffer.postValue(jitterBufferLabel)
val iceLabel = AppUtils.getFormattedString(
R.string.call_stats_ice_label,
stats.iceState
)
audioIce.postValue(iceLabel)
val ipLabel = AppUtils.getFormattedString(
R.string.call_stats_ip_family_label,
if (stats.ipFamilyOfRemote == Address.Family.Inet6) "IPv6" else "IPv4"
)
audioIpFamily.postValue(ipLabel)
}
StreamType.Video -> {
val payloadType = call.currentParams.usedVideoPayloadType
@ -138,6 +162,18 @@ class CallStatsModel
)
videoFps.postValue(fpsLabel)
val iceLabel = AppUtils.getFormattedString(
R.string.call_stats_ice_label,
stats.iceState
)
videoIce.postValue(iceLabel)
val ipLabel = AppUtils.getFormattedString(
R.string.call_stats_ip_family_label,
if (stats.ipFamilyOfRemote == Address.Family.Inet6) "IPv6" else "IPv4"
)
videoIpFamily.postValue(ipLabel)
if (isFecEnabled) {
val lostPacketsValue = stats.fecCumulativeLostPacketsNumber
val lostPacketsLabel = AppUtils.getFormattedString(

View file

@ -249,6 +249,7 @@ class SettingsViewModel
val logsSharingServerUrl = MutableLiveData<String>()
val createEndToEndEncryptedConferences = MutableLiveData<Boolean>()
val enableVuMeters = MutableLiveData<Boolean>()
val enableAdvancedCallStats = MutableLiveData<Boolean>()
val pushCompatibleDomainsList = MutableLiveData<String>()
private val coreListener = object : CoreListenerStub() {
@ -382,6 +383,7 @@ class SettingsViewModel
logsSharingServerUrl.postValue(core.logCollectionUploadServerUrl)
createEndToEndEncryptedConferences.postValue(corePreferences.createEndToEndEncryptedMeetingsAndGroupCalls)
enableVuMeters.postValue(corePreferences.showMicrophoneAndSpeakerVuMeters)
enableAdvancedCallStats.postValue(corePreferences.showAdvancedCallStats)
val domainsListBuilder = StringBuilder()
val domainsArray = corePreferences.pushNotificationCompatibleDomains
@ -1197,6 +1199,16 @@ class SettingsViewModel
}
}
@UiThread
fun toggleEnableAdvancedCallStats() {
val newValue = enableAdvancedCallStats.value == false
coreContext.postOnCoreThread { core ->
corePreferences.showAdvancedCallStats = newValue
enableAdvancedCallStats.postValue(newValue)
}
}
@UiThread
fun updatePushCompatibleDomainsList() {
coreContext.postOnCoreThread { core ->

View file

@ -81,6 +81,30 @@
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.audioIce, default=@string/call_stats_ice_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.audioIpFamily, default=@string/call_stats_ip_family_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
@ -154,6 +178,30 @@
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.videoIce, default=@string/call_stats_ice_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.videoIpFamily, default=@string/call_stats_ip_family_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"

View file

@ -79,6 +79,30 @@
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.audioIce, default=@string/call_stats_ice_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.audioIpFamily, default=@string/call_stats_ip_family_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
@ -151,6 +175,30 @@
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.videoIce, default=@string/call_stats_ice_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{model.videoIpFamily, default=@string/call_stats_ip_family_label}"
android:textColor="@color/bc_white"
android:visibility="@{model.showAdvancedStats ? View.VISIBLE : View.GONE, default=gone}"
android:maxLines="1"
android:ellipsize="end"
android:gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:layout_width="match_parent"

View file

@ -236,6 +236,35 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/e2e_encrypted_conferences_switch" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:onClick="@{() -> viewModel.toggleEnableAdvancedCallStats()}"
android:id="@+id/enable_advanced_call_stats_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:text="@string/settings_developer_enable_advanced_call_stats_title"
android:maxLines="2"
android:ellipsize="end"
android:labelFor="@id/enable_advanced_call_stats_switch"
app:layout_constraintTop_toTopOf="@id/enable_advanced_call_stats_switch"
app:layout_constraintBottom_toBottomOf="@id/enable_advanced_call_stats_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/enable_advanced_call_stats_switch"/>
<com.google.android.material.materialswitch.MaterialSwitch
style="@style/material_switch_style"
android:id="@+id/enable_advanced_call_stats_switch"
android:onClick="@{() -> viewModel.toggleEnableAdvancedCallStats()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:checked="@{viewModel.enableAdvancedCallStats}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/enable_vu_meters_switch" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_padding_style"
android:id="@+id/push_compatible_domains_list_label"
@ -248,7 +277,7 @@
android:labelFor="@id/push_compatible_domains_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/enable_vu_meters_switch"/>
app:layout_constraintTop_toBottomOf="@id/enable_advanced_call_stats_switch"/>
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"

View file

@ -327,6 +327,7 @@
<string name="settings_developer_enabled_toast">Paramètres développeurs activés</string>
<string name="settings_developer_already_enabled_toast">Paramètres développeurs déjà activés</string>
<string name="settings_developer_enable_vu_meters_title">Activer l\'indicateur des volumes d\'enregistrement et de lecture</string>
<string name="settings_developer_enable_advanced_call_stats_title">Afficher plus de statistiques d\'appel</string>
<string name="settings_developer_push_compatible_domains_list_title">Liste des domaines qui supportent les notifications poussées (séparés par des virgules)</string>
<string name="settings_developer_clear_native_friends_in_database_title">Supprimer les contacts natifs importés</string>
<string name="settings_developer_clear_native_friends_in_database_subtitle">Ils seront synchronisés à nouveau au prochain démarrage de l\'application sauf si vous retirez la permission de lire les contacts</string>
@ -752,6 +753,8 @@
<string name="call_stats_bandwidth_label">Bande passante : %s</string>
<string name="call_stats_loss_rate_label">Taux de perte : %s</string>
<string name="call_stats_jitter_buffer_label">Tampon de gigue : %s</string>
<string name="call_stats_ice_label">ICE : %s</string>
<string name="call_stats_ip_family_label">Famille IP : %s</string>
<string name="call_stats_video_title">Vidéo</string>
<string name="call_stats_resolution_label">Définition : %s</string>
<string name="call_stats_fps_label">FPS : %s</string>

View file

@ -369,6 +369,7 @@
<string name="settings_developer_enabled_toast">Developer settings enabled</string>
<string name="settings_developer_already_enabled_toast">Developer settings already enabled</string>
<string name="settings_developer_enable_vu_meters_title">Enable record/playback volume vu meters while in call</string>
<string name="settings_developer_enable_advanced_call_stats_title">Show advanced call statistics</string>
<string name="settings_developer_push_compatible_domains_list_title">List of push notifications compatible domains (comma separated)</string>
<string name="settings_developer_clear_native_friends_in_database_title">Clear imported contacts from native address book</string>
<string name="settings_developer_clear_native_friends_in_database_subtitle">They will be imported again the next time the app starts unless you remove the contacts permission</string>
@ -795,6 +796,8 @@
<string name="call_stats_bandwidth_label">Bandwidth: %s</string>
<string name="call_stats_loss_rate_label">Loss rate: %s</string>
<string name="call_stats_jitter_buffer_label">Jitter buffer: %s</string>
<string name="call_stats_ice_label">ICE: %s</string>
<string name="call_stats_ip_family_label">IP Family: %s</string>
<string name="call_stats_video_title">Video</string>
<string name="call_stats_resolution_label">Resolution: %s</string>
<string name="call_stats_fps_label">FPS: %s</string>