Add some more UI around call failures

Stephen Paul Weber created

Change summary

src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java                | 11 
src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java |  9 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java      | 10 
src/main/res/layout/activity_rtp_session.xml                                   | 10 
4 files changed, 40 insertions(+)

Detailed changes

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<Media> 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) {

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);
     }

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);
         }
     }

src/main/res/layout/activity_rtp_session.xml 🔗

@@ -68,6 +68,16 @@
                 android:visibility="visible"
                 tools:text="jcapulet@example.com" />
 
+            <TextView
+                android:id="@+id/extra_state"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="16dp"
+                android:layout_marginTop="8dp"
+                android:layout_marginRight="16dp"
+                android:textAppearance="?textAppearanceBodyMedium"
+                android:visibility="gone" />
+
             <View
                 android:layout_width="match_parent"
                 android:layout_height="32dp" />