diff --git a/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcaster.java b/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcaster.java index 0376312970..1022d39e12 100644 --- a/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcaster.java +++ b/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcaster.java @@ -7,6 +7,8 @@ package com.nextcloud.talk.call; import com.nextcloud.talk.models.json.signaling.DataChannelMessage; +import com.nextcloud.talk.models.json.signaling.NCMessagePayload; +import com.nextcloud.talk.models.json.signaling.NCSignalingMessage; import java.util.Objects; @@ -48,6 +50,7 @@ public void onChange() { audioEnabled = localCallParticipantModel.isAudioEnabled(); messageSender.sendToAll(getDataChannelMessageForAudioState()); + messageSender.sendToAll(getSignalingMessageForAudioState()); } if (!Objects.equals(speaking, localCallParticipantModel.isSpeaking())) { @@ -60,6 +63,7 @@ public void onChange() { videoEnabled = localCallParticipantModel.isVideoEnabled(); messageSender.sendToAll(getDataChannelMessageForVideoState()); + messageSender.sendToAll(getSignalingMessageForVideoState()); } } } @@ -106,4 +110,61 @@ protected DataChannelMessage getDataChannelMessageForVideoState() { return new DataChannelMessage(type); } + + /** + * Returns a signaling message with the common fields set (type and room type). + * + * @param type the type of the signaling message + * @return the signaling message + */ + private NCSignalingMessage createBaseSignalingMessage(String type) { + NCSignalingMessage ncSignalingMessage = new NCSignalingMessage(); + // "roomType" is not really relevant without a peer or when referring to the whole participant, but it is + // nevertheless expected in the message. As most of the signaling messages currently sent to all participants + // are related to audio/video state "video" is used as the room type. + ncSignalingMessage.setRoomType("video"); + ncSignalingMessage.setType(type); + + return ncSignalingMessage; + } + + /** + * Returns a signaling message to notify current audio state. + * + * @return the signaling message + */ + protected NCSignalingMessage getSignalingMessageForAudioState() { + String type = "mute"; + if (localCallParticipantModel.isAudioEnabled() != null && localCallParticipantModel.isAudioEnabled()) { + type = "unmute"; + } + + NCSignalingMessage ncSignalingMessage = createBaseSignalingMessage(type); + + NCMessagePayload ncMessagePayload = new NCMessagePayload(); + ncMessagePayload.setName("audio"); + ncSignalingMessage.setPayload(ncMessagePayload); + + return ncSignalingMessage; + } + + /** + * Returns a signaling message to notify current video state. + * + * @return the signaling message + */ + protected NCSignalingMessage getSignalingMessageForVideoState() { + String type = "mute"; + if (localCallParticipantModel.isVideoEnabled() != null && localCallParticipantModel.isVideoEnabled()) { + type = "unmute"; + } + + NCSignalingMessage ncSignalingMessage = createBaseSignalingMessage(type); + + NCMessagePayload ncMessagePayload = new NCMessagePayload(); + ncMessagePayload.setName("video"); + ncSignalingMessage.setPayload(ncMessagePayload); + + return ncSignalingMessage; + } } diff --git a/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcasterMcu.java b/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcasterMcu.java index 628b615375..911bf1bf39 100644 --- a/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcasterMcu.java +++ b/app/src/main/java/com/nextcloud/talk/call/LocalStateBroadcasterMcu.java @@ -6,6 +6,8 @@ */ package com.nextcloud.talk.call; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; @@ -26,11 +28,30 @@ * initial state when the local participant joins the call, as all the remote participants joined from the point of * view of the local participant). If the state was already being sent the sending is restarted with each new * participant that joins. + *
+ * Similarly, in the case of signaling messages it is not possible either to know when the remote participants have + * "seen" the local participant and thus are ready to handle signaling messages about the state. However, in the case + * of signaling messages it is possible to send them to a specific participant, so the initial state is sent several + * times with an increasing delay directly to the participant that was added. Moreover, if the participant is removed + * the state is no longer directly sent. + *
+ * In any case, note that the state is sent only when the remote participant joins the call. Even in case of + * temporary disconnections the normal state updates sent when the state changes are expected to be received by the + * other participant, as signaling messages are sent through a WebSocket and are therefore reliable. Moreover, even + * if the WebSocket is restarted and the connection resumed (rather than joining with a new session ID) the messages + * would be also received, as in that case they would be queued until the WebSocket is connected again. + *
+ * Data channel messages, on the other hand, could be lost if the remote participant restarts the peer receiver
+ * connection (although they would be received in case of temporary disconnections, as data channels use a reliable
+ * transport by default). Therefore, as the speaking state is sent only through data channels, updates of the speaking
+ * state could be not received by remote participants.
*/
public class LocalStateBroadcasterMcu extends LocalStateBroadcaster {
private final MessageSender messageSender;
+ private final Map
+ * Nevertheless, in case of a failed connection and an ICE restart it is unclear whether the data channel messages
+ * would be received or not (as the data channel transport may be the one that failed and needs to be restarted).
+ * However, the state (except the speaking state) is also sent through signaling messages, which need to be
+ * explicitly fetched from the internal signaling server, so even in case of a failed connection they will be
+ * eventually received once the remote participant connects again.
*/
public class LocalStateBroadcasterNoMcu extends LocalStateBroadcaster {
@@ -115,5 +121,8 @@ private void sendState(String sessionId) {
messageSender.send(getDataChannelMessageForAudioState(), sessionId);
messageSender.send(getDataChannelMessageForSpeakingState(), sessionId);
messageSender.send(getDataChannelMessageForVideoState(), sessionId);
+
+ messageSender.send(getSignalingMessageForAudioState(), sessionId);
+ messageSender.send(getSignalingMessageForVideoState(), sessionId);
}
}
diff --git a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterMcuTest.kt b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterMcuTest.kt
index a20fea8437..03e32457e9 100644
--- a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterMcuTest.kt
+++ b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterMcuTest.kt
@@ -7,6 +7,8 @@
package com.nextcloud.talk.call
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
+import com.nextcloud.talk.models.json.signaling.NCMessagePayload
+import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
import io.reactivex.plugins.RxJavaPlugins
import io.reactivex.schedulers.TestScheduler
import org.junit.Before
@@ -32,6 +34,54 @@ class LocalStateBroadcasterMcuTest {
mockedMessageSender = Mockito.mock(MessageSender::class.java)
}
+ private fun getExpectedUnmuteAudio(): NCSignalingMessage {
+ val expectedUnmuteAudio = NCSignalingMessage()
+ expectedUnmuteAudio.roomType = "video"
+ expectedUnmuteAudio.type = "unmute"
+
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedUnmuteAudio.payload = payload
+
+ return expectedUnmuteAudio
+ }
+
+ private fun getExpectedMuteAudio(): NCSignalingMessage {
+ val expectedMuteAudio = NCSignalingMessage()
+ expectedMuteAudio.roomType = "video"
+ expectedMuteAudio.type = "mute"
+
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedMuteAudio.payload = payload
+
+ return expectedMuteAudio
+ }
+
+ private fun getExpectedUnmuteVideo(): NCSignalingMessage {
+ val expectedUnmuteVideo = NCSignalingMessage()
+ expectedUnmuteVideo.roomType = "video"
+ expectedUnmuteVideo.type = "unmute"
+
+ val payload = NCMessagePayload()
+ payload.name = "video"
+ expectedUnmuteVideo.payload = payload
+
+ return expectedUnmuteVideo
+ }
+
+ private fun getExpectedMuteVideo(): NCSignalingMessage {
+ val expectedMuteVideo = NCSignalingMessage()
+ expectedMuteVideo.roomType = "video"
+ expectedMuteVideo.type = "mute"
+
+ val payload = NCMessagePayload()
+ payload.name = "video"
+ expectedMuteVideo.payload = payload
+
+ return expectedMuteVideo
+ }
+
@Test
fun testStateSentWithExponentialBackoffWhenParticipantAdded() {
val testScheduler = TestScheduler()
@@ -54,12 +104,17 @@ class LocalStateBroadcasterMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
var messageCount = 1
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
@@ -68,6 +123,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
@@ -76,6 +133,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
@@ -84,6 +143,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
@@ -92,6 +153,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
@@ -100,6 +163,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
@@ -132,11 +197,16 @@ class LocalStateBroadcasterMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(1)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localCallParticipantModel!!.isSpeaking = false
@@ -151,51 +221,73 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedStoppedSpeaking)
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(2)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(2)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localCallParticipantModel!!.isAudioEnabled = false
val expectedAudioOff = DataChannelMessage("audioOff")
+ val expectedMuteAudio = getExpectedMuteAudio()
// Changing the state causes the normal state update to be sent, independently of the initial state
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedAudioOff)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedAudioOff)
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedStoppedSpeaking)
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
+ Mockito.verify(mockedMessageSender!!, times(1)).send(expectedMuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(3)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localCallParticipantModel!!.isVideoEnabled = false
val expectedVideoOff = DataChannelMessage("videoOff")
+ val expectedMuteVideo = getExpectedMuteVideo()
// Changing the state causes the normal state update to be sent, independently of the initial state
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedVideoOff)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedAudioOff)
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedStoppedSpeaking)
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedVideoOff)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
+ Mockito.verify(mockedMessageSender!!, times(2)).send(expectedMuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(1)).send(expectedMuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localCallParticipantModel!!.isVideoEnabled = true
// Changing the state causes the normal state update to be sent, independently of the initial state
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedUnmuteVideo)
testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedAudioOff)
Mockito.verify(mockedMessageSender!!, times(5)).sendToAll(expectedStoppedSpeaking)
Mockito.verify(mockedMessageSender!!, times(5)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
+ Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedUnmuteVideo)
+ Mockito.verify(mockedMessageSender!!, times(3)).send(expectedMuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(4)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@Test
- fun testStateSentWithExponentialBackoffRestartedWhenAnotherParticipantAdded() {
+ fun testStateSentWithExponentialBackoffWhenAnotherParticipantAdded() {
+ // The state sent through data channels should be restarted, although the state sent through signaling
+ // messages should be independent for each participant.
+
val testScheduler = TestScheduler()
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
@@ -216,36 +308,51 @@ class LocalStateBroadcasterMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
var dataChannelMessageCount = 1
+ var signalingMessageCount1 = 1
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
dataChannelMessageCount = 2
+ signalingMessageCount1 = 2
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
dataChannelMessageCount = 3
+ signalingMessageCount1 = 3
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
dataChannelMessageCount = 4
+ signalingMessageCount1 = 4
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
val callParticipantModel2 = MutableCallParticipantModel("theSessionId2")
@@ -255,49 +362,107 @@ class LocalStateBroadcasterMcuTest {
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
dataChannelMessageCount = 5
+ var signalingMessageCount2 = 1
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
dataChannelMessageCount = 6
+ signalingMessageCount2 = 2
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
dataChannelMessageCount = 7
+ signalingMessageCount2 = 3
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
dataChannelMessageCount = 8
+ signalingMessageCount2 = 4
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
- testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
+ // 0+1+2+4+1=8 seconds since last signaling messages for participant 1
+ testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
+
+ signalingMessageCount1 = 5
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
+ Mockito.verifyNoMoreInteractions(mockedMessageSender)
+
+ // 1+7=8 seconds since last data channel messages and signaling messages for participant 2
+ testScheduler.advanceTimeBy(7, TimeUnit.SECONDS)
dataChannelMessageCount = 9
+ signalingMessageCount2 = 5
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
- testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
+ // 7+9=16 seconds since last signaling messages for participant 1
+ testScheduler.advanceTimeBy(9, TimeUnit.SECONDS)
+
+ signalingMessageCount1 = 6
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
+ Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
+ Mockito.verifyNoMoreInteractions(mockedMessageSender)
+
+ // 9+7=16 seconds since last data channel messages and signaling messages for participant 2
+ testScheduler.advanceTimeBy(7, TimeUnit.SECONDS)
dataChannelMessageCount = 10
+ signalingMessageCount2 = 6
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
@@ -306,8 +471,9 @@ class LocalStateBroadcasterMcuTest {
}
@Test
- fun testStateStillSentWithExponentialBackoffWhenParticipantRemoved() {
+ fun testStateSentWithExponentialBackoffWhenParticipantRemoved() {
// For simplicity the exponential backoff is not aborted when the participant that triggered it is removed.
+ // However, the signaling messages are stopped when the participant is removed.
val testScheduler = TestScheduler()
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
@@ -329,36 +495,51 @@ class LocalStateBroadcasterMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
var dataChannelMessageCount = 1
+ var signalingMessageCount = 1
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
dataChannelMessageCount = 2
+ signalingMessageCount = 2
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
dataChannelMessageCount = 3
+ signalingMessageCount = 3
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
dataChannelMessageCount = 4
+ signalingMessageCount = 4
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localStateBroadcasterMcu!!.handleCallParticipantRemoved(callParticipantModel)
@@ -369,6 +550,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
@@ -377,6 +560,8 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
@@ -395,8 +580,10 @@ class LocalStateBroadcasterMcuTest {
)
val callParticipantModel = MutableCallParticipantModel("theSessionId")
+ val callParticipantModel2 = MutableCallParticipantModel("theSessionId2")
localStateBroadcasterMcu!!.handleCallParticipantAdded(callParticipantModel)
+ localStateBroadcasterMcu!!.handleCallParticipantAdded(callParticipantModel2)
// Sending will be done in another thread, so just adding the participant does not send anything until that
// other thread could run.
@@ -406,12 +593,19 @@ class LocalStateBroadcasterMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
var messageCount = 1
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
@@ -420,6 +614,10 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
@@ -428,6 +626,10 @@ class LocalStateBroadcasterMcuTest {
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSender)
localStateBroadcasterMcu!!.destroy()
diff --git a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterNoMcuTest.kt b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterNoMcuTest.kt
index 2075785fdd..f225ff7394 100644
--- a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterNoMcuTest.kt
+++ b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterNoMcuTest.kt
@@ -7,6 +7,8 @@
package com.nextcloud.talk.call
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
+import com.nextcloud.talk.models.json.signaling.NCMessagePayload
+import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito
@@ -28,6 +30,30 @@ class LocalStateBroadcasterNoMcuTest {
mockedMessageSenderNoMcu = Mockito.mock(MessageSenderNoMcu::class.java)
}
+ private fun getExpectedUnmuteAudio(): NCSignalingMessage {
+ val expectedUnmuteAudio = NCSignalingMessage()
+ expectedUnmuteAudio.roomType = "video"
+ expectedUnmuteAudio.type = "unmute"
+
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedUnmuteAudio.payload = payload
+
+ return expectedUnmuteAudio
+ }
+
+ private fun getExpectedUnmuteVideo(): NCSignalingMessage {
+ val expectedUnmuteVideo = NCSignalingMessage()
+ expectedUnmuteVideo.roomType = "video"
+ expectedUnmuteVideo.type = "unmute"
+
+ val payload = NCMessagePayload()
+ payload.name = "video"
+ expectedUnmuteVideo.payload = payload
+
+ return expectedUnmuteVideo
+ }
+
@Test
fun testStateSentWhenIceConnected() {
localStateBroadcasterNoMcu = LocalStateBroadcasterNoMcu(
@@ -49,9 +75,14 @@ class LocalStateBroadcasterNoMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
}
@@ -76,9 +107,14 @@ class LocalStateBroadcasterNoMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
}
@@ -103,9 +139,14 @@ class LocalStateBroadcasterNoMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
callParticipantModel.setIceConnectionState(PeerConnection.IceConnectionState.COMPLETED)
@@ -134,9 +175,14 @@ class LocalStateBroadcasterNoMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
callParticipantModel.setIceConnectionState(PeerConnection.IceConnectionState.COMPLETED)
@@ -191,9 +237,14 @@ class LocalStateBroadcasterNoMcuTest {
val expectedSpeaking = DataChannelMessage("speaking")
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteAudio = getExpectedUnmuteAudio()
+ val expectedUnmuteVideo = getExpectedUnmuteVideo()
+
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
callParticipantModel2.setIceConnectionState(PeerConnection.IceConnectionState.CONNECTED)
@@ -201,6 +252,8 @@ class LocalStateBroadcasterNoMcuTest {
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId2")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId2")
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId2")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId2")
+ Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId2")
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
}
diff --git a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterTest.kt b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterTest.kt
index 29b205cda5..34ca59e7e7 100644
--- a/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterTest.kt
+++ b/app/src/test/java/com/nextcloud/talk/call/LocalStateBroadcasterTest.kt
@@ -7,6 +7,8 @@
package com.nextcloud.talk.call
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
+import com.nextcloud.talk.models.json.signaling.NCMessagePayload
+import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito
@@ -49,7 +51,15 @@ class LocalStateBroadcasterTest {
val expectedAudioOn = DataChannelMessage("audioOn")
+ val expectedUnmuteAudio = NCSignalingMessage()
+ expectedUnmuteAudio.roomType = "video"
+ expectedUnmuteAudio.type = "unmute"
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedUnmuteAudio.payload = payload
+
Mockito.verify(mockedMessageSender!!).sendToAll(expectedAudioOn)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteAudio)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@@ -74,7 +84,15 @@ class LocalStateBroadcasterTest {
val expectedAudioOff = DataChannelMessage("audioOff")
+ val expectedMuteAudio = NCSignalingMessage()
+ expectedMuteAudio.roomType = "video"
+ expectedMuteAudio.type = "mute"
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedMuteAudio.payload = payload
+
Mockito.verify(mockedMessageSender!!).sendToAll(expectedAudioOff)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteAudio)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@@ -141,10 +159,18 @@ class LocalStateBroadcasterTest {
val expectedAudioOn = DataChannelMessage("audioOn")
val expectedSpeaking = DataChannelMessage("speaking")
+ val expectedUnmuteAudio = NCSignalingMessage()
+ expectedUnmuteAudio.roomType = "video"
+ expectedUnmuteAudio.type = "unmute"
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedUnmuteAudio.payload = payload
+
val inOrder = Mockito.inOrder(mockedMessageSender)
inOrder.verify(mockedMessageSender!!).sendToAll(expectedAudioOn)
inOrder.verify(mockedMessageSender!!).sendToAll(expectedSpeaking)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteAudio)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@@ -187,10 +213,18 @@ class LocalStateBroadcasterTest {
val expectedStoppedSpeaking = DataChannelMessage("stoppedSpeaking")
val expectedAudioOff = DataChannelMessage("audioOff")
+ val expectedMuteAudio = NCSignalingMessage()
+ expectedMuteAudio.roomType = "video"
+ expectedMuteAudio.type = "mute"
+ val payload = NCMessagePayload()
+ payload.name = "audio"
+ expectedMuteAudio.payload = payload
+
val inOrder = Mockito.inOrder(mockedMessageSender)
inOrder.verify(mockedMessageSender!!).sendToAll(expectedStoppedSpeaking)
inOrder.verify(mockedMessageSender!!).sendToAll(expectedAudioOff)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteAudio)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@@ -216,7 +250,15 @@ class LocalStateBroadcasterTest {
val expectedVideoOn = DataChannelMessage("videoOn")
+ val expectedUnmuteVideo = NCSignalingMessage()
+ expectedUnmuteVideo.roomType = "video"
+ expectedUnmuteVideo.type = "unmute"
+ val payload = NCMessagePayload()
+ payload.name = "video"
+ expectedUnmuteVideo.payload = payload
+
Mockito.verify(mockedMessageSender!!).sendToAll(expectedVideoOn)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteVideo)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}
@@ -241,7 +283,15 @@ class LocalStateBroadcasterTest {
val expectedVideoOff = DataChannelMessage("videoOff")
+ val expectedMuteVideo = NCSignalingMessage()
+ expectedMuteVideo.roomType = "video"
+ expectedMuteVideo.type = "mute"
+ val payload = NCMessagePayload()
+ payload.name = "video"
+ expectedMuteVideo.payload = payload
+
Mockito.verify(mockedMessageSender!!).sendToAll(expectedVideoOff)
+ Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteVideo)
Mockito.verifyNoMoreInteractions(mockedMessageSender)
}