Implement rejecting incoming call.

This commit is contained in:
onurays 2020-05-26 14:30:22 +03:00 committed by Valere
parent 743ace7e60
commit f50f81d321
2 changed files with 111 additions and 100 deletions

View file

@ -122,10 +122,9 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
private fun createPeerConnectionFactory() { private fun createPeerConnectionFactory() {
executor.execute {
if (peerConnectionFactory == null) { if (peerConnectionFactory == null) {
Timber.v("## VOIP createPeerConnectionFactory") Timber.v("## VOIP createPeerConnectionFactory")
val eglBaseContext = rootEglBase?.eglBaseContext ?: return@execute Unit.also { val eglBaseContext = rootEglBase?.eglBaseContext ?: return Unit.also {
Timber.e("## VOIP No EGL BASE") Timber.e("## VOIP No EGL BASE")
} }
@ -152,9 +151,8 @@ class WebRtcPeerConnectionManager @Inject constructor(
.createPeerConnectionFactory() .createPeerConnectionFactory()
} }
} }
}
private fun createPeerConnection() { private fun createPeerConnection(observer: PeerConnectionObserverAdapter) {
val iceServers = ArrayList<PeerConnection.IceServer>().apply { val iceServers = ArrayList<PeerConnection.IceServer>().apply {
listOf("turn:turn.matrix.org:3478?transport=udp", "turn:turn.matrix.org:3478?transport=tcp", "turns:turn.matrix.org:443?transport=tcp").forEach { listOf("turn:turn.matrix.org:3478?transport=udp", "turn:turn.matrix.org:3478?transport=tcp", "turns:turn.matrix.org:443?transport=tcp").forEach {
add( add(
@ -166,40 +164,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
} }
Timber.v("## VOIP creating peer connection... ") Timber.v("## VOIP creating peer connection... ")
peerConnection = peerConnectionFactory?.createPeerConnection( peerConnection = peerConnectionFactory?.createPeerConnection(iceServers, observer)
iceServers,
object : PeerConnectionObserverAdapter() {
override fun onIceCandidate(p0: IceCandidate?) {
Timber.v("## VOIP onIceCandidate local $p0")
p0?.let { iceCandidateSource.onNext(it) }
}
override fun onAddStream(mediaStream: MediaStream?) {
Timber.v("## VOIP onAddStream remote $mediaStream")
mediaStream?.videoTracks?.firstOrNull()?.let {
listener?.addRemoteVideoTrack(it)
remoteVideoTrack = it
}
}
override fun onRemoveStream(mediaStream: MediaStream?) {
mediaStream?.let {
listener?.removeRemoteVideoStream(it)
}
remoteSurfaceRenderer?.get()?.let {
remoteVideoTrack?.removeSink(it)
}
remoteVideoTrack = null
}
override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
Timber.v("## VOIP onIceConnectionChange $p0")
if (p0 == PeerConnection.IceConnectionState.DISCONNECTED) {
listener?.onDisconnect()
}
}
}
)
} }
// TODO REMOVE THIS FUNCTION // TODO REMOVE THIS FUNCTION
@ -244,8 +209,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
// } // }
// .disposeOnDestroy() // .disposeOnDestroy()
localMediaStream = peerConnectionFactory?.createLocalMediaStream("ARDAMS") // magic value? localMediaStream = peerConnectionFactory?.createLocalMediaStream("ARDAMS") // magic value?
localMediaStream?.addTrack(localVideoTrack) localMediaStream?.addTrack(localVideoTrack)
localMediaStream?.addTrack(audioTrack) localMediaStream?.addTrack(audioTrack)
@ -260,6 +223,8 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
fun answerReceived(callId: String, answerSdp: SessionDescription) { fun answerReceived(callId: String, answerSdp: SessionDescription) {
this.callId = callId
executor.execute { executor.execute {
Timber.v("## answerReceived $callId") Timber.v("## answerReceived $callId")
peerConnection?.setRemoteDescription(object : SdpObserverAdapter() {}, answerSdp) peerConnection?.setRemoteDescription(object : SdpObserverAdapter() {}, answerSdp)
@ -268,21 +233,53 @@ class WebRtcPeerConnectionManager @Inject constructor(
private fun startCall() { private fun startCall() {
createPeerConnectionFactory() createPeerConnectionFactory()
createPeerConnection() createPeerConnection(object : PeerConnectionObserverAdapter() {
override fun onIceCandidate(p0: IceCandidate?) {
Timber.v("## VOIP onIceCandidate local $p0")
p0?.let { iceCandidateSource.onNext(it) }
}
override fun onAddStream(mediaStream: MediaStream?) {
Timber.v("## VOIP onAddStream remote $mediaStream")
mediaStream?.videoTracks?.firstOrNull()?.let {
listener?.addRemoteVideoTrack(it)
remoteVideoTrack = it
}
}
override fun onRemoveStream(mediaStream: MediaStream?) {
mediaStream?.let {
listener?.removeRemoteVideoStream(it)
}
remoteSurfaceRenderer?.get()?.let {
remoteVideoTrack?.removeSink(it)
}
remoteVideoTrack = null
}
override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
Timber.v("## VOIP onIceConnectionChange $p0")
if (p0 == PeerConnection.IceConnectionState.DISCONNECTED) {
listener?.onDisconnect()
}
}
})
iceCandidateDisposable = iceCandidateSource iceCandidateDisposable = iceCandidateSource
.buffer(400, TimeUnit.MILLISECONDS) .buffer(400, TimeUnit.MILLISECONDS)
.subscribe { .subscribe {
// omit empty :/ // omit empty :/
if (it.isNotEmpty()) { if (it.isNotEmpty()) {
Timber.v("## Sending local ice candidates to callId: $callId roomId: $signalingRoomId")
sessionHolder sessionHolder
.getActiveSession() .getActiveSession()
.callService() .callService()
.sendLocalIceCandidates(callId ?: "", signalingRoomId ?: "", it) .sendLocalIceCandidates(callId ?: "", signalingRoomId ?: "", it)
} }
} }
}
executor.execute { private fun sendSdpOffer() {
val constraints = MediaConstraints() val constraints = MediaConstraints()
constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")) constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true")) constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
@ -298,11 +295,14 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
override fun onCreateSuccess(sessionDescription: SessionDescription) { override fun onCreateSuccess(sessionDescription: SessionDescription) {
Timber.v("## VOIP onCreateSuccess $sessionDescription") Timber.v("## VOIP onCreateSuccess $sessionDescription will set local description")
peerConnection?.setLocalDescription(object : SdpObserverAdapter() { peerConnection?.setLocalDescription(object : SdpObserverAdapter() {
override fun onSetSuccess() { override fun onSetSuccess() {
Timber.v("## setLocalDescription success")
callId = UUID.randomUUID().toString() callId = UUID.randomUUID().toString()
sessionHolder.getActiveSession().callService().sendOfferSdp(callId!!, signalingRoomId!!, sessionDescription, object : MatrixCallback<String> {}) Timber.v("## sending offer to callId: $callId roomId: $signalingRoomId")
sessionHolder.getActiveSession().callService().sendOfferSdp(callId ?: "", signalingRoomId
?: "", sessionDescription, object : MatrixCallback<String> {})
} }
}, sessionDescription) }, sessionDescription)
} }
@ -312,7 +312,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
}, constraints) }, constraints)
} }
}
fun attachViewRenderers(localViewRenderer: SurfaceViewRenderer, remoteViewRenderer: SurfaceViewRenderer) { fun attachViewRenderers(localViewRenderer: SurfaceViewRenderer, remoteViewRenderer: SurfaceViewRenderer) {
localVideoTrack?.addSink(localViewRenderer) localVideoTrack?.addSink(localViewRenderer)
@ -339,7 +338,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
executor.execute { executor.execute {
// Do not dispose peer connection (https://bugs.chromium.org/p/webrtc/issues/detail?id=7543) // Do not dispose peer connection (https://bugs.chromium.org/p/webrtc/issues/detail?id=7543)
peerConnection?.close() peerConnection?.close()
peerConnection?.removeStream(localMediaStream) localMediaStream?.let { peerConnection?.removeStream(it) }
peerConnection = null peerConnection = null
audioSource?.dispose() audioSource?.dispose()
videoSource?.dispose() videoSource?.dispose()
@ -377,13 +376,19 @@ class WebRtcPeerConnectionManager @Inject constructor(
fun startOutgoingCall(context: Context, signalingRoomId: String, participantUserId: String, isVideoCall: Boolean) { fun startOutgoingCall(context: Context, signalingRoomId: String, participantUserId: String, isVideoCall: Boolean) {
this.signalingRoomId = signalingRoomId this.signalingRoomId = signalingRoomId
this.participantUserId = participantUserId this.participantUserId = participantUserId
startHeadsUpService(signalingRoomId, sessionHolder.getActiveSession().myUserId, false, isVideoCall) startHeadsUpService(signalingRoomId, sessionHolder.getActiveSession().myUserId, false, isVideoCall)
context.startActivity(VectorCallActivity.newIntent(context, signalingRoomId, participantUserId, false, isVideoCall)) context.startActivity(VectorCallActivity.newIntent(context, signalingRoomId, participantUserId, false, isVideoCall))
startCall() startCall()
sendSdpOffer()
} }
override fun onCallInviteReceived(signalingRoomId: String, participantUserId: String, callInviteContent: CallInviteContent) { override fun onCallInviteReceived(signalingRoomId: String, participantUserId: String, callInviteContent: CallInviteContent) {
this.callId = callInviteContent.callId
this.signalingRoomId = signalingRoomId
this.participantUserId = participantUserId
startHeadsUpService(signalingRoomId, participantUserId, true, callInviteContent.isVideo()) startHeadsUpService(signalingRoomId, participantUserId, true, callInviteContent.isVideo())
startCall() startCall()
@ -399,8 +404,8 @@ class WebRtcPeerConnectionManager @Inject constructor(
fun endCall() { fun endCall() {
if (callId != null && signalingRoomId != null) { if (callId != null && signalingRoomId != null) {
sessionHolder.getActiveSession().callService().sendHangup(callId!!, signalingRoomId!!) sessionHolder.getActiveSession().callService().sendHangup(callId!!, signalingRoomId!!)
close()
} }
close()
} }
override fun onCallAnswerReceived(callAnswerContent: CallAnswerContent) { override fun onCallAnswerReceived(callAnswerContent: CallAnswerContent) {

View file

@ -19,11 +19,22 @@ package im.vector.riotx.features.call.service
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import im.vector.riotx.core.di.HasVectorInjector
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
import im.vector.riotx.features.settings.VectorLocale.context import im.vector.riotx.features.settings.VectorLocale.context
import timber.log.Timber import timber.log.Timber
class CallHeadsUpActionReceiver : BroadcastReceiver() { class CallHeadsUpActionReceiver : BroadcastReceiver() {
private lateinit var peerConnectionManager: WebRtcPeerConnectionManager
init {
val appContext = context.applicationContext
if (appContext is HasVectorInjector) {
peerConnectionManager = appContext.injector().webRtcPeerConnectionManager()
}
}
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
when (intent?.getIntExtra(CallHeadsUpService.EXTRA_CALL_ACTION_KEY, 0)) { when (intent?.getIntExtra(CallHeadsUpService.EXTRA_CALL_ACTION_KEY, 0)) {
CallHeadsUpService.CALL_ACTION_ANSWER -> onCallAnswerClicked() CallHeadsUpService.CALL_ACTION_ANSWER -> onCallAnswerClicked()
@ -33,15 +44,10 @@ class CallHeadsUpActionReceiver : BroadcastReceiver() {
private fun onCallRejectClicked() { private fun onCallRejectClicked() {
Timber.d("onCallRejectClicked") Timber.d("onCallRejectClicked")
stopService() peerConnectionManager.endCall()
} }
private fun onCallAnswerClicked() { private fun onCallAnswerClicked() {
Timber.d("onCallAnswerClicked") Timber.d("onCallAnswerClicked")
} }
private fun stopService() {
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
context.stopService(Intent(context, CallHeadsUpService::class.java))
}
} }