Committed by
GitHub
Forward leave reason of disconnected events (#191)
正在显示
6 个修改的文件
包含
80 行增加
和
32 行删除
| @@ -6,6 +6,7 @@ import io.livekit.android.room.track.LocalTrackPublication | @@ -6,6 +6,7 @@ import io.livekit.android.room.track.LocalTrackPublication | ||
| 6 | import io.livekit.android.room.track.RemoteTrackPublication | 6 | import io.livekit.android.room.track.RemoteTrackPublication |
| 7 | import io.livekit.android.room.track.Track | 7 | import io.livekit.android.room.track.Track |
| 8 | import io.livekit.android.room.track.TrackPublication | 8 | import io.livekit.android.room.track.TrackPublication |
| 9 | +import livekit.LivekitModels | ||
| 9 | 10 | ||
| 10 | sealed class RoomEvent(val room: Room) : Event() { | 11 | sealed class RoomEvent(val room: Room) : Event() { |
| 11 | /** | 12 | /** |
| @@ -22,7 +23,7 @@ sealed class RoomEvent(val room: Room) : Event() { | @@ -22,7 +23,7 @@ sealed class RoomEvent(val room: Room) : Event() { | ||
| 22 | /** | 23 | /** |
| 23 | * Disconnected from room | 24 | * Disconnected from room |
| 24 | */ | 25 | */ |
| 25 | - class Disconnected(room: Room, val error: Exception?) : RoomEvent(room) | 26 | + class Disconnected(room: Room, val error: Exception?, val reason: DisconnectReason) : RoomEvent(room) |
| 26 | 27 | ||
| 27 | /** | 28 | /** |
| 28 | * When a [RemoteParticipant] joins after the local participant. It will not emit events | 29 | * When a [RemoteParticipant] joins after the local participant. It will not emit events |
| @@ -169,3 +170,29 @@ sealed class RoomEvent(val room: Room) : Event() { | @@ -169,3 +170,29 @@ sealed class RoomEvent(val room: Room) : Event() { | ||
| 169 | val oldPermissions: ParticipantPermission?, | 170 | val oldPermissions: ParticipantPermission?, |
| 170 | ) : RoomEvent(room) | 171 | ) : RoomEvent(room) |
| 171 | } | 172 | } |
| 173 | + | ||
| 174 | +enum class DisconnectReason { | ||
| 175 | + UNKNOWN_REASON, | ||
| 176 | + CLIENT_INITIATED, | ||
| 177 | + DUPLICATE_IDENTITY, | ||
| 178 | + SERVER_SHUTDOWN, | ||
| 179 | + PARTICIPANT_REMOVED, | ||
| 180 | + ROOM_DELETED, | ||
| 181 | + STATE_MISMATCH, | ||
| 182 | + JOIN_FAILURE; | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +fun LivekitModels.DisconnectReason?.convert(): DisconnectReason { | ||
| 186 | + return when (this) { | ||
| 187 | + LivekitModels.DisconnectReason.CLIENT_INITIATED -> DisconnectReason.CLIENT_INITIATED | ||
| 188 | + LivekitModels.DisconnectReason.DUPLICATE_IDENTITY -> DisconnectReason.DUPLICATE_IDENTITY | ||
| 189 | + LivekitModels.DisconnectReason.SERVER_SHUTDOWN -> DisconnectReason.SERVER_SHUTDOWN | ||
| 190 | + LivekitModels.DisconnectReason.PARTICIPANT_REMOVED -> DisconnectReason.PARTICIPANT_REMOVED | ||
| 191 | + LivekitModels.DisconnectReason.ROOM_DELETED -> DisconnectReason.ROOM_DELETED | ||
| 192 | + LivekitModels.DisconnectReason.STATE_MISMATCH -> DisconnectReason.STATE_MISMATCH | ||
| 193 | + LivekitModels.DisconnectReason.JOIN_FAILURE -> DisconnectReason.JOIN_FAILURE | ||
| 194 | + LivekitModels.DisconnectReason.UNKNOWN_REASON, | ||
| 195 | + LivekitModels.DisconnectReason.UNRECOGNIZED, | ||
| 196 | + null -> DisconnectReason.UNKNOWN_REASON | ||
| 197 | + } | ||
| 198 | +} |
| @@ -5,6 +5,8 @@ import com.google.protobuf.ByteString | @@ -5,6 +5,8 @@ import com.google.protobuf.ByteString | ||
| 5 | import io.livekit.android.ConnectOptions | 5 | import io.livekit.android.ConnectOptions |
| 6 | import io.livekit.android.RoomOptions | 6 | import io.livekit.android.RoomOptions |
| 7 | import io.livekit.android.dagger.InjectionNames | 7 | import io.livekit.android.dagger.InjectionNames |
| 8 | +import io.livekit.android.events.DisconnectReason | ||
| 9 | +import io.livekit.android.events.convert | ||
| 8 | import io.livekit.android.room.participant.ParticipantTrackPermission | 10 | import io.livekit.android.room.participant.ParticipantTrackPermission |
| 9 | import io.livekit.android.room.track.TrackException | 11 | import io.livekit.android.room.track.TrackException |
| 10 | import io.livekit.android.room.util.MediaConstraintKeys | 12 | import io.livekit.android.room.util.MediaConstraintKeys |
| @@ -456,7 +458,7 @@ internal constructor( | @@ -456,7 +458,7 @@ internal constructor( | ||
| 456 | } | 458 | } |
| 457 | 459 | ||
| 458 | close("Failed reconnecting") | 460 | close("Failed reconnecting") |
| 459 | - listener?.onEngineDisconnected("failed reconnecting.") | 461 | + listener?.onEngineDisconnected(DisconnectReason.UNKNOWN_REASON) |
| 460 | } | 462 | } |
| 461 | 463 | ||
| 462 | reconnectingJob = job | 464 | reconnectingJob = job |
| @@ -566,7 +568,7 @@ internal constructor( | @@ -566,7 +568,7 @@ internal constructor( | ||
| 566 | fun onEngineConnected() | 568 | fun onEngineConnected() |
| 567 | fun onEngineReconnected() | 569 | fun onEngineReconnected() |
| 568 | fun onEngineReconnecting() | 570 | fun onEngineReconnecting() |
| 569 | - fun onEngineDisconnected(reason: String) | 571 | + fun onEngineDisconnected(reason: DisconnectReason) |
| 570 | fun onFailToConnect(error: Throwable) | 572 | fun onFailToConnect(error: Throwable) |
| 571 | fun onJoinResponse(response: LivekitRtc.JoinResponse) | 573 | fun onJoinResponse(response: LivekitRtc.JoinResponse) |
| 572 | fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>) | 574 | fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>) |
| @@ -722,7 +724,8 @@ internal constructor( | @@ -722,7 +724,8 @@ internal constructor( | ||
| 722 | fullReconnectOnNext = true | 724 | fullReconnectOnNext = true |
| 723 | } else { | 725 | } else { |
| 724 | close() | 726 | close() |
| 725 | - listener?.onEngineDisconnected("server leave") | 727 | + val disconnectReason = leave.reason.convert() |
| 728 | + listener?.onEngineDisconnected(disconnectReason) | ||
| 726 | } | 729 | } |
| 727 | } | 730 | } |
| 728 | 731 |
| @@ -16,10 +16,7 @@ import io.livekit.android.RoomOptions | @@ -16,10 +16,7 @@ import io.livekit.android.RoomOptions | ||
| 16 | import io.livekit.android.Version | 16 | import io.livekit.android.Version |
| 17 | import io.livekit.android.audio.AudioHandler | 17 | import io.livekit.android.audio.AudioHandler |
| 18 | import io.livekit.android.dagger.InjectionNames | 18 | import io.livekit.android.dagger.InjectionNames |
| 19 | -import io.livekit.android.events.BroadcastEventBus | ||
| 20 | -import io.livekit.android.events.ParticipantEvent | ||
| 21 | -import io.livekit.android.events.RoomEvent | ||
| 22 | -import io.livekit.android.events.collect | 19 | +import io.livekit.android.events.* |
| 23 | import io.livekit.android.memory.CloseableManager | 20 | import io.livekit.android.memory.CloseableManager |
| 24 | import io.livekit.android.renderer.TextureViewRenderer | 21 | import io.livekit.android.renderer.TextureViewRenderer |
| 25 | import io.livekit.android.room.participant.* | 22 | import io.livekit.android.room.participant.* |
| @@ -250,7 +247,7 @@ constructor( | @@ -250,7 +247,7 @@ constructor( | ||
| 250 | */ | 247 | */ |
| 251 | fun disconnect() { | 248 | fun disconnect() { |
| 252 | engine.client.sendLeave() | 249 | engine.client.sendLeave() |
| 253 | - handleDisconnect() | 250 | + handleDisconnect(DisconnectReason.CLIENT_INITIATED) |
| 254 | } | 251 | } |
| 255 | 252 | ||
| 256 | /** | 253 | /** |
| @@ -463,7 +460,7 @@ constructor( | @@ -463,7 +460,7 @@ constructor( | ||
| 463 | .forEach { sid -> handleParticipantDisconnect(sid) } | 460 | .forEach { sid -> handleParticipantDisconnect(sid) } |
| 464 | } | 461 | } |
| 465 | 462 | ||
| 466 | - private fun handleDisconnect() { | 463 | + private fun handleDisconnect(reason: DisconnectReason) { |
| 467 | if (state == State.DISCONNECTED) { | 464 | if (state == State.DISCONNECTED) { |
| 468 | return | 465 | return |
| 469 | } | 466 | } |
| @@ -485,7 +482,7 @@ constructor( | @@ -485,7 +482,7 @@ constructor( | ||
| 485 | 482 | ||
| 486 | // Ensure all observers see the disconnected before closing scope. | 483 | // Ensure all observers see the disconnected before closing scope. |
| 487 | runBlocking { | 484 | runBlocking { |
| 488 | - eventBus.postEvent(RoomEvent.Disconnected(this@Room, null), coroutineScope).join() | 485 | + eventBus.postEvent(RoomEvent.Disconnected(this@Room, null, reason), coroutineScope).join() |
| 489 | } | 486 | } |
| 490 | coroutineScope.cancel() | 487 | coroutineScope.cancel() |
| 491 | } | 488 | } |
| @@ -737,9 +734,9 @@ constructor( | @@ -737,9 +734,9 @@ constructor( | ||
| 737 | /** | 734 | /** |
| 738 | * @suppress | 735 | * @suppress |
| 739 | */ | 736 | */ |
| 740 | - override fun onEngineDisconnected(reason: String) { | 737 | + override fun onEngineDisconnected(reason: DisconnectReason) { |
| 741 | LKLog.v { "engine did disconnect: $reason" } | 738 | LKLog.v { "engine did disconnect: $reason" } |
| 742 | - handleDisconnect() | 739 | + handleDisconnect(reason) |
| 743 | } | 740 | } |
| 744 | 741 | ||
| 745 | /** | 742 | /** |
| @@ -5,9 +5,7 @@ import android.net.ConnectivityManager | @@ -5,9 +5,7 @@ import android.net.ConnectivityManager | ||
| 5 | import android.net.Network | 5 | import android.net.Network |
| 6 | import androidx.test.platform.app.InstrumentationRegistry | 6 | import androidx.test.platform.app.InstrumentationRegistry |
| 7 | import io.livekit.android.MockE2ETest | 7 | import io.livekit.android.MockE2ETest |
| 8 | -import io.livekit.android.events.EventCollector | ||
| 9 | -import io.livekit.android.events.FlowCollector | ||
| 10 | -import io.livekit.android.events.RoomEvent | 8 | +import io.livekit.android.events.* |
| 11 | import io.livekit.android.mock.MockAudioStreamTrack | 9 | import io.livekit.android.mock.MockAudioStreamTrack |
| 12 | import io.livekit.android.mock.MockMediaStream | 10 | import io.livekit.android.mock.MockMediaStream |
| 13 | import io.livekit.android.mock.TestData | 11 | import io.livekit.android.mock.TestData |
| @@ -315,9 +313,33 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -315,9 +313,33 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 315 | room.disconnect() | 313 | room.disconnect() |
| 316 | val events = eventCollector.stopCollecting() | 314 | val events = eventCollector.stopCollecting() |
| 317 | 315 | ||
| 318 | - Assert.assertEquals(2, events.size) | ||
| 319 | - Assert.assertEquals(true, events[0] is RoomEvent.TrackUnpublished) | ||
| 320 | - Assert.assertEquals(true, events[1] is RoomEvent.Disconnected) | 316 | + assertEquals(2, events.size) |
| 317 | + assertEquals(true, events[0] is RoomEvent.TrackUnpublished) | ||
| 318 | + assertEquals(true, events[1] is RoomEvent.Disconnected) | ||
| 319 | + } | ||
| 320 | + | ||
| 321 | + @Test | ||
| 322 | + fun serverDisconnectReason() = runTest { | ||
| 323 | + connect() | ||
| 324 | + | ||
| 325 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 326 | + wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.LEAVE.toOkioByteString()) | ||
| 327 | + val events = eventCollector.stopCollecting() | ||
| 328 | + assertEquals(1, events.size) | ||
| 329 | + assertEquals(true, events[0] is RoomEvent.Disconnected) | ||
| 330 | + assertEquals(SignalClientTest.LEAVE.leave.reason.convert(), (events[0] as RoomEvent.Disconnected).reason) | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + @Test | ||
| 334 | + fun clientDisconnectReason() = runTest { | ||
| 335 | + connect() | ||
| 336 | + | ||
| 337 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 338 | + room.disconnect() | ||
| 339 | + val events = eventCollector.stopCollecting() | ||
| 340 | + assertEquals(1, events.size) | ||
| 341 | + assertEquals(true, events[0] is RoomEvent.Disconnected) | ||
| 342 | + assertEquals(DisconnectReason.CLIENT_INITIATED, (events[0] as RoomEvent.Disconnected).reason) | ||
| 321 | } | 343 | } |
| 322 | 344 | ||
| 323 | @Test | 345 | @Test |
| @@ -7,10 +7,7 @@ import androidx.test.core.app.ApplicationProvider | @@ -7,10 +7,7 @@ import androidx.test.core.app.ApplicationProvider | ||
| 7 | import androidx.test.platform.app.InstrumentationRegistry | 7 | import androidx.test.platform.app.InstrumentationRegistry |
| 8 | import io.livekit.android.audio.NoAudioHandler | 8 | import io.livekit.android.audio.NoAudioHandler |
| 9 | import io.livekit.android.coroutines.TestCoroutineRule | 9 | import io.livekit.android.coroutines.TestCoroutineRule |
| 10 | -import io.livekit.android.events.EventCollector | ||
| 11 | -import io.livekit.android.events.EventListenable | ||
| 12 | -import io.livekit.android.events.ParticipantEvent | ||
| 13 | -import io.livekit.android.events.RoomEvent | 10 | +import io.livekit.android.events.* |
| 14 | import io.livekit.android.memory.CloseableManager | 11 | import io.livekit.android.memory.CloseableManager |
| 15 | import io.livekit.android.mock.* | 12 | import io.livekit.android.mock.* |
| 16 | import io.livekit.android.room.participant.LocalParticipant | 13 | import io.livekit.android.room.participant.LocalParticipant |
| @@ -135,11 +132,12 @@ class RoomTest { | @@ -135,11 +132,12 @@ class RoomTest { | ||
| 135 | connect() | 132 | connect() |
| 136 | 133 | ||
| 137 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 134 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 138 | - room.onEngineDisconnected("") | 135 | + room.onEngineDisconnected(DisconnectReason.SERVER_SHUTDOWN) |
| 139 | val events = eventCollector.stopCollecting() | 136 | val events = eventCollector.stopCollecting() |
| 140 | 137 | ||
| 141 | - Assert.assertEquals(1, events.size) | ||
| 142 | - Assert.assertEquals(true, events[0] is RoomEvent.Disconnected) | 138 | + assertEquals(1, events.size) |
| 139 | + assertEquals(true, events[0] is RoomEvent.Disconnected) | ||
| 140 | + assertEquals(DisconnectReason.SERVER_SHUTDOWN, (events[0] as RoomEvent.Disconnected).reason) | ||
| 143 | } | 141 | } |
| 144 | 142 | ||
| 145 | @Test | 143 | @Test |
| @@ -160,14 +158,14 @@ class RoomTest { | @@ -160,14 +158,14 @@ class RoomTest { | ||
| 160 | ) | 158 | ) |
| 161 | 159 | ||
| 162 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 160 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 163 | - room.onEngineDisconnected("") | 161 | + room.onEngineDisconnected(DisconnectReason.CLIENT_INITIATED) |
| 164 | val events = eventCollector.stopCollecting() | 162 | val events = eventCollector.stopCollecting() |
| 165 | 163 | ||
| 166 | - Assert.assertEquals(4, events.size) | ||
| 167 | - Assert.assertEquals(true, events[0] is RoomEvent.TrackUnsubscribed) | ||
| 168 | - Assert.assertEquals(true, events[1] is RoomEvent.TrackUnpublished) | ||
| 169 | - Assert.assertEquals(true, events[2] is RoomEvent.ParticipantDisconnected) | ||
| 170 | - Assert.assertEquals(true, events[3] is RoomEvent.Disconnected) | 164 | + assertEquals(4, events.size) |
| 165 | + assertEquals(true, events[0] is RoomEvent.TrackUnsubscribed) | ||
| 166 | + assertEquals(true, events[1] is RoomEvent.TrackUnpublished) | ||
| 167 | + assertEquals(true, events[2] is RoomEvent.ParticipantDisconnected) | ||
| 168 | + assertEquals(true, events[3] is RoomEvent.Disconnected) | ||
| 171 | Assert.assertTrue(room.remoteParticipants.isEmpty()) | 169 | Assert.assertTrue(room.remoteParticipants.isEmpty()) |
| 172 | } | 170 | } |
| 173 | } | 171 | } |
| @@ -442,6 +442,7 @@ class SignalClientTest : BaseTest() { | @@ -442,6 +442,7 @@ class SignalClientTest : BaseTest() { | ||
| 442 | 442 | ||
| 443 | val LEAVE = with(LivekitRtc.SignalResponse.newBuilder()) { | 443 | val LEAVE = with(LivekitRtc.SignalResponse.newBuilder()) { |
| 444 | leave = with(LivekitRtc.LeaveRequest.newBuilder()) { | 444 | leave = with(LivekitRtc.LeaveRequest.newBuilder()) { |
| 445 | + reason = LivekitModels.DisconnectReason.SERVER_SHUTDOWN | ||
| 445 | build() | 446 | build() |
| 446 | } | 447 | } |
| 447 | build() | 448 | build() |
-
请 注册 或 登录 后发表评论