diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt index d059f2633..e5227d552 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt @@ -141,7 +141,6 @@ import com.nextcloud.talk.webrtc.PeerConnectionWrapper import com.nextcloud.talk.webrtc.PeerConnectionWrapper.PeerConnectionObserver import com.nextcloud.talk.webrtc.WebRtcAudioManager import com.nextcloud.talk.webrtc.WebRtcAudioManager.AudioDevice -import com.nextcloud.talk.webrtc.WebRtcAudioManager.AudioManagerListener import com.nextcloud.talk.webrtc.WebSocketConnectionHelper import com.nextcloud.talk.webrtc.WebSocketInstance import com.wooplr.spotlight.SpotlightView @@ -183,6 +182,7 @@ import javax.inject.Inject import kotlin.math.roundToInt @AutoInjector(NextcloudTalkApplication::class) +@Suppress("TooManyFunctions") class CallActivity : CallBaseActivity() { @JvmField @Inject @@ -348,7 +348,7 @@ class CallActivity : CallBaseActivity() { } } } - if (!rationaleList.isEmpty()) { + if (rationaleList.isNotEmpty()) { showRationaleDialogForSettings(rationaleList) } } @@ -404,7 +404,7 @@ class CallActivity : CallBaseActivity() { binding!!.lowerHandButton.visibility = View.GONE raised = false } - if (isConnectionEstablished && peerConnectionWrapperList != null) { + if (isConnectionEstablished) { for (peerConnectionWrapper in peerConnectionWrapperList) { peerConnectionWrapper.raiseHand(raised) } @@ -436,12 +436,12 @@ class CallActivity : CallBaseActivity() { val dialogBuilder = MaterialAlertDialogBuilder(this) .setTitle(R.string.record_stop_confirm_title) .setMessage(R.string.record_stop_confirm_message) - .setPositiveButton( - R.string.record_stop_description - ) { dialog: DialogInterface?, which: Int -> callRecordingViewModel!!.stopRecording() } - .setNegativeButton( - R.string.nc_common_dismiss - ) { dialog: DialogInterface?, which: Int -> callRecordingViewModel!!.dismissStopRecording() } + .setPositiveButton(R.string.record_stop_description) { _: DialogInterface?, _: Int -> + callRecordingViewModel!!.stopRecording() + } + .setNegativeButton(R.string.nc_common_dismiss) { _: DialogInterface?, _: Int -> + callRecordingViewModel!!.dismissStopRecording() + } viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder) val dialog = dialogBuilder.show() viewThemeUtils.platform.colorTextButtons( @@ -483,7 +483,7 @@ class CallActivity : CallBaseActivity() { fun sendReaction(emoji: String?) { addReactionForAnimation(emoji, conversationUser!!.displayName) - if (isConnectionEstablished && peerConnectionWrapperList != null) { + if (isConnectionEstablished) { for (peerConnectionWrapper in peerConnectionWrapperList) { peerConnectionWrapper.sendReaction(emoji) } @@ -521,18 +521,21 @@ class CallActivity : CallBaseActivity() { } private fun initClickListeners() { - binding!!.pictureInPictureButton.setOnClickListener { l: View? -> enterPipMode() } - binding!!.audioOutputButton.setOnClickListener { v: View? -> + binding!!.pictureInPictureButton.setOnClickListener { enterPipMode() } + + binding!!.audioOutputButton.setOnClickListener { audioOutputDialog = AudioOutputDialog(this) audioOutputDialog!!.show() } - binding!!.moreCallActions.setOnClickListener { v: View? -> + + binding!!.moreCallActions.setOnClickListener { moreCallActionsDialog = MoreCallActionsDialog(this) moreCallActionsDialog!!.show() } + if (canPublishAudioStream) { - binding!!.microphoneButton.setOnClickListener { l: View? -> onMicrophoneClick() } - binding!!.microphoneButton.setOnLongClickListener { l: View? -> + binding!!.microphoneButton.setOnClickListener { onMicrophoneClick() } + binding!!.microphoneButton.setOnLongClickListener { if (!microphoneOn) { callControlHandler.removeCallbacksAndMessages(null) callInfosHandler.removeCallbacksAndMessages(null) @@ -547,7 +550,7 @@ class CallActivity : CallBaseActivity() { true } } else { - binding!!.microphoneButton.setOnClickListener { l: View? -> + binding!!.microphoneButton.setOnClickListener { Toast.makeText( context, R.string.nc_not_allowed_to_activate_audio, @@ -555,10 +558,11 @@ class CallActivity : CallBaseActivity() { ).show() } } + if (canPublishVideoStream) { - binding!!.cameraButton.setOnClickListener { l: View? -> onCameraClick() } + binding!!.cameraButton.setOnClickListener { onCameraClick() } } else { - binding!!.cameraButton.setOnClickListener { l: View? -> + binding!!.cameraButton.setOnClickListener { Toast.makeText( context, R.string.nc_not_allowed_to_activate_video, @@ -566,22 +570,22 @@ class CallActivity : CallBaseActivity() { ).show() } } - binding!!.hangupButton.setOnClickListener { l: View? -> hangup(true) } - binding!!.switchSelfVideoButton.setOnClickListener { l: View? -> switchCamera() } + binding!!.hangupButton.setOnClickListener { hangup(true) } + binding!!.switchSelfVideoButton.setOnClickListener { switchCamera() } binding!!.gridview.onItemClickListener = - AdapterView.OnItemClickListener { parent: AdapterView<*>?, view: View?, position: Int, id: Long -> + AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, _: Long -> animateCallControls( true, 0 ) } - binding!!.callStates.callStateRelativeLayout.setOnClickListener { l: View? -> + binding!!.callStates.callStateRelativeLayout.setOnClickListener { if (currentCallStatus === CallStatus.CALLING_TIMEOUT) { setCallState(CallStatus.RECONNECTING) hangupNetworkCalls(false) } } - binding!!.callRecordingIndicator.setOnClickListener { l: View? -> + binding!!.callRecordingIndicator.setOnClickListener { if (isAllowedToStartOrStopRecording) { if (callRecordingViewModel!!.viewState.value is RecordingStartingState) { if (moreCallActionsDialog == null) { @@ -644,14 +648,12 @@ class CallActivity : CallBaseActivity() { // Store existing audio settings and change audio mode to // MODE_IN_COMMUNICATION for best possible VoIP performance. Log.d(TAG, "Starting the audio manager...") - audioManager!!.start( - AudioManagerListener { currentDevice: AudioDevice, availableDevices: Set -> - onAudioManagerDevicesChanged( - currentDevice, - availableDevices - ) - } - ) + audioManager!!.start { currentDevice: AudioDevice, availableDevices: Set -> + onAudioManagerDevicesChanged( + currentDevice, + availableDevices + ) + } if (isVoiceOnlyCall) { setAudioOutputChannel(AudioDevice.EARPIECE) } else { @@ -776,14 +778,14 @@ class CallActivity : CallBaseActivity() { } initSelfVideoView() } - binding!!.gridview.setOnTouchListener { v, me -> + binding!!.gridview.setOnTouchListener { _, me -> val action = me.actionMasked if (action == MotionEvent.ACTION_DOWN) { animateCallControls(true, 0) } false } - binding!!.conversationRelativeLayout.setOnTouchListener { v, me -> + binding!!.conversationRelativeLayout.setOnTouchListener { _, me -> val action = me.actionMasked if (action == MotionEvent.ACTION_DOWN) { animateCallControls(true, 0) @@ -881,7 +883,7 @@ class CallActivity : CallBaseActivity() { if (!videoOn) { onCameraClick() } - if (cameraEnumerator!!.deviceNames.size == 0) { + if (cameraEnumerator!!.deviceNames.isEmpty()) { binding!!.cameraButton.visibility = View.GONE } if (cameraEnumerator!!.deviceNames.size > 1) { @@ -904,8 +906,8 @@ class CallActivity : CallBaseActivity() { permissionsToRequest.add(Manifest.permission.BLUETOOTH_CONNECT) } } - if (!permissionsToRequest.isEmpty()) { - if (!rationaleList.isEmpty()) { + if (permissionsToRequest.isNotEmpty()) { + if (rationaleList.isNotEmpty()) { showRationaleDialog(permissionsToRequest, rationaleList) } else { requestPermissionLauncher.launch(permissionsToRequest.toTypedArray()) @@ -932,12 +934,8 @@ class CallActivity : CallBaseActivity() { val dialogBuilder = MaterialAlertDialogBuilder(this) .setTitle(R.string.nc_permissions_rationale_dialog_title) .setMessage(rationalesWithLineBreaks) - .setPositiveButton( - R.string.nc_permissions_ask - ) { dialog: DialogInterface?, which: Int -> - requestPermissionLauncher.launch( - permissionsToRequest.toTypedArray() - ) + .setPositiveButton(R.string.nc_permissions_ask) { _, _ -> + requestPermissionLauncher.launch(permissionsToRequest.toTypedArray()) } .setNegativeButton(R.string.nc_common_dismiss, null) viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder) @@ -956,7 +954,7 @@ class CallActivity : CallBaseActivity() { val dialogBuilder = MaterialAlertDialogBuilder(this) .setTitle(R.string.nc_permissions_rationale_dialog_title) .setMessage(rationalesWithLineBreaks) - .setPositiveButton(R.string.nc_permissions_settings) { dialog: DialogInterface?, which: Int -> + .setPositiveButton(R.string.nc_permissions_settings) { _, _ -> val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) intent.data = Uri.fromParts("package", packageName, null) startActivity(intent) @@ -973,11 +971,7 @@ class CallActivity : CallBaseActivity() { currentDevice: AudioDevice, availableDevices: Set ) { - Log.d( - TAG, - "onAudioManagerDevicesChanged: " + availableDevices + ", " + - "currentDevice: " + currentDevice - ) + Log.d(TAG, "onAudioManagerDevicesChanged: $availableDevices, currentDevice: $currentDevice") val shouldDisableProximityLock = currentDevice == AudioDevice.WIRED_HEADSET || currentDevice == AudioDevice.SPEAKER_PHONE || @@ -1065,26 +1059,7 @@ class CallActivity : CallBaseActivity() { } if (permissionUtil!!.isMicrophonePermissionGranted()) { if (!appPreferences.pushToTalkIntroShown) { - val primary = viewThemeUtils.getScheme(binding!!.audioOutputButton.context).primary - spotlightView = SpotlightView.Builder(this) - .introAnimationDuration(300) - .enableRevealAnimation(true) - .performClick(false) - .fadeinTextDuration(400) - .headingTvColor(primary) - .headingTvSize(20) - .headingTvText(resources.getString(R.string.nc_push_to_talk)) - .subHeadingTvColor(resources.getColor(R.color.bg_default, null)) - .subHeadingTvSize(16) - .subHeadingTvText(resources.getString(R.string.nc_push_to_talk_desc)) - .maskColor(Color.parseColor("#dc000000")) - .target(binding!!.microphoneButton) - .lineAnimDuration(400) - .lineAndArcColor(primary) - .enableDismissAfterShown(true) - .dismissOnBackPress(true) - .usageId("pushToTalk") - .show() + spotlightView = getSpotlightView() appPreferences.pushToTalkIntroShown = true } if (!isPushToTalkActive) { @@ -1120,7 +1095,30 @@ class CallActivity : CallBaseActivity() { } } - fun onCameraClick() { + private fun getSpotlightView(): SpotlightView? { + val primary = viewThemeUtils.getScheme(binding!!.audioOutputButton.context).primary + return SpotlightView.Builder(this) + .introAnimationDuration(300) + .enableRevealAnimation(true) + .performClick(false) + .fadeinTextDuration(400) + .headingTvColor(primary) + .headingTvSize(20) + .headingTvText(resources.getString(R.string.nc_push_to_talk)) + .subHeadingTvColor(resources.getColor(R.color.bg_default, null)) + .subHeadingTvSize(16) + .subHeadingTvText(resources.getString(R.string.nc_push_to_talk_desc)) + .maskColor(Color.parseColor("#dc000000")) + .target(binding!!.microphoneButton) + .lineAnimDuration(400) + .lineAndArcColor(primary) + .enableDismissAfterShown(true) + .dismissOnBackPress(true) + .usageId("pushToTalk") + .show() + } + + private fun onCameraClick() { if (!canPublishVideoStream) { videoOn = false binding!!.cameraButton.setImageResource(R.drawable.ic_videocam_off_white_24px) @@ -1156,7 +1154,9 @@ class CallActivity : CallBaseActivity() { binding!!.selfVideoRenderer.setMirror(currentCameraIsFront) } - override fun onCameraSwitchError(s: String) {} + override fun onCameraSwitchError(s: String) { + Log.e(TAG, "Error while switching camera: $s") + } }) } @@ -1198,7 +1198,7 @@ class CallActivity : CallBaseActivity() { localStream!!.audioTracks[0].setEnabled(enable) } } - if (isConnectionEstablished && peerConnectionWrapperList != null) { + if (isConnectionEstablished) { if (!hasMCU) { for (peerConnectionWrapper in peerConnectionWrapperList) { peerConnectionWrapper.sendChannelData(DataChannelMessage(message)) @@ -1348,12 +1348,8 @@ class CallActivity : CallBaseActivity() { signalingSettingsOverall.ocs!!.settings != null ) { externalSignalingServer = ExternalSignalingServer() - if (!TextUtils.isEmpty( - signalingSettingsOverall.ocs!!.settings!!.externalSignalingServer - ) && - !TextUtils.isEmpty( - signalingSettingsOverall.ocs!!.settings!!.externalSignalingTicket - ) + if (!TextUtils.isEmpty(signalingSettingsOverall.ocs!!.settings!!.externalSignalingServer) && + !TextUtils.isEmpty(signalingSettingsOverall.ocs!!.settings!!.externalSignalingTicket) ) { externalSignalingServer = ExternalSignalingServer() externalSignalingServer!!.externalSignalingServer = @@ -1365,6 +1361,7 @@ class CallActivity : CallBaseActivity() { hasExternalSignalingServer = false } Log.d(TAG, " hasExternalSignalingServer: $hasExternalSignalingServer") + if ("?" != conversationUser!!.userId && conversationUser!!.id != null) { Log.d( TAG, @@ -1380,43 +1377,8 @@ class CallActivity : CallBaseActivity() { } else { conversationUser!!.externalSignalingServer = externalSignalingServer } - if (signalingSettingsOverall.ocs!!.settings!!.stunServers != null) { - val stunServers = signalingSettingsOverall.ocs!!.settings!!.stunServers - if (apiVersion == ApiUtils.APIv3) { - for ((_, urls) in stunServers!!) { - if (urls != null) { - for (url in urls) { - Log.d(TAG, " STUN server url: $url") - iceServers!!.add(PeerConnection.IceServer(url)) - } - } - } - } else { - if (signalingSettingsOverall.ocs!!.settings!!.stunServers != null) { - for ((url) in stunServers!!) { - Log.d(TAG, " STUN server url: $url") - iceServers!!.add(PeerConnection.IceServer(url)) - } - } - } - } - if (signalingSettingsOverall.ocs!!.settings!!.turnServers != null) { - val turnServers = signalingSettingsOverall.ocs!!.settings!!.turnServers - for ((_, urls, username, credential) in turnServers!!) { - if (urls != null) { - for (url in urls) { - Log.d(TAG, " TURN server url: $url") - iceServers!!.add( - PeerConnection.IceServer( - url, - username, - credential - ) - ) - } - } - } - } + + addIceServers(signalingSettingsOverall, apiVersion) } checkCapabilities() } @@ -1431,6 +1393,44 @@ class CallActivity : CallBaseActivity() { }) } + private fun addIceServers( + signalingSettingsOverall: SignalingSettingsOverall, + apiVersion: Int + ) { + if (signalingSettingsOverall.ocs!!.settings!!.stunServers != null) { + val stunServers = signalingSettingsOverall.ocs!!.settings!!.stunServers + if (apiVersion == ApiUtils.APIv3) { + for ((_, urls) in stunServers!!) { + if (urls != null) { + for (url in urls) { + Log.d(TAG, " STUN server url: $url") + iceServers!!.add(PeerConnection.IceServer(url)) + } + } + } + } else { + if (signalingSettingsOverall.ocs!!.settings!!.stunServers != null) { + for ((url) in stunServers!!) { + Log.d(TAG, " STUN server url: $url") + iceServers!!.add(PeerConnection.IceServer(url)) + } + } + } + } + + if (signalingSettingsOverall.ocs!!.settings!!.turnServers != null) { + val turnServers = signalingSettingsOverall.ocs!!.settings!!.turnServers + for ((_, urls, username, credential) in turnServers!!) { + if (urls != null) { + for (url in urls) { + Log.d(TAG, " TURN server url: $url") + iceServers!!.add(PeerConnection.IceServer(url, username, credential)) + } + } + } + } + } + private fun checkCapabilities() { ncApi!!.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl)) .retry(3) @@ -1527,6 +1527,7 @@ class CallActivity : CallBaseActivity() { } callParticipantList = CallParticipantList(signalingMessageReceiver) callParticipantList!!.addObserver(callParticipantListObserver) + val apiVersion = ApiUtils.getCallApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1)) ncApi!!.joinCall( credentials, @@ -1557,55 +1558,7 @@ class CallActivity : CallBaseActivity() { ) } if (!hasExternalSignalingServer) { - val signalingApiVersion = - ApiUtils.getSignalingApiVersion(conversationUser, intArrayOf(ApiUtils.APIv3, 2, 1)) - val delayOnError = AtomicInteger(0) - ncApi!!.pullSignalingMessages( - credentials, - ApiUtils.getUrlForSignaling( - signalingApiVersion, - baseUrl, - roomToken - ) - ) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .repeatWhen { observable: Observable? -> observable } - .takeWhile { isConnectionEstablished } - .doOnNext { delayOnError.set(0) } - .retryWhen { errors: Observable -> - errors - .flatMap { error: Throwable? -> - if (!isConnectionEstablished) { - return@flatMap Observable.error(error) - } - if (delayOnError.get() == 0) { - delayOnError.set(1) - } else if (delayOnError.get() < 16) { - delayOnError.set(delayOnError.get() * 2) - } - Observable.timer(delayOnError.get().toLong(), TimeUnit.SECONDS) - } - } - .subscribe(object : Observer { - override fun onSubscribe(d: Disposable) { - signalingDisposable = d - } - - override fun onNext( - signalingOverall: SignalingOverall - ) { - receivedSignalingMessages(signalingOverall.ocs!!.signalings) - } - - override fun onError(e: Throwable) { - dispose(signalingDisposable) - } - - override fun onComplete() { - dispose(signalingDisposable) - } - }) + pullSignalingMessages() } } } @@ -1620,6 +1573,55 @@ class CallActivity : CallBaseActivity() { }) } + private fun pullSignalingMessages() { + val signalingApiVersion = ApiUtils.getSignalingApiVersion(conversationUser, intArrayOf(ApiUtils.APIv3, 2, 1)) + val delayOnError = AtomicInteger(0) + + ncApi!!.pullSignalingMessages( + credentials, + ApiUtils.getUrlForSignaling( + signalingApiVersion, + baseUrl, + roomToken + ) + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .repeatWhen { observable: Observable? -> observable } + .takeWhile { isConnectionEstablished } + .doOnNext { delayOnError.set(0) } + .retryWhen { errors: Observable -> + errors.flatMap { error: Throwable? -> + if (!isConnectionEstablished) { + return@flatMap Observable.error(error) + } + if (delayOnError.get() == 0) { + delayOnError.set(1) + } else if (delayOnError.get() < 16) { + delayOnError.set(delayOnError.get() * 2) + } + Observable.timer(delayOnError.get().toLong(), TimeUnit.SECONDS) + } + } + .subscribe(object : Observer { + override fun onSubscribe(d: Disposable) { + signalingDisposable = d + } + + override fun onNext(signalingOverall: SignalingOverall) { + receivedSignalingMessages(signalingOverall.ocs!!.signalings) + } + + override fun onError(e: Throwable) { + dispose(signalingDisposable) + } + + override fun onComplete() { + dispose(signalingDisposable) + } + }) + } + private fun setupAndInitiateWebSocketsConnection() { if (webSocketConnectionHelper == null) { webSocketConnectionHelper = WebSocketConnectionHelper() @@ -1722,16 +1724,21 @@ class CallActivity : CallBaseActivity() { if (!isConnectionEstablished && currentCallStatus !== CallStatus.CONNECTING) { return } - if ("usersInRoom" == messageType) { - internalSignalingMessageReceiver.process(signaling.messageWrapper as List?>?) - } else if ("message" == messageType) { - val ncSignalingMessage = LoganSquare.parse( - signaling.messageWrapper.toString(), - NCSignalingMessage::class.java - ) - internalSignalingMessageReceiver.process(ncSignalingMessage) - } else { - Log.e(TAG, "unexpected message type when receiving signaling message") + + when (messageType) { + "usersInRoom" -> + internalSignalingMessageReceiver.process(signaling.messageWrapper as List?>?) + + "message" -> { + val ncSignalingMessage = LoganSquare.parse( + signaling.messageWrapper.toString(), + NCSignalingMessage::class.java + ) + internalSignalingMessageReceiver.process(ncSignalingMessage) + } + + else -> + Log.e(TAG, "unexpected message type when receiving signaling message") } } @@ -1742,6 +1749,7 @@ class CallActivity : CallBaseActivity() { } stopCallingSound() dispose(null) + if (shutDownView) { if (videoCapturer != null) { try { @@ -1775,25 +1783,27 @@ class CallActivity : CallBaseActivity() { WebSocketConnectionHelper.deleteExternalSignalingInstanceForUserEntity(-1) } } - val peerConnectionIdsToEnd: MutableList = ArrayList( - peerConnectionWrapperList!!.size - ) + + val peerConnectionIdsToEnd: MutableList = ArrayList(peerConnectionWrapperList.size) + for (wrapper in peerConnectionWrapperList) { peerConnectionIdsToEnd.add(wrapper.sessionId) } + for (sessionId in peerConnectionIdsToEnd) { endPeerConnection(sessionId, "video") endPeerConnection(sessionId, "screen") } - val callParticipantIdsToEnd: MutableList = ArrayList( - peerConnectionWrapperList.size - ) + + val callParticipantIdsToEnd: MutableList = ArrayList(peerConnectionWrapperList.size) for (callParticipant in callParticipants.values) { callParticipantIdsToEnd.add(callParticipant!!.callParticipantModel.sessionId) } + for (sessionId in callParticipantIdsToEnd) { removeCallParticipant(sessionId) } + ApplicationWideCurrentRoomHolder.getInstance().isInCall = false ApplicationWideCurrentRoomHolder.getInstance().isDialing = false hangupNetworkCalls(shutDownView) @@ -1851,6 +1861,7 @@ class CallActivity : CallBaseActivity() { } } + @Suppress("Detekt.ComplexMethod") private fun handleCallParticipantsChanged( joined: Collection, updated: Collection, @@ -1867,12 +1878,15 @@ class CallActivity : CallBaseActivity() { currentSessionId = webSocketClient!!.sessionId } Log.d(TAG, " currentSessionId is $currentSessionId") + val participantsInCall: MutableList = ArrayList() participantsInCall.addAll(joined) participantsInCall.addAll(updated) participantsInCall.addAll(unchanged) + var isSelfInCall = false var selfParticipant: Participant? = null + for (participant in participantsInCall) { val inCallFlag = participant.inCall if (participant.sessionId != currentSessionId) { @@ -1889,6 +1903,7 @@ class CallActivity : CallBaseActivity() { selfParticipant = participant } } + if (!isSelfInCall && currentCallStatus !== CallStatus.LEAVING && ApplicationWideCurrentRoomHolder.getInstance().isInCall @@ -1897,6 +1912,7 @@ class CallActivity : CallBaseActivity() { hangup(true) return } + if (!isSelfInCall) { Log.d(TAG, "Self not in call, disconnecting from all other sessions") for ((_, _, _, _, _, _, _, _, _, _, sessionId) in participantsInCall) { @@ -1932,19 +1948,22 @@ class CallActivity : CallBaseActivity() { } Log.d(TAG, " newSession joined: $sessionId") addCallParticipant(sessionId) + val userId = participant.userId if (userId != null) { callParticipants[sessionId]!!.setUserId(userId) } + if (participant.internal != null) { callParticipants[sessionId]!!.setInternal(participant.internal) } - var nick: String? - nick = if (hasExternalSignalingServer) { + + val nick: String? = if (hasExternalSignalingServer) { webSocketClient!!.getDisplayNameForSession(sessionId) } else { if (offerAnswerNickProviders[sessionId] != null) offerAnswerNickProviders[sessionId]?.nick else "" } + callParticipants[sessionId]!!.setNick(nick) val participantHasAudioOrVideo = participantInCallFlagsHaveAudioOrVideo(participant) @@ -1952,16 +1971,14 @@ class CallActivity : CallBaseActivity() { // remote session ID. However, if the other participant does not have audio nor video that participant // will not send an offer, so no connection is actually established when the remote participant has a // higher session ID but is not publishing media. - if (hasMCU && participantHasAudioOrVideo || !hasMCU && selfParticipantHasAudioOrVideo && ( - !participantHasAudioOrVideo || sessionId.compareTo( - currentSessionId!! - ) < 0 - ) + if (hasMCU && participantHasAudioOrVideo || + !hasMCU && selfParticipantHasAudioOrVideo && + (!participantHasAudioOrVideo || sessionId < currentSessionId!!) ) { getOrCreatePeerConnectionWrapperForSessionIdAndType(sessionId, VIDEO_STREAM_TYPE_VIDEO, false) } } - val othersInCall = if (selfJoined) joined.size > 1 else joined.size > 0 + val othersInCall = if (selfJoined) joined.size > 1 else joined.isNotEmpty() if (othersInCall && currentCallStatus !== CallStatus.IN_CONVERSATION) { setCallState(CallStatus.IN_CONVERSATION) } @@ -1984,7 +2001,7 @@ class CallActivity : CallBaseActivity() { } private fun getPeerConnectionWrapperForSessionIdAndType(sessionId: String?, type: String): PeerConnectionWrapper? { - for (wrapper in peerConnectionWrapperList!!) { + for (wrapper in peerConnectionWrapperList) { if (wrapper.sessionId == sessionId && wrapper.videoStreamType == type) { return wrapper } @@ -2072,7 +2089,7 @@ class CallActivity : CallBaseActivity() { ) } } - peerConnectionWrapperList!!.add(peerConnectionWrapper) + peerConnectionWrapperList.add(peerConnectionWrapper) if (!publisher) { var callParticipant = callParticipants[sessionId] if (callParticipant == null) { @@ -2144,7 +2161,7 @@ class CallActivity : CallBaseActivity() { } } peerConnectionWrapper.removePeerConnection() - peerConnectionWrapperList!!.remove(peerConnectionWrapper) + peerConnectionWrapperList.remove(peerConnectionWrapper) } private fun removeCallParticipant(sessionId: String?) { @@ -2202,8 +2219,7 @@ class CallActivity : CallBaseActivity() { val screenWidthPx = displayMetrics.widthPixels val screenWidthDp = DisplayUtils.convertPixelToDp(screenWidthPx.toFloat(), applicationContext).toInt() var newXafterRotate = 0f - val newYafterRotate: Float - newYafterRotate = if (binding!!.callInfosLinearLayout.visibility == View.VISIBLE) { + val newYafterRotate: Float = if (binding!!.callInfosLinearLayout.visibility == View.VISIBLE) { 250f } else { 20f @@ -2247,7 +2263,7 @@ class CallActivity : CallBaseActivity() { nickChangedPayload["userid"] = conversationUser!!.userId!! nickChangedPayload["name"] = conversationUser!!.displayName!! dataChannelMessage.payloadMap = nickChangedPayload.toMap() - for (peerConnectionWrapper in peerConnectionWrapperList!!) { + for (peerConnectionWrapper in peerConnectionWrapperList) { if (peerConnectionWrapper.isMCUPublisher) { Observable .interval(1, TimeUnit.SECONDS) @@ -2455,14 +2471,12 @@ class CallActivity : CallBaseActivity() { binding!!.callStates.errorImageView.visibility = View.GONE } } - - else -> {} } } } private val descriptionForCallType: String - private get() { + get() { val appName = resources.getString(R.string.nc_app_product_name) return if (isVoiceOnlyCall) { String.format(resources.getString(R.string.nc_call_voice), appName) @@ -2473,14 +2487,10 @@ class CallActivity : CallBaseActivity() { private fun playCallingSound() { stopCallingSound() - val ringtoneUri: Uri? - ringtoneUri = if (isIncomingCallFromNotification) { + val ringtoneUri: Uri? = if (isIncomingCallFromNotification) { getCallRingtoneUri(applicationContext, appPreferences) } else { - Uri.parse( - "android.resource://" + applicationContext.packageName + "/raw" + - "/tr110_1_kap8_3_freiton1" - ) + Uri.parse("android.resource://" + applicationContext.packageName + "/raw/tr110_1_kap8_3_freiton1") } if (ringtoneUri != null) { mediaPlayer = MediaPlayer() @@ -2554,8 +2564,13 @@ class CallActivity : CallBaseActivity() { onOfferOrAnswer(nick) } - override fun onCandidate(sdpMid: String, sdpMLineIndex: Int, sdp: String) {} - override fun onEndOfCandidates() {} + override fun onCandidate(sdpMid: String, sdpMLineIndex: Int, sdp: String) { + // unused atm + } + + override fun onEndOfCandidates() { + // unused atm + } } private fun onOfferOrAnswer(nick: String) { @@ -2568,16 +2583,28 @@ class CallActivity : CallBaseActivity() { private inner class CallActivityCallParticipantMessageListener(private val sessionId: String?) : CallParticipantMessageListener { - override fun onRaiseHand(state: Boolean, timestamp: Long) {} - override fun onReaction(reaction: String) {} + override fun onRaiseHand(state: Boolean, timestamp: Long) { + // unused atm + } + + override fun onReaction(reaction: String) { + // unused atm + } + override fun onUnshareScreen() { endPeerConnection(sessionId, "screen") } } private inner class CallActivitySelfPeerConnectionObserver : PeerConnectionObserver { - override fun onStreamAdded(mediaStream: MediaStream) {} - override fun onStreamRemoved(mediaStream: MediaStream) {} + override fun onStreamAdded(mediaStream: MediaStream) { + // unused atm + } + + override fun onStreamRemoved(mediaStream: MediaStream) { + // unused atm + } + override fun onIceConnectionStateChanged(iceConnectionState: IceConnectionState) { runOnUiThread { updateSelfVideoViewIceConnectionState(iceConnectionState) @@ -2604,7 +2631,9 @@ class CallActivity : CallBaseActivity() { } } - override fun onReaction(reaction: String) {} + override fun onReaction(reaction: String) { + // unused atm + } } private inner class CallParticipantEventDisplayer(private val callParticipantModel: CallParticipantModel) : @@ -2640,8 +2669,7 @@ class CallActivity : CallBaseActivity() { private inner class InternalSignalingMessageSender : SignalingMessageSender { override fun send(ncSignalingMessage: NCSignalingMessage) { addLocalParticipantNickIfNeeded(ncSignalingMessage) - val serializedNcSignalingMessage: String - serializedNcSignalingMessage = try { + val serializedNcSignalingMessage: String = try { LoganSquare.serialize(ncSignalingMessage) } catch (e: IOException) { Log.e(TAG, "Failed to serialize signaling message", e) @@ -2686,7 +2714,9 @@ class CallActivity : CallBaseActivity() { Log.e(TAG, "", e) } - override fun onComplete() {} + override fun onComplete() { + // unused atm + } }) } @@ -2772,7 +2802,7 @@ class CallActivity : CallBaseActivity() { } } - fun updatePictureInPictureActions( + private fun updatePictureInPictureActions( @DrawableRes iconId: Int, title: String?, requestCode: Int @@ -2780,8 +2810,7 @@ class CallActivity : CallBaseActivity() { if (isGreaterEqualOreo && isPipModePossible) { val actions = ArrayList() val icon = Icon.createWithResource(this, iconId) - val intentFlag: Int - intentFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val intentFlag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.FLAG_IMMUTABLE } else { 0 @@ -2869,7 +2898,8 @@ class CallActivity : CallBaseActivity() { companion object { var active = false - const val VIDEO_STREAM_TYPE_SCREEN = "screen" + + // const val VIDEO_STREAM_TYPE_SCREEN = "screen" const val VIDEO_STREAM_TYPE_VIDEO = "video" const val TAG = "CallActivity" private val PERMISSIONS_CAMERA = arrayOf(