Cleaning call states
This commit is contained in:
parent
56ed56a986
commit
a1907aaddb
@ -21,17 +21,20 @@ enum class CallState {
|
|||||||
/** Idle, setting up objects */
|
/** Idle, setting up objects */
|
||||||
IDLE,
|
IDLE,
|
||||||
|
|
||||||
|
|
||||||
/** Dialing. Outgoing call is signaling the remote peer */
|
/** Dialing. Outgoing call is signaling the remote peer */
|
||||||
DIALING,
|
DIALING,
|
||||||
|
|
||||||
|
|
||||||
|
/** Local ringing. Incoming call offer received */
|
||||||
|
LOCAL_RINGING,
|
||||||
|
|
||||||
/** Answering. Incoming call is responding to remote peer */
|
/** Answering. Incoming call is responding to remote peer */
|
||||||
ANSWERING,
|
ANSWERING,
|
||||||
|
|
||||||
/** Remote ringing. Outgoing call, ICE negotiation is complete */
|
/** Connecting. Incoming/Outgoing Offer and answer are known, Currently checking and testing pairs of ice candidates */
|
||||||
REMOTE_RINGING,
|
CONNECTING,
|
||||||
|
|
||||||
/** Local ringing. Incoming call, ICE negotiation is complete */
|
|
||||||
LOCAL_RINGING,
|
|
||||||
|
|
||||||
/** Connected. Incoming/Outgoing call, the call is connected */
|
/** Connected. Incoming/Outgoing call, the call is connected */
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
|
@ -74,15 +74,16 @@ internal class MxCallImpl(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
if (isOutgoing) {
|
if (isOutgoing) {
|
||||||
state = CallState.DIALING
|
state = CallState.IDLE
|
||||||
} else {
|
} else {
|
||||||
|
// because it's created on reception of an offer
|
||||||
state = CallState.LOCAL_RINGING
|
state = CallState.LOCAL_RINGING
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun offerSdp(sdp: SessionDescription) {
|
override fun offerSdp(sdp: SessionDescription) {
|
||||||
if (!isOutgoing) return
|
if (!isOutgoing) return
|
||||||
state = CallState.REMOTE_RINGING
|
state = CallState.DIALING
|
||||||
CallInviteContent(
|
CallInviteContent(
|
||||||
callId = callId,
|
callId = callId,
|
||||||
lifetime = DefaultCallSignalingService.CALL_TIMEOUT_MS,
|
lifetime = DefaultCallSignalingService.CALL_TIMEOUT_MS,
|
||||||
@ -108,6 +109,7 @@ internal class MxCallImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun sendLocalIceCandidateRemovals(candidates: List<IceCandidate>) {
|
override fun sendLocalIceCandidateRemovals(candidates: List<IceCandidate>) {
|
||||||
|
// For now we don't support this flow
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hangUp() {
|
override fun hangUp() {
|
||||||
|
@ -35,17 +35,16 @@ class CallControlsView @JvmOverloads constructor(
|
|||||||
|
|
||||||
var interactionListener: InteractionListener? = null
|
var interactionListener: InteractionListener? = null
|
||||||
|
|
||||||
@BindView(R.id.incomingRingingControls)
|
@BindView(R.id.ringingControls)
|
||||||
lateinit var incomingRingingControls: ViewGroup
|
lateinit var ringingControls: ViewGroup
|
||||||
// @BindView(R.id.iv_icr_accept_call)
|
@BindView(R.id.iv_icr_accept_call)
|
||||||
// lateinit var incomingRingingControlAccept: ImageView
|
lateinit var ringingControlAccept: ImageView
|
||||||
// @BindView(R.id.iv_icr_end_call)
|
@BindView(R.id.iv_icr_end_call)
|
||||||
// lateinit var incomingRingingControlDecline: ImageView
|
lateinit var ringingControlDecline: ImageView
|
||||||
|
|
||||||
@BindView(R.id.connectedControls)
|
@BindView(R.id.connectedControls)
|
||||||
lateinit var connectedControls: ViewGroup
|
lateinit var connectedControls: ViewGroup
|
||||||
|
|
||||||
|
|
||||||
@BindView(R.id.iv_mute_toggle)
|
@BindView(R.id.iv_mute_toggle)
|
||||||
lateinit var muteIcon: ImageView
|
lateinit var muteIcon: ImageView
|
||||||
|
|
||||||
@ -89,31 +88,31 @@ class CallControlsView @JvmOverloads constructor(
|
|||||||
videoToggleIcon.setImageResource(if (state.isVideoEnabled) R.drawable.ic_video else R.drawable.ic_video_off)
|
videoToggleIcon.setImageResource(if (state.isVideoEnabled) R.drawable.ic_video else R.drawable.ic_video_off)
|
||||||
|
|
||||||
when (callState) {
|
when (callState) {
|
||||||
CallState.DIALING -> {
|
CallState.IDLE,
|
||||||
}
|
CallState.DIALING,
|
||||||
CallState.ANSWERING -> {
|
CallState.CONNECTING,
|
||||||
incomingRingingControls.isVisible = false
|
CallState.ANSWERING -> {
|
||||||
|
ringingControls.isVisible = true
|
||||||
|
ringingControlAccept.isVisible = false
|
||||||
|
ringingControlDecline.isVisible = true
|
||||||
connectedControls.isVisible = false
|
connectedControls.isVisible = false
|
||||||
}
|
}
|
||||||
CallState.REMOTE_RINGING -> {
|
CallState.LOCAL_RINGING -> {
|
||||||
}
|
ringingControls.isVisible = true
|
||||||
CallState.LOCAL_RINGING -> {
|
ringingControlAccept.isVisible = true
|
||||||
incomingRingingControls.isVisible = true
|
ringingControlDecline.isVisible = true
|
||||||
connectedControls.isVisible = false
|
connectedControls.isVisible = false
|
||||||
}
|
}
|
||||||
CallState.CONNECTED -> {
|
CallState.CONNECTED -> {
|
||||||
incomingRingingControls.isVisible = false
|
ringingControls.isVisible = false
|
||||||
connectedControls.isVisible = true
|
connectedControls.isVisible = true
|
||||||
}
|
}
|
||||||
CallState.TERMINATED,
|
CallState.TERMINATED,
|
||||||
CallState.IDLE,
|
null -> {
|
||||||
null -> {
|
ringingControls.isVisible = false
|
||||||
incomingRingingControls.isVisible = false
|
|
||||||
connectedControls.isVisible = false
|
connectedControls.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InteractionListener {
|
interface InteractionListener {
|
||||||
|
@ -91,17 +91,6 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||||||
|
|
||||||
private var rootEglBase: EglBase? = null
|
private var rootEglBase: EglBase? = null
|
||||||
|
|
||||||
// var callHeadsUpService: CallHeadsUpService? = null
|
|
||||||
// private val serviceConnection = object : ServiceConnection {
|
|
||||||
// override fun onServiceDisconnected(name: ComponentName?) {
|
|
||||||
// finish()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
// callHeadsUpService = (service as? CallHeadsUpService.CallHeadsUpServiceBinder)?.getService()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun doBeforeSetContentView() {
|
override fun doBeforeSetContentView() {
|
||||||
// Set window styles for fullscreen-window size. Needs to be done before adding content.
|
// Set window styles for fullscreen-window size. Needs to be done before adding content.
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
@ -130,9 +119,6 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||||||
// window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
// window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
// window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
// window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
// tryThis { unbindService(serviceConnection) }
|
|
||||||
// bindService(Intent(this, CallHeadsUpService::class.java), serviceConnection, 0)
|
|
||||||
|
|
||||||
if (intent.hasExtra(MvRx.KEY_ARG)) {
|
if (intent.hasExtra(MvRx.KEY_ARG)) {
|
||||||
callArgs = intent.getParcelableExtra(MvRx.KEY_ARG)!!
|
callArgs = intent.getParcelableExtra(MvRx.KEY_ARG)!!
|
||||||
} else {
|
} else {
|
||||||
@ -184,8 +170,7 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||||||
Timber.v("## VOIP renderState call $state")
|
Timber.v("## VOIP renderState call $state")
|
||||||
callControlsView.updateForState(state)
|
callControlsView.updateForState(state)
|
||||||
when (state.callState.invoke()) {
|
when (state.callState.invoke()) {
|
||||||
CallState.IDLE -> {
|
CallState.IDLE,
|
||||||
}
|
|
||||||
CallState.DIALING -> {
|
CallState.DIALING -> {
|
||||||
callVideoGroup.isInvisible = true
|
callVideoGroup.isInvisible = true
|
||||||
callInfoGroup.isVisible = true
|
callInfoGroup.isVisible = true
|
||||||
@ -196,35 +181,40 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||||||
callTypeText.setText(if (state.isVideoCall) R.string.action_video_call else R.string.action_voice_call)
|
callTypeText.setText(if (state.isVideoCall) R.string.action_video_call else R.string.action_voice_call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallState.ANSWERING -> {
|
|
||||||
callInfoGroup.isVisible = true
|
|
||||||
callStatusText.setText(R.string.call_connecting)
|
|
||||||
state.otherUserMatrixItem.invoke()?.let {
|
|
||||||
avatarRenderer.render(it, otherMemberAvatar)
|
|
||||||
}
|
|
||||||
// fullscreenRenderer.isVisible = true
|
|
||||||
// pipRenderer.isVisible = true
|
|
||||||
}
|
|
||||||
CallState.REMOTE_RINGING -> {
|
|
||||||
callVideoGroup.isInvisible = true
|
|
||||||
callInfoGroup.isVisible = true
|
|
||||||
callStatusText.setText(
|
|
||||||
if (state.isVideoCall) R.string.incoming_video_call else R.string.incoming_voice_call
|
|
||||||
)
|
|
||||||
}
|
|
||||||
CallState.LOCAL_RINGING -> {
|
CallState.LOCAL_RINGING -> {
|
||||||
callVideoGroup.isInvisible = true
|
callVideoGroup.isInvisible = true
|
||||||
callInfoGroup.isVisible = true
|
callInfoGroup.isVisible = true
|
||||||
|
callStatusText.text = null
|
||||||
state.otherUserMatrixItem.invoke()?.let {
|
state.otherUserMatrixItem.invoke()?.let {
|
||||||
avatarRenderer.render(it, otherMemberAvatar)
|
avatarRenderer.render(it, otherMemberAvatar)
|
||||||
participantNameText.text = it.getBestName()
|
participantNameText.text = it.getBestName()
|
||||||
callTypeText.setText(if (state.isVideoCall) R.string.action_video_call else R.string.action_voice_call)
|
callTypeText.setText(if (state.isVideoCall) R.string.action_video_call else R.string.action_voice_call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallState.ANSWERING -> {
|
||||||
|
callVideoGroup.isInvisible = true
|
||||||
|
callInfoGroup.isVisible = true
|
||||||
|
callStatusText.setText(R.string.call_connecting)
|
||||||
|
state.otherUserMatrixItem.invoke()?.let {
|
||||||
|
avatarRenderer.render(it, otherMemberAvatar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CallState.CONNECTING -> {
|
||||||
|
callVideoGroup.isInvisible = true
|
||||||
|
callInfoGroup.isVisible = true
|
||||||
|
callStatusText.setText(R.string.call_connecting)
|
||||||
|
}
|
||||||
CallState.CONNECTED -> {
|
CallState.CONNECTED -> {
|
||||||
// TODO only if is video call
|
if (callArgs.isVideoCall) {
|
||||||
callVideoGroup.isVisible = true
|
callVideoGroup.isVisible = true
|
||||||
callInfoGroup.isVisible = false
|
callInfoGroup.isVisible = false
|
||||||
|
} else {
|
||||||
|
callVideoGroup.isInvisible = true
|
||||||
|
callInfoGroup.isVisible = true
|
||||||
|
callStatusText.text = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CallState.TERMINATED -> {
|
CallState.TERMINATED -> {
|
||||||
finish()
|
finish()
|
||||||
@ -279,20 +269,20 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onPause() {
|
||||||
peerConnectionManager.detachRenderers()
|
peerConnectionManager.detachRenderers()
|
||||||
// tryThis { unbindService(serviceConnection) }
|
super.onPause()
|
||||||
super.onDestroy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleViewEvents(event: VectorCallViewEvents?) {
|
private fun handleViewEvents(event: VectorCallViewEvents?) {
|
||||||
when (event) {
|
Timber.v("handleViewEvents $event")
|
||||||
is VectorCallViewEvents.CallAnswered -> {
|
// when (event) {
|
||||||
}
|
// is VectorCallViewEvents.CallAnswered -> {
|
||||||
is VectorCallViewEvents.CallHangup -> {
|
// }
|
||||||
finish()
|
// is VectorCallViewEvents.CallHangup -> {
|
||||||
}
|
// finish()
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -57,9 +57,9 @@ sealed class VectorCallViewActions : VectorViewModelAction {
|
|||||||
|
|
||||||
sealed class VectorCallViewEvents : VectorViewEvents {
|
sealed class VectorCallViewEvents : VectorViewEvents {
|
||||||
|
|
||||||
data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents()
|
// data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents()
|
||||||
data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents()
|
// data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents()
|
||||||
object CallAccepted : VectorCallViewEvents()
|
// object CallAccepted : VectorCallViewEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
class VectorCallViewModel @AssistedInject constructor(
|
class VectorCallViewModel @AssistedInject constructor(
|
||||||
|
@ -211,7 +211,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||||||
currentCall?.mxCall?.offerSdp(p0)
|
currentCall?.mxCall?.offerSdp(p0)
|
||||||
}
|
}
|
||||||
}, constraints)
|
}, constraints)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTurnServer(callback: ((TurnServer?) -> Unit)) {
|
private fun getTurnServer(callback: ((TurnServer?) -> Unit)) {
|
||||||
@ -374,7 +373,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||||||
// If remote track exists, then sink it to surface
|
// If remote track exists, then sink it to surface
|
||||||
remoteSurfaceRenderer?.get()?.let { participantSurface ->
|
remoteSurfaceRenderer?.get()?.let { participantSurface ->
|
||||||
currentCall?.remoteVideoTrack?.let {
|
currentCall?.remoteVideoTrack?.let {
|
||||||
it.setEnabled(true)
|
|
||||||
it.addSink(participantSurface)
|
it.addSink(participantSurface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -551,17 +549,47 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||||||
override fun onConnectionChange(newState: PeerConnection.PeerConnectionState?) {
|
override fun onConnectionChange(newState: PeerConnection.PeerConnectionState?) {
|
||||||
Timber.v("## VOIP StreamObserver onConnectionChange: $newState")
|
Timber.v("## VOIP StreamObserver onConnectionChange: $newState")
|
||||||
when (newState) {
|
when (newState) {
|
||||||
PeerConnection.PeerConnectionState.CONNECTED -> {
|
/**
|
||||||
|
* Every ICE transport used by the connection is either in use (state "connected" or "completed")
|
||||||
|
* or is closed (state "closed"); in addition, at least one transport is either "connected" or "completed"
|
||||||
|
*/
|
||||||
|
PeerConnection.PeerConnectionState.CONNECTED -> {
|
||||||
callContext.mxCall.state = CallState.CONNECTED
|
callContext.mxCall.state = CallState.CONNECTED
|
||||||
}
|
}
|
||||||
PeerConnection.PeerConnectionState.FAILED -> {
|
/**
|
||||||
|
* One or more of the ICE transports on the connection is in the "failed" state.
|
||||||
|
*/
|
||||||
|
PeerConnection.PeerConnectionState.FAILED -> {
|
||||||
endCall()
|
endCall()
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* At least one of the connection's ICE transports (RTCIceTransports or RTCDtlsTransports) are in the "new" state,
|
||||||
|
* and none of them are in one of the following states: "connecting", "checking", "failed", or "disconnected",
|
||||||
|
* or all of the connection's transports are in the "closed" state.
|
||||||
|
*/
|
||||||
PeerConnection.PeerConnectionState.NEW,
|
PeerConnection.PeerConnectionState.NEW,
|
||||||
PeerConnection.PeerConnectionState.CONNECTING,
|
|
||||||
PeerConnection.PeerConnectionState.DISCONNECTED,
|
/**
|
||||||
|
* One or more of the ICE transports are currently in the process of establishing a connection;
|
||||||
|
* that is, their RTCIceConnectionState is either "checking" or "connected", and no transports are in the "failed" state
|
||||||
|
*/
|
||||||
|
PeerConnection.PeerConnectionState.CONNECTING -> {
|
||||||
|
callContext.mxCall.state = CallState.CONNECTING
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The RTCPeerConnection is closed.
|
||||||
|
* This value was in the RTCSignalingState enum (and therefore found by reading the value of the signalingState)
|
||||||
|
* property until the May 13, 2016 draft of the specification.
|
||||||
|
*/
|
||||||
PeerConnection.PeerConnectionState.CLOSED,
|
PeerConnection.PeerConnectionState.CLOSED,
|
||||||
null -> {
|
/**
|
||||||
|
* At least one of the ICE transports for the connection is in the "disconnected" state and none of the other transports are in the state "failed",
|
||||||
|
* "connecting", or "checking".
|
||||||
|
*/
|
||||||
|
PeerConnection.PeerConnectionState.DISCONNECTED -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
null -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -580,14 +608,60 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState) {
|
override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState) {
|
||||||
|
Timber.v("## VOIP StreamObserver onIceConnectionChange IceConnectionState:$newState")
|
||||||
when (newState) {
|
when (newState) {
|
||||||
PeerConnection.IceConnectionState.CONNECTED -> Timber.v("## VOIP StreamObserver onIceConnectionChange.CONNECTED")
|
|
||||||
PeerConnection.IceConnectionState.DISCONNECTED -> {
|
/**
|
||||||
Timber.v("## VOIP StreamObserver onIceConnectionChange.DISCONNECTED")
|
* the ICE agent is gathering addresses or is waiting to be given remote candidates through
|
||||||
endCall()
|
* calls to RTCPeerConnection.addIceCandidate() (or both).
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.NEW -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The ICE agent has been given one or more remote candidates and is checking pairs of local and remote candidates
|
||||||
|
* against one another to try to find a compatible match, but has not yet found a pair which will allow
|
||||||
|
* the peer connection to be made. It's possible that gathering of candidates is also still underway.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.CHECKING -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A usable pairing of local and remote candidates has been found for all components of the connection,
|
||||||
|
* and the connection has been established.
|
||||||
|
* It's possible that gathering is still underway, and it's also possible that the ICE agent is still checking
|
||||||
|
* candidates against one another looking for a better connection to use.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.CONNECTED -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Checks to ensure that components are still connected failed for at least one component of the RTCPeerConnection.
|
||||||
|
* This is a less stringent test than "failed" and may trigger intermittently and resolve just as spontaneously on less reliable networks,
|
||||||
|
* or during temporary disconnections. When the problem resolves, the connection may return to the "connected" state.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.DISCONNECTED -> {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The ICE candidate has checked all candidates pairs against one another and has failed to find compatible matches for all components of the connection.
|
||||||
|
* It is, however, possible that the ICE agent did find compatible connections for some components.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.FAILED -> {
|
||||||
|
callContext.mxCall.hangUp()
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The ICE agent has finished gathering candidates, has checked all pairs against one another, and has found a connection for all components.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.COMPLETED -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The ICE agent for this RTCPeerConnection has shut down and is no longer handling requests.
|
||||||
|
*/
|
||||||
|
PeerConnection.IceConnectionState.CLOSED -> {
|
||||||
|
|
||||||
}
|
}
|
||||||
PeerConnection.IceConnectionState.FAILED -> Timber.v("## VOIP StreamObserver onIceConnectionChange.FAILED")
|
|
||||||
else -> Timber.v("## VOIP StreamObserver onIceConnectionChange.$newState")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +669,12 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||||||
Timber.v("## VOIP StreamObserver onAddStream: $stream")
|
Timber.v("## VOIP StreamObserver onAddStream: $stream")
|
||||||
executor.execute {
|
executor.execute {
|
||||||
// reportError("Weird-looking stream: " + stream);
|
// reportError("Weird-looking stream: " + stream);
|
||||||
if (stream.audioTracks.size > 1 || stream.videoTracks.size > 1) return@execute
|
if (stream.audioTracks.size > 1 || stream.videoTracks.size > 1) {
|
||||||
|
Timber.e("## VOIP StreamObserver weird looking stream: $stream")
|
||||||
|
//TODO maybe do something more??
|
||||||
|
callContext.mxCall.hangUp()
|
||||||
|
return@execute
|
||||||
|
}
|
||||||
|
|
||||||
if (stream.videoTracks.size == 1) {
|
if (stream.videoTracks.size == 1) {
|
||||||
val remoteVideoTrack = stream.videoTracks.first()
|
val remoteVideoTrack = stream.videoTracks.first()
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/incomingRingingControls"
|
android:id="@+id/ringingControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user