| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1,6 +1,5 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				package org.thoughtcrime.securesms.service
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.app.ForegroundServiceStartNotAllowedException
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.BroadcastReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.Context
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.Intent
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -10,11 +9,11 @@ import android.content.IntentFilter
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.pm.PackageManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.media.AudioManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.os.Build
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.os.IBinder
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.os.ResultReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.telephony.PhoneStateListener
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.telephony.PhoneStateListener.LISTEN_NONE
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.telephony.TelephonyManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import androidx.annotation.RequiresApi
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import androidx.core.content.ContextCompat
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import androidx.core.os.bundleOf
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import androidx.lifecycle.LifecycleService
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -34,13 +33,31 @@ import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_IN
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_INCOMING_PRE_OFFER
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_INCOMING_RINGING
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_OUTGOING_RINGING
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.CallManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.CallViewModel
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.HangUpRtcOnPstnCallAnsweredListener
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.HangUpRtcTelephonyCallback
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.IncomingPstnCallReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.NetworkChangeReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.PeerConnectionException
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.PowerButtonReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.ProximityLockRelease
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.UncaughtExceptionHandlerManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.WiredHeadsetStateReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.data.Event
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.webrtc.locks.LockManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.PeerConnection.IceConnectionState.*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.DataChannel
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.IceCandidate
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.MediaStream
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.PeerConnection
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.PeerConnection.IceConnectionState.CONNECTED
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.PeerConnection.IceConnectionState.DISCONNECTED
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.PeerConnection.IceConnectionState.FAILED
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.RtpReceiver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.webrtc.SessionDescription
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.UUID
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.concurrent.ExecutionException
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.concurrent.Executors
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.concurrent.ScheduledFuture
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -215,12 +232,42 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private val hangupTelephonyCallback by lazy {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        HangUpRtcTelephonyCallback {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContextCompat.startForegroundService(this, hangupIntent(this))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private interface TelephonyHandler {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fun register(telephonyManager: TelephonyManager)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fun unregister(telephonyManager: TelephonyManager)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @RequiresApi(Build.VERSION_CODES.S)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private inner class TelephonyHandlerV31: TelephonyHandler {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        private val callback = HangUpRtcTelephonyCallback {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContextCompat.startForegroundService(this@WebRtcCallService, hangupIntent(this@WebRtcCallService))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun register(telephonyManager: TelephonyManager) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyManager.registerTelephonyCallback(serviceExecutor, callback)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun unregister(telephonyManager: TelephonyManager) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyManager.unregisterTelephonyCallback(callback)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private inner class TelephonyHandlerV23: TelephonyHandler {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun register(telephonyManager: TelephonyManager) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyManager.listen(hangupOnCallAnswered, PhoneStateListener.LISTEN_CALL_STATE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun unregister(telephonyManager: TelephonyManager) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyManager.listen(hangupOnCallAnswered, LISTEN_NONE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private val telephonyHandler = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        TelephonyHandlerV31()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        TelephonyHandlerV23()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var networkChangedReceiver: NetworkChangeReceiver? = null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var callReceiver: IncomingPstnCallReceiver? = null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var wantsToAnswerReceiver: BroadcastReceiver? = null
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -251,17 +298,12 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return callManager.callId == expectedCallId
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun isPreOffer() = callManager.isPreOffer()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun isBusy(intent: Intent) = callManager.isBusy(this, getCallId(intent))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun isIdle() = callManager.isIdle()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    override fun onBind(intent: Intent): IBinder? {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return super.onBind(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    override fun onHangup() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        serviceExecutor.execute {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            callManager.handleRemoteHangup()
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -276,38 +318,41 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        super.onStartCommand(intent, flags, startId)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (intent == null || intent.action == null) return START_NOT_STICKY
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        serviceExecutor.execute {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val action = intent.action
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val callId = ((intent.getSerializableExtra(EXTRA_CALL_ID) as? UUID)?.toString() ?: "No callId")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Log.i("Loki", "Handling ${intent.action} for call: ${callId}")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            when {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_INCOMING_RING && isSameCall(intent) && callManager.currentConnectionState == CallState.Reconnecting -> handleNewOffer(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    intent
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_PRE_OFFER && isIdle() -> handlePreOffer(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_INCOMING_RING && isBusy(intent) -> handleBusyCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_INCOMING_RING && isPreOffer() -> handleIncomingRing(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_OUTGOING_CALL && isIdle() -> handleOutgoingCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_ANSWER_CALL -> handleAnswerCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_DENY_CALL -> handleDenyCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_LOCAL_HANGUP -> handleLocalHangup(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_REMOTE_HANGUP -> handleRemoteHangup(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_SET_MUTE_AUDIO -> handleSetMuteAudio(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_SET_MUTE_VIDEO -> handleSetMuteVideo(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_FLIP_CAMERA -> handleSetCameraFlip(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_WIRED_HEADSET_CHANGE -> handleWiredHeadsetChanged(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_SCREEN_OFF -> handleScreenOffChange(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_RESPONSE_MESSAGE && isSameCall(intent) && callManager.currentConnectionState == CallState.Reconnecting -> handleResponseMessage(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    intent
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_RESPONSE_MESSAGE -> handleResponseMessage(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_ICE_MESSAGE -> handleRemoteIceCandidate(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_ICE_CONNECTED -> handleIceConnected(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_CHECK_TIMEOUT -> handleCheckTimeout(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_CHECK_RECONNECT -> handleCheckReconnect(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_IS_IN_CALL_QUERY -> handleIsInCallQuery(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                action == ACTION_UPDATE_AUDIO -> handleUpdateAudio(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            when (action) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_INCOMING_RING -> if (isSameCall(intent) && callManager.currentConnectionState == CallState.Reconnecting) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    handleNewOffer(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_PRE_OFFER -> if (isIdle()) handlePreOffer(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_INCOMING_RING -> when {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    isBusy(intent) -> handleBusyCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    isPreOffer() -> handleIncomingRing(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_OUTGOING_CALL -> if (isIdle()) handleOutgoingCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_ANSWER_CALL -> handleAnswerCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_DENY_CALL -> handleDenyCall(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_LOCAL_HANGUP -> handleLocalHangup(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_REMOTE_HANGUP -> handleRemoteHangup(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_SET_MUTE_AUDIO -> handleSetMuteAudio(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_SET_MUTE_VIDEO -> handleSetMuteVideo(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_FLIP_CAMERA -> handleSetCameraFlip(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_WIRED_HEADSET_CHANGE -> handleWiredHeadsetChanged(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_SCREEN_OFF -> handleScreenOffChange(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_RESPONSE_MESSAGE -> if (isSameCall(intent) && callManager.currentConnectionState == CallState.Reconnecting) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    handleResponseMessage(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_RESPONSE_MESSAGE -> handleResponseMessage(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_ICE_MESSAGE -> handleRemoteIceCandidate(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_ICE_CONNECTED -> handleIceConnected(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_CHECK_TIMEOUT -> handleCheckTimeout(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_CHECK_RECONNECT -> handleCheckReconnect(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_IS_IN_CALL_QUERY -> handleIsInCallQuery(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ACTION_UPDATE_AUDIO -> handleUpdateAudio(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return START_NOT_STICKY
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -322,13 +367,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        registerWiredHeadsetStateReceiver()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        registerWantsToAnswerReceiver()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                getSystemService(TelephonyManager::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    .listen(hangupOnCallAnswered, PhoneStateListener.LISTEN_CALL_STATE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                getSystemService(TelephonyManager::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    .registerTelephonyCallback(serviceExecutor, hangupTelephonyCallback)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyHandler.register(getSystemService(TelephonyManager::class.java))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        registerUncaughtExceptionHandler()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        networkChangedReceiver = NetworkChangeReceiver(::networkChange)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -735,9 +774,8 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                CallNotificationBuilder.WEBRTC_NOTIFICATION,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                CallNotificationBuilder.getCallInProgressNotification(this, type, recipient)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        catch(e: ForegroundServiceStartNotAllowedException) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Log.e(TAG, "Failed to setCallInProgressNotification as a foreground service for type: ${type}, trying to update instead")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } catch (e: IllegalStateException) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Log.e(TAG, "Failed to setCallInProgressNotification as a foreground service for type: ${type}, trying to update instead", e)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (!CallNotificationBuilder.areNotificationsEnabled(this) && type == TYPE_INCOMING_PRE_OFFER) {
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -750,11 +788,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun getOptionalRemoteRecipient(intent: Intent): Recipient? =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (intent.hasExtra(EXTRA_RECIPIENT_ADDRESS)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            getRemoteRecipient(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        intent.takeIf { it.hasExtra(EXTRA_RECIPIENT_ADDRESS) }?.let(::getRemoteRecipient)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun getRemoteRecipient(intent: Intent): Recipient {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        val remoteAddress = intent.getParcelableExtra<Address>(EXTRA_RECIPIENT_ADDRESS)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -763,10 +797,9 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return Recipient.from(this, remoteAddress, true)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun getCallId(intent: Intent): UUID {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return intent.getSerializableExtra(EXTRA_CALL_ID) as? UUID
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun getCallId(intent: Intent): UUID =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        intent.getSerializableExtra(EXTRA_CALL_ID) as? UUID
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ?: throw AssertionError("No callId in intent!")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun insertMissedCall(recipient: Recipient, signal: Boolean) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        callManager.insertCallMessage(
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -788,8 +821,8 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        callReceiver?.let { receiver ->
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            unregisterReceiver(receiver)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        wiredHeadsetStateReceiver?.let { unregisterReceiver(it) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        powerButtonReceiver?.let { unregisterReceiver(it) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        wiredHeadsetStateReceiver?.let(::unregisterReceiver)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        powerButtonReceiver?.let(::unregisterReceiver)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        networkChangedReceiver?.unregister(this)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        wantsToAnswerReceiver?.let { receiver ->
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -804,14 +837,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        currentTimeouts = 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        isNetworkAvailable = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val telephonyManager = getSystemService(TelephonyManager::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            with(telephonyManager) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    this.listen(hangupOnCallAnswered, LISTEN_NONE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    this.unregisterTelephonyCallback(hangupTelephonyCallback)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            telephonyHandler.unregister(getSystemService(TelephonyManager::class.java))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        super.onDestroy()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -819,13 +845,12 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private fun networkChange(networkAvailable: Boolean) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Log.d("Loki", "flipping network available to $networkAvailable")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        isNetworkAvailable = networkAvailable
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (networkAvailable && !callManager.isReestablishing && callManager.currentConnectionState == CallState.Connected) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (networkAvailable && callManager.currentConnectionState == CallState.Connected) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Log.d("Loki", "Should reconnected")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private class CheckReconnectedRunnable(private val callId: UUID, private val context: Context) :
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Runnable {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private class CheckReconnectedRunnable(private val callId: UUID, private val context: Context) : Runnable {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun run() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val intent = Intent(context, WebRtcCallService::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                .setAction(ACTION_CHECK_RECONNECT)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -834,18 +859,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private class ReconnectTimeoutRunnable(private val callId: UUID, private val context: Context) :
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Runnable {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun run() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val intent = Intent(context, WebRtcCallService::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                .setAction(ACTION_CHECK_RECONNECT_TIMEOUT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                .putExtra(EXTRA_CALL_ID, callId)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            context.startService(intent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private class TimeoutRunnable(private val callId: UUID, private val context: Context) :
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Runnable {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private class TimeoutRunnable(private val callId: UUID, private val context: Context) : Runnable {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        override fun run() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            val intent = Intent(context, WebRtcCallService::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                .setAction(ACTION_CHECK_TIMEOUT)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |