use stopwatch to keep track of jingle rtp session duration

This commit is contained in:
Daniel Gultsch 2021-11-11 16:52:18 +01:00
parent 9843b72f6f
commit 9c3f55bef2
3 changed files with 34 additions and 29 deletions

View file

@ -939,14 +939,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
this.binding.duration.setVisibility(View.GONE); this.binding.duration.setVisibility(View.GONE);
return; return;
} }
final long rtpConnectionStarted = connection.getRtpConnectionStarted(); if (connection.zeroDuration()) {
final long rtpConnectionEnded = connection.getRtpConnectionEnded();
if (rtpConnectionStarted != 0) {
final long ended = rtpConnectionEnded == 0 ? SystemClock.elapsedRealtime() : rtpConnectionEnded;
this.binding.duration.setText(TimeFrameUtils.formatTimePassed(rtpConnectionStarted, ended, false));
this.binding.duration.setVisibility(View.VISIBLE);
} else {
this.binding.duration.setVisibility(View.GONE); this.binding.duration.setVisibility(View.GONE);
} else {
this.binding.duration.setText(TimeFrameUtils.formatElapsedTime(connection.getCallDuration(), false));
this.binding.duration.setVisibility(View.VISIBLE);
} }
} }

View file

@ -71,10 +71,14 @@ public class TimeFrameUtils {
public static String formatTimePassed(final long since, final long to, final boolean withMilliseconds) { public static String formatTimePassed(final long since, final long to, final boolean withMilliseconds) {
final long passed = (since < 0) ? 0 : (to - since); final long passed = (since < 0) ? 0 : (to - since);
final int hours = (int) (passed / 3600000); return formatElapsedTime(passed, withMilliseconds);
final int minutes = (int) (passed / 60000) % 60; }
final int seconds = (int) (passed / 1000) % 60;
final int milliseconds = (int) (passed / 100) % 10; public static String formatElapsedTime(final long elapsed, final boolean withMilliseconds) {
final int hours = (int) (elapsed / 3600000);
final int minutes = (int) (elapsed / 60000) % 60;
final int seconds = (int) (elapsed / 1000) % 60;
final int milliseconds = (int) (elapsed / 100) % 10;
if (hours > 0) { if (hours > 0) {
return String.format(Locale.ENGLISH, "%d:%02d:%02d", hours, minutes, seconds); return String.format(Locale.ENGLISH, "%d:%02d:%02d", hours, minutes, seconds);
} else if (withMilliseconds) { } else if (withMilliseconds) {

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.xmpp.jingle; package eu.siacs.conversations.xmpp.jingle;
import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -8,6 +7,7 @@ import androidx.annotation.Nullable;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
@ -29,8 +29,10 @@ import java.util.ArrayDeque;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -147,8 +149,8 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
private Set<Media> proposedMedia; private Set<Media> proposedMedia;
private RtpContentMap initiatorRtpContentMap; private RtpContentMap initiatorRtpContentMap;
private RtpContentMap responderRtpContentMap; private RtpContentMap responderRtpContentMap;
private long rtpConnectionStarted = 0; //time of 'connected' private final Stopwatch sessionDuration = Stopwatch.createUnstarted();
private long rtpConnectionEnded = 0; private final Queue<PeerConnection.PeerConnectionState> stateHistory = new LinkedList<>();
private ScheduledFuture<?> ringingTimeoutFuture; private ScheduledFuture<?> ringingTimeoutFuture;
JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) { JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
@ -1056,7 +1058,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
return RtpEndUserState.RETRACTED; return RtpEndUserState.RETRACTED;
} }
case TERMINATED_CONNECTIVITY_ERROR: case TERMINATED_CONNECTIVITY_ERROR:
return rtpConnectionStarted == 0 ? RtpEndUserState.CONNECTIVITY_ERROR : RtpEndUserState.CONNECTIVITY_LOST_ERROR; return zeroDuration() ? RtpEndUserState.CONNECTIVITY_ERROR : RtpEndUserState.CONNECTIVITY_LOST_ERROR;
case TERMINATED_APPLICATION_FAILURE: case TERMINATED_APPLICATION_FAILURE:
return RtpEndUserState.APPLICATION_ERROR; return RtpEndUserState.APPLICATION_ERROR;
case TERMINATED_SECURITY_ERROR: case TERMINATED_SECURITY_ERROR:
@ -1084,7 +1086,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
case CLOSED: case CLOSED:
return RtpEndUserState.ENDING_CALL; return RtpEndUserState.ENDING_CALL;
default: default:
return rtpConnectionStarted == 0 ? RtpEndUserState.CONNECTIVITY_ERROR : RtpEndUserState.RECONNECTING; return zeroDuration() ? RtpEndUserState.CONNECTIVITY_ERROR : RtpEndUserState.RECONNECTING;
} }
} }
@ -1338,15 +1340,18 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
@Override @Override
public void onConnectionChange(final PeerConnection.PeerConnectionState oldState, final PeerConnection.PeerConnectionState newState) { public void onConnectionChange(final PeerConnection.PeerConnectionState oldState, final PeerConnection.PeerConnectionState newState) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": PeerConnectionState changed: " + oldState + "->" + newState); Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": PeerConnectionState changed: " + oldState + "->" + newState);
final boolean neverConnected = this.rtpConnectionStarted == 0; this.stateHistory.add(newState);
if (newState == PeerConnection.PeerConnectionState.CONNECTED && this.rtpConnectionStarted == 0) { if (newState == PeerConnection.PeerConnectionState.CONNECTED) {
this.rtpConnectionStarted = SystemClock.elapsedRealtime(); this.sessionDuration.start();
} } else if (this.sessionDuration.isRunning()) {
if (newState == PeerConnection.PeerConnectionState.CLOSED && this.rtpConnectionEnded == 0) { this.sessionDuration.stop();
this.rtpConnectionEnded = SystemClock.elapsedRealtime();
} }
if (neverConnected && Arrays.asList(PeerConnection.PeerConnectionState.FAILED, PeerConnection.PeerConnectionState.DISCONNECTED).contains(newState)) { final boolean neverConnected = !this.stateHistory.contains(PeerConnection.PeerConnectionState.CONNECTED);
final boolean failedOrDisconnected = Arrays.asList(PeerConnection.PeerConnectionState.FAILED, PeerConnection.PeerConnectionState.DISCONNECTED).contains(newState);
if (neverConnected && failedOrDisconnected) {
if (isTerminated()) { if (isTerminated()) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state); Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state);
return; return;
@ -1375,12 +1380,12 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
} }
} }
public long getRtpConnectionStarted() { public boolean zeroDuration() {
return this.rtpConnectionStarted; return this.sessionDuration.elapsed(TimeUnit.NANOSECONDS) <= 0;
} }
public long getRtpConnectionEnded() { public long getCallDuration() {
return this.rtpConnectionEnded; return this.sessionDuration.elapsed(TimeUnit.MILLISECONDS);
} }
public AppRTCAudioManager getAudioManager() { public AppRTCAudioManager getAudioManager() {
@ -1507,8 +1512,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
} }
private void writeLogMessage(final State state) { private void writeLogMessage(final State state) {
final long started = this.rtpConnectionStarted; final long duration = getCallDuration();
long duration = started <= 0 ? 0 : SystemClock.elapsedRealtime() - started;
if (state == State.TERMINATED_SUCCESS || (state == State.TERMINATED_CONNECTIVITY_ERROR && duration > 0)) { if (state == State.TERMINATED_SUCCESS || (state == State.TERMINATED_CONNECTIVITY_ERROR && duration > 0)) {
writeLogMessageSuccess(duration); writeLogMessageSuccess(duration);
} else { } else {