mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
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_INCOMING
|
||||||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_OUTGOING
|
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_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.CallViewModel.State.CALL_RINGING
|
||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.EARPIECE
|
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.EARPIECE
|
||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
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
|
state !in listOf(CALL_CONNECTED, CALL_RINGING, CALL_PRE_INIT) || wantsToAnswer
|
||||||
incomingControlGroup.isVisible =
|
incomingControlGroup.isVisible =
|
||||||
state in listOf(CALL_RINGING, CALL_PRE_INIT) && !wantsToAnswer
|
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.UUID
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.concurrent.ScheduledFuture
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.thoughtcrime.securesms.webrtc.data.State as CallState
|
import org.thoughtcrime.securesms.webrtc.data.State as CallState
|
||||||
|
@ -101,7 +102,8 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
||||||
|
|
||||||
const val INVALID_NOTIFICATION_ID = -1
|
const val INVALID_NOTIFICATION_ID = -1
|
||||||
private const val TIMEOUT_SECONDS = 90L
|
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)
|
fun cameraEnabled(context: Context, enabled: Boolean) = Intent(context, WebRtcCallService::class.java)
|
||||||
.setAction(ACTION_SET_MUTE_VIDEO)
|
.setAction(ACTION_SET_MUTE_VIDEO)
|
||||||
|
@ -188,6 +190,9 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
||||||
private var wantsToAnswer = false
|
private var wantsToAnswer = false
|
||||||
private var currentTimeouts = 0
|
private var currentTimeouts = 0
|
||||||
private var isNetworkAvailable = true
|
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 lockManager by lazy { LockManager(this) }
|
||||||
private val serviceExecutor = Executors.newSingleThreadExecutor()
|
private val serviceExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
@ -407,7 +412,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
||||||
callManager.startOutgoingRinger(OutgoingRinger.Type.RINGING)
|
callManager.startOutgoingRinger(OutgoingRinger.Type.RINGING)
|
||||||
setCallInProgressNotification(TYPE_OUTGOING_RINGING, callManager.recipient)
|
setCallInProgressNotification(TYPE_OUTGOING_RINGING, callManager.recipient)
|
||||||
callManager.insertCallMessage(recipient.address.serialize(), CallMessageType.CALL_OUTGOING)
|
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)
|
callManager.setAudioEnabled(true)
|
||||||
|
|
||||||
val expectedState = callManager.currentConnectionState
|
val expectedState = callManager.currentConnectionState
|
||||||
|
@ -463,7 +468,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
||||||
callManager.silenceIncomingRinger()
|
callManager.silenceIncomingRinger()
|
||||||
callManager.postViewModelState(CallViewModel.State.CALL_INCOMING)
|
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.initializeAudioForCall()
|
||||||
callManager.initializeVideo(this)
|
callManager.initializeVideo(this)
|
||||||
|
@ -598,8 +603,13 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
|
||||||
val callId = callManager.callId ?: return
|
val callId = callManager.callId ?: return
|
||||||
val numTimeouts = ++currentTimeouts
|
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()
|
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?) {
|
override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState?) {
|
||||||
if (newState == CONNECTED) {
|
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)
|
val intent = Intent(this, WebRtcCallService::class.java)
|
||||||
.setAction(ACTION_ICE_CONNECTED)
|
.setAction(ACTION_ICE_CONNECTED)
|
||||||
startService(intent)
|
startService(intent)
|
||||||
} else if (newState == FAILED) {
|
} else if (newState in arrayOf(FAILED, DISCONNECTED) && scheduledReconnectTimeout == null) {
|
||||||
val intent = hangupIntent(this)
|
|
||||||
startService(intent)
|
|
||||||
} else if (newState == DISCONNECTED) {
|
|
||||||
callManager.callId?.let { callId ->
|
callManager.callId?.let { callId ->
|
||||||
callManager.postViewModelState(CallViewModel.State.CALL_RECONNECTING)
|
callManager.postConnectionEvent(Event.IceDisconnect) {
|
||||||
timeoutExecutor.schedule(CheckReconnectedRunnable(callId, this), 5, TimeUnit.SECONDS)
|
callManager.postViewModelState(CallViewModel.State.CALL_RECONNECTING)
|
||||||
timeoutExecutor.schedule(ReconnectTimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
scheduledReconnect = timeoutExecutor.schedule(CheckReconnectedRunnable(callId, this), RECONNECT_SECONDS, TimeUnit.SECONDS)
|
||||||
|
scheduledReconnectTimeout = timeoutExecutor.schedule(ReconnectTimeoutRunnable(callId, this), TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||||
|
}
|
||||||
} ?: run {
|
} ?: run {
|
||||||
val intent = hangupIntent(this)
|
val intent = hangupIntent(this)
|
||||||
startService(intent)
|
startService(intent)
|
||||||
|
|
|
@ -675,17 +675,15 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
|
||||||
val callId = callId ?: return
|
val callId = callId ?: return
|
||||||
val recipient = recipient ?: return
|
val recipient = recipient ?: return
|
||||||
|
|
||||||
if (isReestablishing) return
|
postConnectionEvent(Event.NetworkReconnect) {
|
||||||
isReestablishing = true
|
Log.d("Loki", "start re-establish")
|
||||||
Log.d("Loki", "start re-establish")
|
|
||||||
|
|
||||||
val offer = connection.createOffer(MediaConstraints().apply {
|
val offer = connection.createOffer(MediaConstraints().apply {
|
||||||
mandatory.add(MediaConstraints.KeyValuePair("IceRestart", "true"))
|
mandatory.add(MediaConstraints.KeyValuePair("IceRestart", "true"))
|
||||||
})
|
})
|
||||||
connection.setLocalDescription(offer)
|
connection.setLocalDescription(offer)
|
||||||
|
|
||||||
MessageSender.sendNonDurably(CallMessage.offer(offer.description, callId), recipient.address).success {
|
MessageSender.sendNonDurably(CallMessage.offer(offer.description, callId), recipient.address)
|
||||||
isReestablishing = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.thoughtcrime.securesms.webrtc.video
|
package org.thoughtcrime.securesms.webrtc.video
|
||||||
|
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.webrtc.data.quadrantRotation
|
import org.thoughtcrime.securesms.webrtc.data.quadrantRotation
|
||||||
import org.webrtc.VideoFrame
|
import org.webrtc.VideoFrame
|
||||||
import org.webrtc.VideoSink
|
import org.webrtc.VideoSink
|
||||||
|
@ -19,7 +18,6 @@ class RemoteRotationVideoProxySink: VideoSink {
|
||||||
val modifiedRotation = thisFrame.rotation - quadrantRotation
|
val modifiedRotation = thisFrame.rotation - quadrantRotation
|
||||||
|
|
||||||
val newFrame = VideoFrame(thisFrame.buffer, modifiedRotation, thisFrame.timestampNs)
|
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)
|
thisSink.onFrame(newFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,16 @@
|
||||||
app:layout_constraintTop_toBottomOf="@id/remote_recipient"
|
app:layout_constraintTop_toBottomOf="@id/remote_recipient"
|
||||||
tools:visibility="visible" />
|
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
|
<TextView
|
||||||
android:id="@+id/sessionCallText"
|
android:id="@+id/sessionCallText"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -903,5 +903,6 @@
|
||||||
<string name="CallNotificationBuilder_first_call_title">Call Missed</string>
|
<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="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_Session_Call">Session Call</string>
|
||||||
|
<string name="WebRtcCallActivity_Reconnecting">Reconnecting…</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue