@@ -939,14 +939,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
this.binding.duration.setVisibility(View.GONE);
return;
}
- final long rtpConnectionStarted = connection.getRtpConnectionStarted();
- 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 {
+ if (connection.zeroDuration()) {
this.binding.duration.setVisibility(View.GONE);
+ } else {
+ this.binding.duration.setText(TimeFrameUtils.formatElapsedTime(connection.getCallDuration(), false));
+ this.binding.duration.setVisibility(View.VISIBLE);
}
}
@@ -71,10 +71,14 @@ public class TimeFrameUtils {
public static String formatTimePassed(final long since, final long to, final boolean withMilliseconds) {
final long passed = (since < 0) ? 0 : (to - since);
- final int hours = (int) (passed / 3600000);
- final int minutes = (int) (passed / 60000) % 60;
- final int seconds = (int) (passed / 1000) % 60;
- final int milliseconds = (int) (passed / 100) % 10;
+ return formatElapsedTime(passed, withMilliseconds);
+ }
+
+ 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) {
return String.format(Locale.ENGLISH, "%d:%02d:%02d", hours, minutes, seconds);
} else if (withMilliseconds) {
@@ -1,6 +1,5 @@
package eu.siacs.conversations.xmpp.jingle;
-import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -8,6 +7,7 @@ import androidx.annotation.Nullable;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Collections2;
@@ -29,8 +29,10 @@ import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -147,8 +149,8 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
private Set<Media> proposedMedia;
private RtpContentMap initiatorRtpContentMap;
private RtpContentMap responderRtpContentMap;
- private long rtpConnectionStarted = 0; //time of 'connected'
- private long rtpConnectionEnded = 0;
+ private final Stopwatch sessionDuration = Stopwatch.createUnstarted();
+ private final Queue<PeerConnection.PeerConnectionState> stateHistory = new LinkedList<>();
private ScheduledFuture<?> ringingTimeoutFuture;
JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
@@ -1056,7 +1058,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
return RtpEndUserState.RETRACTED;
}
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:
return RtpEndUserState.APPLICATION_ERROR;
case TERMINATED_SECURITY_ERROR:
@@ -1084,7 +1086,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
case CLOSED:
return RtpEndUserState.ENDING_CALL;
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
public void onConnectionChange(final PeerConnection.PeerConnectionState oldState, final PeerConnection.PeerConnectionState newState) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": PeerConnectionState changed: " + oldState + "->" + newState);
- final boolean neverConnected = this.rtpConnectionStarted == 0;
- if (newState == PeerConnection.PeerConnectionState.CONNECTED && this.rtpConnectionStarted == 0) {
- this.rtpConnectionStarted = SystemClock.elapsedRealtime();
- }
- if (newState == PeerConnection.PeerConnectionState.CLOSED && this.rtpConnectionEnded == 0) {
- this.rtpConnectionEnded = SystemClock.elapsedRealtime();
+ this.stateHistory.add(newState);
+ if (newState == PeerConnection.PeerConnectionState.CONNECTED) {
+ this.sessionDuration.start();
+ } else if (this.sessionDuration.isRunning()) {
+ this.sessionDuration.stop();
}
- 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()) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state);
return;
@@ -1375,12 +1380,12 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
}
- public long getRtpConnectionStarted() {
- return this.rtpConnectionStarted;
+ public boolean zeroDuration() {
+ return this.sessionDuration.elapsed(TimeUnit.NANOSECONDS) <= 0;
}
- public long getRtpConnectionEnded() {
- return this.rtpConnectionEnded;
+ public long getCallDuration() {
+ return this.sessionDuration.elapsed(TimeUnit.MILLISECONDS);
}
public AppRTCAudioManager getAudioManager() {
@@ -1507,8 +1512,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
private void writeLogMessage(final State state) {
- final long started = this.rtpConnectionStarted;
- long duration = started <= 0 ? 0 : SystemClock.elapsedRealtime() - started;
+ final long duration = getCallDuration();
if (state == State.TERMINATED_SUCCESS || (state == State.TERMINATED_CONNECTIVITY_ERROR && duration > 0)) {
writeLogMessageSuccess(duration);
} else {