refactor: adding reconnecting logic and visuals
This commit is contained in:
parent
573f0930df
commit
a90bd89c9a
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_CONNECTED
|
|||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_INCOMING
|
||||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_OUTGOING
|
||||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_PRE_INIT
|
||||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_RECONNECTING
|
||||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_RINGING
|
||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.EARPIECE
|
||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
||||
|
@ -223,6 +224,8 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {
|
|||
state !in listOf(CALL_CONNECTED, CALL_RINGING, CALL_PRE_INIT) || wantsToAnswer
|
||||
incomingControlGroup.isVisible =
|
||||
state in listOf(CALL_RINGING, CALL_PRE_INIT) && !wantsToAnswer
|
||||
reconnectingText.isVisible = state == CALL_RECONNECTING
|
||||
endCallButton.isVisible = endCallButton.isVisible || state == CALL_RECONNECTING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.webrtc.SessionDescription
|
|||
import java.util.UUID
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import org.thoughtcrime.securesms.webrtc.data.State as CallState
|
||||
|
@ -101,7 +102,8 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
|
||||
const val INVALID_NOTIFICATION_ID = -1
|
||||
private const val TIMEOUT_SECONDS = 90L
|
||||
private const val MAX_TIMEOUTS = 3
|
||||
private const val RECONNECT_SECONDS = 5L
|
||||
private const val MAX_RECONNECTS = 5
|
||||
|
||||
fun cameraEnabled(context: Context, enabled: Boolean) = Intent(context, WebRtcCallService::class.java)
|
||||
.setAction(ACTION_SET_MUTE_VIDEO)
|
||||
|
@ -188,6 +190,9 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
private var wantsToAnswer = false
|
||||
private var currentTimeouts = 0
|
||||
private var isNetworkAvailable = true
|
||||
private var scheduledTimeout: ScheduledFuture<*>? = null
|
||||
private var scheduledReconnectTimeout: ScheduledFuture<*>? = null
|
||||
private var scheduledReconnect: ScheduledFuture<*>? = null
|
||||
|
||||
private val lockManager by lazy { LockManager(this) }
|
||||
private val serviceExecutor = Executors.newSingleThreadExecutor()
|
||||
|
@ -407,7 +412,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
callManager.startOutgoingRinger(OutgoingRinger.Type.RINGING)
|
||||
setCallInProgressNotification(TYPE_OUTGOING_RINGING, callManager.recipient)
|
||||
callManager.insertCallMessage(recipient.address.serialize(), CallMessageType.CALL_OUTGOING)
|
||||
timeoutExecutor.schedule(TimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
scheduledTimeout = timeoutExecutor.schedule(TimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
callManager.setAudioEnabled(true)
|
||||
|
||||
val expectedState = callManager.currentConnectionState
|
||||
|
@ -463,7 +468,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
callManager.silenceIncomingRinger()
|
||||
callManager.postViewModelState(CallViewModel.State.CALL_INCOMING)
|
||||
|
||||
timeoutExecutor.schedule(TimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
scheduledTimeout = timeoutExecutor.schedule(TimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
|
||||
callManager.initializeAudioForCall()
|
||||
callManager.initializeVideo(this)
|
||||
|
@ -598,8 +603,13 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
val callId = callManager.callId ?: return
|
||||
val numTimeouts = ++currentTimeouts
|
||||
|
||||
if (callId == getCallId(intent) && isNetworkAvailable && numTimeouts <= 5) {
|
||||
if (callId == getCallId(intent) && isNetworkAvailable && numTimeouts <= MAX_RECONNECTS) {
|
||||
Log.d("Loki", "Trying to re-connect")
|
||||
callManager.networkReestablished()
|
||||
scheduledTimeout = timeoutExecutor.schedule(TimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
} else {
|
||||
Log.d("Loki", "Network isn't available, timeouts == $numTimeouts out of $MAX_RECONNECTS")
|
||||
scheduledReconnect = timeoutExecutor.schedule(CheckReconnectedRunnable(callId, this), RECONNECT_SECONDS, TimeUnit.SECONDS)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,17 +793,22 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
|||
|
||||
override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState?) {
|
||||
if (newState == CONNECTED) {
|
||||
scheduledTimeout?.cancel(false)
|
||||
scheduledReconnect?.cancel(false)
|
||||
scheduledReconnectTimeout?.cancel(false)
|
||||
scheduledTimeout = null
|
||||
scheduledReconnect = null
|
||||
scheduledReconnectTimeout = null
|
||||
val intent = Intent(this, WebRtcCallService::class.java)
|
||||
.setAction(ACTION_ICE_CONNECTED)
|
||||
startService(intent)
|
||||
} else if (newState == FAILED) {
|
||||
val intent = hangupIntent(this)
|
||||
startService(intent)
|
||||
} else if (newState == DISCONNECTED) {
|
||||
} else if (newState in arrayOf(FAILED, DISCONNECTED) && scheduledReconnectTimeout == null) {
|
||||
callManager.callId?.let { callId ->
|
||||
callManager.postViewModelState(CallViewModel.State.CALL_RECONNECTING)
|
||||
timeoutExecutor.schedule(CheckReconnectedRunnable(callId, this), 5, TimeUnit.SECONDS)
|
||||
timeoutExecutor.schedule(ReconnectTimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
callManager.postConnectionEvent(Event.IceDisconnect) {
|
||||
callManager.postViewModelState(CallViewModel.State.CALL_RECONNECTING)
|
||||
scheduledReconnect = timeoutExecutor.schedule(CheckReconnectedRunnable(callId, this), RECONNECT_SECONDS, TimeUnit.SECONDS)
|
||||
scheduledReconnectTimeout = timeoutExecutor.schedule(ReconnectTimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
}
|
||||
} ?: run {
|
||||
val intent = hangupIntent(this)
|
||||
startService(intent)
|
||||
|
|
|
@ -675,17 +675,15 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
|
|||
val callId = callId ?: return
|
||||
val recipient = recipient ?: return
|
||||
|
||||
if (isReestablishing) return
|
||||
isReestablishing = true
|
||||
Log.d("Loki", "start re-establish")
|
||||
postConnectionEvent(Event.NetworkReconnect) {
|
||||
Log.d("Loki", "start re-establish")
|
||||
|
||||
val offer = connection.createOffer(MediaConstraints().apply {
|
||||
mandatory.add(MediaConstraints.KeyValuePair("IceRestart", "true"))
|
||||
})
|
||||
connection.setLocalDescription(offer)
|
||||
val offer = connection.createOffer(MediaConstraints().apply {
|
||||
mandatory.add(MediaConstraints.KeyValuePair("IceRestart", "true"))
|
||||
})
|
||||
connection.setLocalDescription(offer)
|
||||
|
||||
MessageSender.sendNonDurably(CallMessage.offer(offer.description, callId), recipient.address).success {
|
||||
isReestablishing = false
|
||||
MessageSender.sendNonDurably(CallMessage.offer(offer.description, callId), recipient.address)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.thoughtcrime.securesms.webrtc.video
|
||||
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.thoughtcrime.securesms.webrtc.data.quadrantRotation
|
||||
import org.webrtc.VideoFrame
|
||||
import org.webrtc.VideoSink
|
||||
|
@ -19,7 +18,6 @@ class RemoteRotationVideoProxySink: VideoSink {
|
|||
val modifiedRotation = thisFrame.rotation - quadrantRotation
|
||||
|
||||
val newFrame = VideoFrame(thisFrame.buffer, modifiedRotation, thisFrame.timestampNs)
|
||||
Log.d("Loki", "sending frame: w=${newFrame.buffer.width}, h=${newFrame.buffer.height}, rw=${newFrame.rotatedWidth}, rh=${newFrame.rotatedHeight}, rot=${newFrame.rotation}")
|
||||
thisSink.onFrame(newFrame)
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,16 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/remote_recipient"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/remote_loading_view"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:text="@string/WebRtcCallActivity_Reconnecting"
|
||||
android:id="@+id/reconnecting_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sessionCallText"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -903,5 +903,6 @@
|
|||
<string name="CallNotificationBuilder_first_call_title">Call Missed</string>
|
||||
<string name="CallNotificationBuilder_first_call_message">You missed a call because you need to enable the \'Voice and video calls\' permission in the Privacy Settings.</string>
|
||||
<string name="WebRtcCallActivity_Session_Call">Session Call</string>
|
||||
<string name="WebRtcCallActivity_Reconnecting">Reconnecting…</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue