diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt index 145ec8cbbe..f9e3a2dbde 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt @@ -1,10 +1,12 @@ package org.thoughtcrime.securesms.calls +import android.Manifest import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.os.Bundle +import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import kotlinx.android.synthetic.main.activity_webrtc_tests.* import kotlinx.coroutines.delay @@ -18,6 +20,7 @@ import org.session.libsession.utilities.Debouncer import org.session.libsignal.protos.SignalServiceProtos import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity +import org.thoughtcrime.securesms.permissions.Permissions import org.webrtc.* @@ -63,6 +66,26 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection private val candidates: MutableList = mutableListOf() private val iceDebouncer = Debouncer(2_000) + private var localCandidateType: String? = null + set(value) { + field = value + if (value != null) { + // show it + local_candidate_info.isVisible = true + local_candidate_info.text = "local: $value" + } + } + + private var remoteCandidateType: String? = null + set(value) { + field = value + if (value != null) { + remote_candidate_info.isVisible = true + remote_candidate_info.text = "remote: $value" + } + // update text + } + private lateinit var callAddress: Address private val peerConnection by lazy { // TODO: in a lokinet world, ice servers shouldn't be needed as .loki addresses should suffice to p2p @@ -80,14 +103,20 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection super.onCreate(savedInstanceState, ready) setContentView(R.layout.activity_webrtc_tests) + //TODO: better handling of permissions + Permissions.with(this) + .request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) + .onAllGranted { + setupStreams() + } + .execute() + local_renderer.run { - setMirror(true) setEnableHardwareScaler(true) init(eglBase.eglBaseContext, null) } remote_renderer.run { - setMirror(true) setEnableHardwareScaler(true) init(eglBase.eglBaseContext, null) } @@ -104,24 +133,6 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection } - val videoSource = connectionFactory.createVideoSource(false) - - videoCapturer?.initialize(surfaceHelper, local_renderer.context, videoSource.capturerObserver) ?: run { - finish() - return - } - videoCapturer?.startCapture(HD_VIDEO_WIDTH, HD_VIDEO_HEIGHT, 10) - - val audioTrack = connectionFactory.createAudioTrack(LOCAL_TRACK_ID + "_audio", audioSource) - val videoTrack = connectionFactory.createVideoTrack(LOCAL_TRACK_ID, videoSource) - videoTrack.addSink(local_renderer) - - val stream = connectionFactory.createLocalMediaStream(LOCAL_STREAM_ID) - stream.addTrack(videoTrack) - stream.addTrack(audioTrack) - - peerConnection.addStream(stream) - // create either call or answer if (intent.action == ACTION_ANSWER) { callAddress = intent.getParcelableExtra(EXTRA_ADDRESS) ?: run { finish(); return } @@ -175,11 +186,27 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection override fun onStatsDelivered(statsReport: RTCStatsReport?) { statsReport?.let { report -> + val usedConnection = report.statsMap.filter { (_,v) -> v.type == "candidate-pair" && v.members["writable"] == true }.asIterable().firstOrNull()?.value ?: return@let + + usedConnection.members["remoteCandidateId"]?.let { candidate -> + runOnUiThread { + remoteCandidateType = report.statsMap[candidate]?.members?.get("candidateType") as? String + } + } + + usedConnection.members["localCandidateId"]?.let { candidate -> + runOnUiThread { + localCandidateType = report.statsMap[candidate]?.members?.get("candidateType") as? String + } + } + Log.d("Loki-RTC", "report is: $report") } } private fun endCall() { + if (isFinishing) return + MessageSender.sendNonDurably( CallMessage.endCall(), callAddress @@ -193,6 +220,26 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection endCall() } + private fun setupStreams() { + val videoSource = connectionFactory.createVideoSource(false) + + videoCapturer?.initialize(surfaceHelper, local_renderer.context, videoSource.capturerObserver) ?: run { + finish() + return + } + videoCapturer?.startCapture(HD_VIDEO_WIDTH, HD_VIDEO_HEIGHT, 10) + + val audioTrack = connectionFactory.createAudioTrack(LOCAL_TRACK_ID + "_audio", audioSource) + val videoTrack = connectionFactory.createVideoTrack(LOCAL_TRACK_ID, videoSource) + videoTrack.addSink(local_renderer) + + val stream = connectionFactory.createLocalMediaStream(LOCAL_STREAM_ID) + stream.addTrack(videoTrack) + stream.addTrack(audioTrack) + + peerConnection.addStream(stream) + } + private fun createCameraCapturer(enumerator: CameraEnumerator): CameraVideoCapturer? { val deviceNames = enumerator.deviceNames @@ -237,16 +284,6 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) { Log.d("Loki-RTC", "onIceGatheringChange: $p0") - p0 ?: return - Log.d("Loki-RTC","sending IceCandidates of size: ${candidates.size}") - MessageSender.sendNonDurably( - CallMessage(SignalServiceProtos.CallMessage.Type.ICE_CANDIDATES, - candidates.map { it.sdp }, - candidates.map { it.sdpMLineIndex }, - candidates.map { it.sdpMid } - ), - callAddress - ) } override fun onIceCandidate(iceCandidate: IceCandidate?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index b7d63d1500..15510b8326 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -14,6 +14,7 @@ import android.view.View import android.widget.Toast import androidx.core.os.bundleOf import androidx.core.view.isVisible +import androidx.lifecycle.Lifecycle import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope import androidx.loader.app.LoaderManager @@ -150,13 +151,15 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis when (message.type) { OFFER -> { // show bottom sheet - CallBottomSheet().apply { - arguments = bundleOf( - CallBottomSheet.ARGUMENT_ADDRESS to sender, - CallBottomSheet.ARGUMENT_SDP to message.sdps.toTypedArray(), - CallBottomSheet.ARGUMENT_TYPE to message.type!!.number - ) - show(this@HomeActivity.supportFragmentManager,"call-sheet") + if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { + CallBottomSheet().apply { + arguments = bundleOf( + CallBottomSheet.ARGUMENT_ADDRESS to sender, + CallBottomSheet.ARGUMENT_SDP to message.sdps.toTypedArray(), + CallBottomSheet.ARGUMENT_TYPE to message.type!!.number + ) + show(this@HomeActivity.supportFragmentManager,"call-sheet") + } } } END_CALL -> { diff --git a/app/src/main/res/layout/activity_webrtc_tests.xml b/app/src/main/res/layout/activity_webrtc_tests.xml index 4694b29d98..9a915e5e04 100644 --- a/app/src/main/res/layout/activity_webrtc_tests.xml +++ b/app/src/main/res/layout/activity_webrtc_tests.xml @@ -2,7 +2,42 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> + + + +