From 7a86bf788c56c4f202b67a130b58fa4e82aaa025 Mon Sep 17 00:00:00 2001 From: isaacakakpo1 Date: Fri, 15 Nov 2024 12:17:33 +0100 Subject: [PATCH 1/4] - Remove Unwanted IPS from SDP Outbound Inbound Attach --- .../main/java/com/telnyx/webrtc/sdk/Call.kt | 1 + .../com/telnyx/webrtc/sdk/TelnyxClient.kt | 37 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt index f5a8d342..1514d21a 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt @@ -81,6 +81,7 @@ data class Call( init { callStateLiveData.postValue(CallState.CONNECTING) + // Ensure that loudSpeakerLiveData is correct based on possible options provided from client. loudSpeakerLiveData.postValue(audioManager.isSpeakerphoneOn) } diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt index a3b9ee06..1f6b1258 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt @@ -184,13 +184,13 @@ class TelnyxClient( // reset audio mode to communication speakerState?.let { setSpeakerMode(it) } - callStateLiveData.postValue(CallState.ACTIVE) + callStateLiveData.value = CallState.ACTIVE client.callOngoing() - } } this.addToCalls(acceptCall) + Timber.d("Event-Check Active ${ calls[callId]?.getCallState()?.value}") return acceptCall } @@ -214,6 +214,7 @@ class TelnyxClient( val inviteCallId: UUID = UUID.randomUUID() callId = inviteCallId + val call = this // Create new peer peerConnection = Peer( @@ -221,7 +222,11 @@ class TelnyxClient( object : PeerConnectionObserver() { override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) - peerConnection?.addIceCandidate(p0) + Timber.d("Event-IceCandidate Generated") + if (call.getCallState().value != CallState.ACTIVE){ + peerConnection?.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } } ) @@ -311,7 +316,7 @@ class TelnyxClient( * @param call, and instance of [Call] */ internal fun addToCalls(call: Call) { - calls.getOrPut(call.callId) { call } + calls[call.callId] = call } /** @@ -1274,6 +1279,7 @@ class TelnyxClient( peerConnection?.onRemoteSessionReceived(sdp) callStateLiveData.postValue(CallState.ACTIVE) + callStateLiveData.value = CallState.ACTIVE val answerResponse = AnswerResponse( UUID.fromString(callId), @@ -1309,6 +1315,7 @@ class TelnyxClient( ) ) callStateLiveData.postValue(CallState.ACTIVE) + callStateLiveData.value = CallState.ACTIVE } else -> { @@ -1320,6 +1327,7 @@ class TelnyxClient( client.callOngoing() client.stopMediaPlayer() } + addToCalls(answeredCall!!) } @@ -1405,6 +1413,7 @@ class TelnyxClient( // Set global callID callId = offerCallId + val call = this //retrieve custom headers val customHeaders = @@ -1414,8 +1423,12 @@ class TelnyxClient( object : PeerConnectionObserver() { override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) - peerConnection?.addIceCandidate(p0) - Timber.d("On IceCandidate Added") + Timber.d("Event-IceCandidate Generated") + Timber.d("Event-IceCandidate ${calls[callId]?.getCallState()?.value}") + if (calls[callId]?.getCallState()?.value != CallState.ACTIVE){ + peerConnection?.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } override fun onRenegotiationNeeded() { @@ -1540,8 +1553,6 @@ class TelnyxClient( } override fun onAttachReceived(jsonObject: JsonObject) { - /* val params = jsonObject.getAsJsonObject("params") - val callId = UUID.fromString(params.get("callID").asString)*/ val attachCall = call!!.copy( context = context, @@ -1572,14 +1583,16 @@ class TelnyxClient( // Set global callID callId = offerCallId - peerConnection = Peer( context, client, providedTurn, providedStun, offerCallId.toString(), object : PeerConnectionObserver() { override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) - peerConnection?.addIceCandidate(p0) - Timber.d("On IceCandidate Added") + Timber.d("Event-IceCandidate Generated") + if (calls[callId]?.getCallState()?.value != CallState.ACTIVE){ + peerConnection?.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } override fun onRenegotiationNeeded() { @@ -1608,7 +1621,7 @@ class TelnyxClient( Call.ICE_CANDIDATE_DELAY ) } - + attachCall.callStateLiveData.value = CallState.ACTIVE calls[attachCall.callId] = attachCall } From e06c3d5c9fd9fa94eae2fd1abf7575d7267db728 Mon Sep 17 00:00:00 2001 From: isaacakakpo1 Date: Fri, 15 Nov 2024 13:01:49 +0100 Subject: [PATCH 2/4] - Fix Answer Test --- .../src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt index 1f6b1258..e6609c11 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt @@ -1327,7 +1327,9 @@ class TelnyxClient( client.callOngoing() client.stopMediaPlayer() } - addToCalls(answeredCall!!) + answeredCall?.let { + addToCalls(it) + } } From 011da73bf3797bcb1b3fc3c4975e3428b04a1f20 Mon Sep 17 00:00:00 2001 From: isaacakakpo1 Date: Sun, 17 Nov 2024 21:23:54 +0100 Subject: [PATCH 3/4] - Deprecated `callStateLiveData` and introduced callStateFlow as a Flow variable. --- .../main/java/com/telnyx/webrtc/sdk/Call.kt | 25 ++++---- .../com/telnyx/webrtc/sdk/TelnyxClient.kt | 60 ++++++++++--------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt index 1514d21a..07f81666 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt @@ -10,25 +10,17 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.google.gson.Gson import com.google.gson.JsonArray -import com.google.gson.JsonObject import com.google.gson.JsonSyntaxException import com.telnyx.webrtc.sdk.model.CallState -import com.telnyx.webrtc.sdk.model.CauseCode import com.telnyx.webrtc.sdk.model.SocketMethod import com.telnyx.webrtc.sdk.peer.Peer -import com.telnyx.webrtc.sdk.peer.PeerConnectionObserver import com.telnyx.webrtc.sdk.socket.TxSocket -import com.telnyx.webrtc.sdk.socket.TxSocketListener -import com.telnyx.webrtc.sdk.telnyx_rtc.BuildConfig -import com.telnyx.webrtc.sdk.utilities.encodeBase64 import com.telnyx.webrtc.sdk.verto.receive.* import com.telnyx.webrtc.sdk.verto.send.* -import org.jetbrains.annotations.TestOnly -import org.webrtc.IceCandidate -import org.webrtc.SessionDescription +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import timber.log.Timber import java.util.* -import kotlin.concurrent.timerTask /** * Class that represents a Call and handles all call related actions, including answering and ending a call. @@ -67,7 +59,12 @@ data class Call( internal var telnyxSessionId: UUID? = null internal var telnyxLegId: UUID? = null - internal val callStateLiveData = MutableLiveData(CallState.NEW) + + private val callStateLiveData = MutableLiveData(CallState.NEW) + + private val _callStateFlow = MutableStateFlow(CallState.NEW) + + val callStateFlow: StateFlow = _callStateFlow // Ongoing call options // Mute toggle live data @@ -92,6 +89,11 @@ data class Call( peerConnection?.startTimer() } + internal fun updateCallState(value: CallState) { + callStateLiveData.postValue(value) + _callStateFlow.value = value + } + fun stopDebug() { Timber.d("Peer connection debug stopped") peerConnection?.stopTimer() @@ -286,6 +288,7 @@ data class Call( * @see [CallState] * @return [LiveData] */ + @Deprecated("Use `getCallState` instead", ReplaceWith("callStateFlow")) fun getCallState(): LiveData = callStateLiveData /** diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt index e6609c11..c7d4efac 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/TelnyxClient.kt @@ -107,7 +107,7 @@ class TelnyxClient( val call: Call? by lazy { if (calls.isNotEmpty()) { val allCalls = calls.values - val activeCall = allCalls.firstOrNull { it.getCallState().value == CallState.ACTIVE } + val activeCall = allCalls.firstOrNull { it.callStateFlow.value == CallState.ACTIVE } activeCall ?: allCalls.first() // return the first } else { buildCall() @@ -165,7 +165,7 @@ class TelnyxClient( val sessionDescriptionString = peerConnection?.getLocalDescription()?.description if (sessionDescriptionString == null) { - callStateLiveData.postValue(CallState.ERROR) + updateCallState(CallState.ERROR) } else { val answerBodyMessage = SendingMessageBody( uuid, SocketMethod.ANSWER.methodName, @@ -179,18 +179,21 @@ class TelnyxClient( ) ) ) + updateCallState(CallState.ACTIVE) socket.send(answerBodyMessage) client.stopMediaPlayer() // reset audio mode to communication - speakerState?.let { setSpeakerMode(it) } + speakerState.let { setSpeakerMode(it) } - callStateLiveData.postValue(CallState.ACTIVE) - callStateLiveData.value = CallState.ACTIVE + // callStateLiveData.value = CallState.ACTIVE client.callOngoing() } } + this.addToCalls(acceptCall) - Timber.d("Event-Check Active ${ calls[callId]?.getCallState()?.value}") + Timber.d("Event-Check Active ${calls[callId]?.callStateFlow?.value}") + Timber.d("Event-Check2 Active ${ calls[callId]?.getCallState()?.value}") + return acceptCall } @@ -223,9 +226,11 @@ class TelnyxClient( override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) Timber.d("Event-IceCandidate Generated") - if (call.getCallState().value != CallState.ACTIVE){ - peerConnection?.addIceCandidate(p0) - Timber.d("Event-IceCandidate Added") + if (call.callStateFlow.value != CallState.ACTIVE) { + peerConnection?.let { connection -> + connection.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } } } @@ -298,7 +303,7 @@ class TelnyxClient( ) ) ) - callStateLiveData.postValue(CallState.DONE) + updateCallState(CallState.DONE) client.removeFromCalls(callId) client.callNotOngoing() socket.send(byeMessageBody) @@ -1252,7 +1257,7 @@ class TelnyxClient( ) ) - callStateLiveData.postValue(CallState.DONE) + updateCallState(CallState.DONE) client.removeFromCalls(callId) client.callNotOngoing() resetCallOptions() @@ -1278,8 +1283,7 @@ class TelnyxClient( peerConnection?.onRemoteSessionReceived(sdp) - callStateLiveData.postValue(CallState.ACTIVE) - callStateLiveData.value = CallState.ACTIVE + updateCallState(CallState.ACTIVE) val answerResponse = AnswerResponse( UUID.fromString(callId), @@ -1298,7 +1302,7 @@ class TelnyxClient( } earlySDP -> { - callStateLiveData.postValue(CallState.CONNECTING) + updateCallState(CallState.CONNECTING) val stringSdp = peerConnection?.getLocalDescription()?.description val answerResponse = AnswerResponse( UUID.fromString(callId), @@ -1314,13 +1318,12 @@ class TelnyxClient( ) ) ) - callStateLiveData.postValue(CallState.ACTIVE) - callStateLiveData.value = CallState.ACTIVE + updateCallState(CallState.ACTIVE) } else -> { // There was no SDP in the response, there was an error. - callStateLiveData.postValue(CallState.DONE) + updateCallState(CallState.DONE) client.removeFromCalls(UUID.fromString(callId)) } } @@ -1369,7 +1372,7 @@ class TelnyxClient( } else { // There was no SDP in the response, there was an error. - callStateLiveData.postValue(CallState.DONE) + updateCallState(CallState.DONE) client.removeFromCalls(UUID.fromString(callId)) } @@ -1426,10 +1429,11 @@ class TelnyxClient( override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) Timber.d("Event-IceCandidate Generated") - Timber.d("Event-IceCandidate ${calls[callId]?.getCallState()?.value}") - if (calls[callId]?.getCallState()?.value != CallState.ACTIVE){ - peerConnection?.addIceCandidate(p0) - Timber.d("Event-IceCandidate Added") + if (calls[callId]?.getCallState()?.value != CallState.ACTIVE) { + peerConnection?.let { connection -> + connection.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } } @@ -1529,7 +1533,7 @@ class TelnyxClient( override fun onIceCandidateReceived(iceCandidate: IceCandidate) { call?.apply { - callStateLiveData.postValue(CallState.CONNECTING) + updateCallState(CallState.CONNECTING) } } @@ -1591,9 +1595,11 @@ class TelnyxClient( override fun onIceCandidate(p0: IceCandidate?) { super.onIceCandidate(p0) Timber.d("Event-IceCandidate Generated") - if (calls[callId]?.getCallState()?.value != CallState.ACTIVE){ - peerConnection?.addIceCandidate(p0) - Timber.d("Event-IceCandidate Added") + if (calls[callId]?.callStateFlow?.value != CallState.ACTIVE) { + peerConnection?.let { connection -> + connection.addIceCandidate(p0) + Timber.d("Event-IceCandidate Added") + } } } @@ -1623,7 +1629,7 @@ class TelnyxClient( Call.ICE_CANDIDATE_DELAY ) } - attachCall.callStateLiveData.value = CallState.ACTIVE + attachCall.updateCallState(CallState.ACTIVE) calls[attachCall.callId] = attachCall } From 116eed0c9b591ada3a892224b13fe55dd07422e7 Mon Sep 17 00:00:00 2001 From: isaacakakpo1 Date: Mon, 18 Nov 2024 09:36:01 +0100 Subject: [PATCH 4/4] - Set Initial callState for Call --- telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt index 07f81666..71e5993b 100644 --- a/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt +++ b/telnyx_rtc/src/main/java/com/telnyx/webrtc/sdk/Call.kt @@ -77,7 +77,7 @@ data class Call( private val loudSpeakerLiveData = MutableLiveData(false) init { - callStateLiveData.postValue(CallState.CONNECTING) + updateCallState(CallState.CONNECTING) // Ensure that loudSpeakerLiveData is correct based on possible options provided from client. loudSpeakerLiveData.postValue(audioManager.isSpeakerphoneOn)