From 4985523daf17c77ccec985fdae7385884c2b1170 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 24 Nov 2025 13:05:28 -0500 Subject: [PATCH] Add some more UI around call failures --- .../eu/siacs/conversations/ui/RtpSessionActivity.java | 11 +++++++++++ .../xmpp/jingle/AbstractJingleConnection.java | 9 +++++++++ .../xmpp/jingle/JingleRtpConnection.java | 10 ++++++++++ src/main/res/layout/activity_rtp_session.xml | 10 ++++++++++ 4 files changed, 40 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java index d97ad0168451c403840af9687a107e8e39458920..dce597f2d86db38a314a13ded1d3eacfd1fc51ee 100644 --- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java @@ -146,6 +146,7 @@ public class RtpSessionActivity extends XmppActivity }; private boolean buttonsHiddenAfterTimeout = false; private final Runnable mVisibilityToggleExecutor = this::updateButtonInVideoCallVisibility; + private String extraState = null; public static Set actionToMedia(final String action) { if (ACTION_MAKE_VIDEO_CALL.equals(action)) { @@ -940,6 +941,16 @@ public class RtpSessionActivity extends XmppActivity throw new IllegalStateException( String.format("State %s has not been handled in UI", state)); } + + final var connection = + this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null; + if (connection != null) extraState = connection.extraState(); + if (extraState != null) { + binding.extraState.setText(extraState); + binding.extraState.setVisibility(View.VISIBLE); + } else { + binding.extraState.setVisibility(View.GONE); + } } private void updateVerifiedShield(final boolean verified) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java index 9a80ecabec409f7a9ccd053eb81b5f05a2b61a3a..b9f1de14c2510f1364cfbe5843469b2f7705ab79 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java @@ -118,6 +118,7 @@ public abstract class AbstractJingleConnection { private final Jid initiator; protected State state = State.NULL; + protected String extraState = null; AbstractJingleConnection( final JingleConnectionManager jingleConnectionManager, @@ -149,6 +150,14 @@ public abstract class AbstractJingleConnection { return Arrays.asList(state).contains(this.state); } + public synchronized String extraState() { + return extraState; + } + + protected synchronized void setExtraState(final String s) { + extraState = s; + } + protected boolean transition(final State target) { return transition(target, null); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index f3d892ffd887a0fe9d00f6d3f2c3917d82188075..a9ea278278c8a45ca7ddacc52072fae04803d6c2 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -179,6 +179,7 @@ public class JingleRtpConnection extends AbstractJingleConnection if (isResponder() && isInState(State.PROPOSED, State.SESSION_INITIALIZED)) { xmppConnectionService.getNotificationService().cancelIncomingCallNotification(); } + setExtraState("rebound"); if (isInState( State.SESSION_INITIALIZED, State.SESSION_INITIALIZED_PRE_APPROVED, @@ -1219,6 +1220,7 @@ public class JingleRtpConnection extends AbstractJingleConnection String.format( "%s: received session-initiate while in state %s", id.account.getJid().asBareJid(), state)); + setExtraState("out of order"); terminateWithOutOfOrder(jinglePacket); } } @@ -1258,6 +1260,7 @@ public class JingleRtpConnection extends AbstractJingleConnection contentMap.requireContentDescriptions(); contentMap.requireDTLSFingerprint(); } catch (final RuntimeException e) { + setExtraState("bad contents"); respondOk(jinglePacket); Log.d( Config.LOGTAG, @@ -1527,6 +1530,7 @@ public class JingleRtpConnection extends AbstractJingleConnection + ": receive message error for proceed message (" + Strings.nullToEmpty(message) + ")"); + setExtraState("proceed error"); if (transition(State.TERMINATED_CONNECTIVITY_ERROR)) { webRTCWrapper.close(); Log.d( @@ -1598,6 +1602,7 @@ public class JingleRtpConnection extends AbstractJingleConnection } private void receiveRejectFromMyself(String serverMsgId, long timestamp) { + setExtraState("rejected"); if (transition(State.REJECTED)) { this.xmppConnectionService.getNotificationService().cancelIncomingCallNotification(); this.finish(); @@ -1615,6 +1620,7 @@ public class JingleRtpConnection extends AbstractJingleConnection } private void receiveRejectFromResponder() { + setExtraState("responder rejected"); if (isInState(State.PROCEED)) { Log.d( Config.LOGTAG, @@ -1854,6 +1860,7 @@ public class JingleRtpConnection extends AbstractJingleConnection try { setupWebRTC(media, iceServers, !includeCandidates); } catch (final WebRTCWrapper.InitializationException e) { + setExtraState("Unable to init WebRTC"); Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to initialize WebRTC"); webRTCWrapper.close(); sendRetract(Reason.ofThrowable(e)); @@ -1864,6 +1871,7 @@ public class JingleRtpConnection extends AbstractJingleConnection this.webRTCWrapper.setLocalDescription(includeCandidates).get(); prepareSessionInitiate(webRTCSessionDescription, includeCandidates, targetState); } catch (final Exception e) { + setExtraState("Unable to setLocalDescription"); // TODO sending the error text is worthwhile as well. Especially for FailureToSet // exceptions failureToInitiateSession(e, targetState); @@ -1931,6 +1939,7 @@ public class JingleRtpConnection extends AbstractJingleConnection @Override public void onFailure(@NonNull final Throwable throwable) { + setExtraState("Unable to outgoingContentMapFuture"); failureToInitiateSession(throwable, targetState); } }, @@ -2689,6 +2698,7 @@ public class JingleRtpConnection extends AbstractJingleConnection + " Other party already did"); return; } + setExtraState("WebRTC failed"); sendSessionTerminate(Reason.CONNECTIVITY_ERROR); } } diff --git a/src/main/res/layout/activity_rtp_session.xml b/src/main/res/layout/activity_rtp_session.xml index f59468e852a103bbdc3ce2dbf7d588d60ac19cdc..3e35a4132a21c8cd7b176f8eb5bb65bad2cd4bda 100644 --- a/src/main/res/layout/activity_rtp_session.xml +++ b/src/main/res/layout/activity_rtp_session.xml @@ -68,6 +68,16 @@ android:visibility="visible" tools:text="jcapulet@example.com" /> + +