diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.java b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.java index 5317d029f3..2b7d3f0466 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.java @@ -151,6 +151,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer, public static final String ACTION_MESSAGE_SENT_ERROR = "MESSAGE_SENT_ERROR"; public static final String ACTION_CAMERA_SWITCH_COMPLETED = "CAMERA_FLIP_COMPLETE"; public static final String ACTION_TURN_SERVER_UPDATE = "TURN_SERVER_UPDATE"; + public static final String ACTION_SETUP_FAILURE = "SETUP_FAILURE"; public static final int BUSY_TONE_LENGTH = 2000; @@ -333,17 +334,28 @@ public class WebRtcCallService extends Service implements CallManager.Observer, } public void retrieveTurnServers(@NonNull RemotePeer remotePeer) { - retrieveTurnServers().addListener(new SuccessOnlyListener(remotePeer.getState(), remotePeer.getCallId()) { + retrieveTurnServers().addListener(new FutureTaskListener() { @Override - public void onSuccessContinue(@Nullable TurnServerInfoParcel turnServerInfoParcel) { + public void onSuccess(@Nullable TurnServerInfoParcel result) { boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this); Intent intent = new Intent(WebRtcCallService.this, WebRtcCallService.class); intent.setAction(ACTION_TURN_SERVER_UPDATE) .putExtra(EXTRA_IS_ALWAYS_TURN, isAlwaysTurn) - .putExtra(EXTRA_TURN_SERVER_INFO, turnServerInfoParcel); + .putExtra(EXTRA_TURN_SERVER_INFO, result); - WebRtcCallService.this.startService(intent); + startService(intent); + } + + @Override + public void onFailure(@NonNull ExecutionException exception) { + Log.w(TAG, "Unable to retrieve turn servers: ", exception); + + Intent intent = new Intent(WebRtcCallService.this, WebRtcCallService.class); + intent.setAction(ACTION_SETUP_FAILURE) + .putExtra(EXTRA_CALL_ID, remotePeer.getCallId().longValue()); + + startService(intent); } }); } @@ -543,18 +555,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer, public abstract void onFailureContinue(@Nullable Throwable throwable); } - private abstract class SuccessOnlyListener extends StateAwareListener { - SuccessOnlyListener(@NonNull CallState expectedState, @NonNull CallId expectedCallId) { - super(expectedState, expectedCallId); - } - - @Override - public void onFailureContinue(@Nullable Throwable throwable) { - Log.w(TAG, throwable); - throw new AssertionError(throwable); - } - } - private class SendCallMessageListener extends StateAwareListener { SendCallMessageListener(@NonNull RemotePeer expectedRemotePeer) { super(expectedRemotePeer.getState(), expectedRemotePeer.getCallId()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java index 57f945ff35..dd1eb1a5f7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.signal.ringrtc.CallException; +import org.signal.ringrtc.CallId; import org.signal.ringrtc.IceCandidate; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.events.CallParticipant; @@ -246,4 +247,38 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor { return terminate(currentState, remotePeer); } + + @Override + protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) { + Log.i(tag, "handleSetupFailure(): call_id: " + callId); + + RemotePeer activePeer = currentState.getCallInfoState().getActivePeer(); + + if (activePeer != null && activePeer.getCallId().equals(callId)) { + try { + if (activePeer.getState() == CallState.DIALING || activePeer.getState() == CallState.REMOTE_RINGING) { + webRtcInteractor.getCallManager().hangup(); + } else { + webRtcInteractor.getCallManager().drop(callId); + } + } catch (CallException e) { + return callFailure(currentState, "Unable to drop call due to setup failure", e); + } + + currentState = currentState.builder() + .changeCallInfoState() + .callState(WebRtcViewModel.State.NETWORK_FAILURE) + .build(); + + webRtcInteractor.sendMessage(currentState); + + if (activePeer.getState() == CallState.ANSWERING || activePeer.getState() == CallState.LOCAL_RINGING) { + webRtcInteractor.insertMissedCall(activePeer, true, activePeer.getCallStartTimestamp()); + } + + return terminate(currentState, activePeer); + } + + return currentState; + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java index 5884e77c2d..615b0ff05f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java @@ -7,6 +7,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.signal.ringrtc.CallException; +import org.signal.ringrtc.CallId; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.events.CallParticipant; @@ -204,6 +205,11 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor { return activeCallDelegate.handleEnded(currentState, action, remotePeer); } + @Override + protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) { + return activeCallDelegate.handleSetupFailure(currentState, callId); + } + @Override protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { return activeCallDelegate.handleCallConcluded(currentState, remotePeer); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java index b052ac31ae..3f88d75a4c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java @@ -7,6 +7,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.signal.ringrtc.CallException; +import org.signal.ringrtc.CallId; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.CallParticipant; @@ -204,6 +205,11 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor { return activeCallDelegate.handleEnded(currentState, action, remotePeer); } + @Override + protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) { + return activeCallDelegate.handleSetupFailure(currentState, callId); + } + @Override protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { return activeCallDelegate.handleCallConcluded(currentState, remotePeer); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java index f2e6ac85a1..00df72693e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java @@ -80,6 +80,7 @@ import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_B import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_HANGUP; import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_ICE_CANDIDATES; import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_OFFER; +import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SETUP_FAILURE; import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_AUDIO_BLUETOOTH; import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_AUDIO_SPEAKER; import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_ENABLE_VIDEO; @@ -204,6 +205,9 @@ public abstract class WebRtcActionProcessor { case ACTION_ENDED_INTERNAL_FAILURE: case ACTION_ENDED_SIGNALING_FAILURE: case ACTION_ENDED_CONNECTION_FAILURE: return handleEnded(currentState, action, getRemotePeerFromMap(intent, currentState)); + + // Local Call Failure Actions + case ACTION_SETUP_FAILURE: return handleSetupFailure(currentState, getCallId(intent)); } return currentState; @@ -574,6 +578,15 @@ public abstract class WebRtcActionProcessor { //endregion + //region Local call failure + + protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) { + Log.i(tag, "handleSetupFailure not processed"); + return currentState; + } + + //endregion + //region Global call operations public @NonNull WebRtcServiceState callFailure(@NonNull WebRtcServiceState currentState,