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 a62cd2aca8..0168b33e79 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcTestsActivity.kt @@ -92,13 +92,13 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection private val peerConnection by lazy { // TODO: in a lokinet world, ice servers shouldn't be needed as .loki addresses should suffice to p2p - val turn = PeerConnection.IceServer.builder("turn:freyr.getsession.org:5349").setUsername("webrtc").setPassword("webrtc").createIceServer() -// val stun = PeerConnection.IceServer.builder("stun:freyr.getsession.org").createIceServer() - val iceServers = mutableListOf(turn) + val stun = PeerConnection.IceServer.builder("stun:freyr.getsession.org:5349").setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK).createIceServer() + val turn = PeerConnection.IceServer.builder("turn:freyr.getsession.org:5349").setUsername("webrtc").setPassword("webrtc").setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK).createIceServer() + val iceServers = mutableListOf(turn, stun) val rtcConfig = PeerConnection.RTCConfiguration(iceServers).apply { this.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED this.candidateNetworkPolicy = PeerConnection.CandidateNetworkPolicy.ALL - this.iceTransportsType = PeerConnection.IceTransportsType.RELAY +// this.iceTransportsType = PeerConnection.IceTransportsType.RELAY } rtcConfig.keyType = PeerConnection.KeyType.ECDSA connectionFactory.createPeerConnection(rtcConfig, this)!! diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt index 747df0751f..78bc402294 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt @@ -8,11 +8,12 @@ import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint import org.thoughtcrime.securesms.webrtc.AudioManagerCommand import org.thoughtcrime.securesms.webrtc.CallManager +import org.thoughtcrime.securesms.webrtc.RTCAudioManager import java.util.* import javax.inject.Inject @AndroidEntryPoint -class WebRtcCallService: Service() { +class WebRtcCallService: Service(), RTCAudioManager.EventListener { @Inject lateinit var callManager: CallManager @@ -63,9 +64,24 @@ class WebRtcCallService: Service() { .putExtra(EXTRA_ENABLED, register) ContextCompat.startForegroundService(context, intent) } - } override fun onBind(intent: Intent?): IBinder? = null + override fun onCreate() { + super.onCreate() + // create audio manager + // reset call notification + // register uncaught exception handler + // register network receiver + // telephony listen to call state + } + + override fun onDestroy() { + super.onDestroy() + // unregister exception handler + // shutdown audiomanager + // unregister network receiver + // unregister power button + } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioEvent.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioEvent.kt new file mode 100644 index 0000000000..b01edfb492 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioEvent.kt @@ -0,0 +1,5 @@ +package org.thoughtcrime.securesms.webrtc + +enum class AudioEvent { + +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioManager.kt deleted file mode 100644 index d59adb9113..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/AudioManager.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.thoughtcrime.securesms.webrtc - -import android.content.Context -import android.media.AudioManager - -class RTCAudioManager(context: Context, deviceChangeListener: (currentDevice: AudioDevice?, availableDevices: Collection)->Unit) { - - enum class AudioDevice { - SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, NONE - } - - val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager - -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/RTCAudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/RTCAudioManager.kt new file mode 100644 index 0000000000..6440871ad4 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/RTCAudioManager.kt @@ -0,0 +1,24 @@ +package org.thoughtcrime.securesms.webrtc + +import android.content.Context +import android.media.AudioManager +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import org.thoughtcrime.securesms.webrtc.audio.IncomingRinger + +class RTCAudioManager(context: Context, deviceChangeListener: (currentDevice: AudioDevice?, availableDevices: Collection)->Unit) { + + enum class AudioDevice { + SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, NONE + } + + private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager + private val incomingRinger = IncomingRinger(context) + + private val stateChannel = Channel() + + interface EventListener { + fun onAudioDeviceChanged(activeDevice: AudioDevice, devices: Set) + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/IncomingRinger.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/IncomingRinger.kt new file mode 100644 index 0000000000..86acba6a4b --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/IncomingRinger.kt @@ -0,0 +1,90 @@ +package org.thoughtcrime.securesms.webrtc.audio + +import android.content.Context +import android.media.AudioManager +import android.media.MediaPlayer +import android.media.RingtoneManager +import android.os.Vibrator +import org.session.libsignal.utilities.Log + +class IncomingRinger(private val context: Context) { + companion object { + const val TAG = "IncomingRinger" + val PATTERN = longArrayOf(0L, 1000L, 1000L) + } + + private val vibrator: Vibrator? = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator? + var mediaPlayer: MediaPlayer? = null + + fun start(vibrate: Boolean) { + val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager + mediaPlayer?.release() + mediaPlayer = createMediaPlayer() + val ringerMode = audioManager.ringerMode + + if (shouldVibrate(mediaPlayer, ringerMode, vibrate)) { + Log.i(TAG,"Starting vibration") + vibrator?.vibrate(PATTERN, 1) + } else { + Log.i(TAG,"Skipping vibration") + } + + mediaPlayer?.let { player -> + if (ringerMode == AudioManager.RINGER_MODE_NORMAL) { + try { + if (!player.isPlaying) { + player.prepare() + player.start() + Log.i(TAG,"Playing ringtone") + } + } catch (e: Exception) { + Log.e(TAG,"Failed to start mediaPlayer", e) + } + } + } ?: run { + Log.w(TAG,"Not ringing, mediaPlayer: ${mediaPlayer?.let{"available"}}, mode: $ringerMode") + } + + } + + fun stop() { + mediaPlayer?.release() + mediaPlayer = null + vibrator?.cancel() + } + + private fun shouldVibrate(player: MediaPlayer?, ringerMode: Int, vibrate: Boolean): Boolean { + player ?: return true + + if (vibrator == null || !vibrator.hasVibrator()) return false + + return if (vibrate) ringerMode != AudioManager.RINGER_MODE_SILENT + else ringerMode == AudioManager.RINGER_MODE_VIBRATE + } + + fun createMediaPlayer(): MediaPlayer? { + try { + val defaultRingtone = try { + RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE) + } catch (e: Exception) { + Log.e(TAG, "Failed to get default system ringtone", e) + null + } ?: return null + + try { + val mediaPlayer = MediaPlayer() + mediaPlayer.setDataSource(context, defaultRingtone) + return mediaPlayer + } catch (e: SecurityException) { + Log.w(TAG, "Failed to create player with ringtone the normal way", e) + } + } catch (e: Exception) { + Log.e(TAG,"Failed to create mediaPlayer") + } + + return null + } + + + +} \ No newline at end of file