Merge branch 'dev' into fix/video-call-rotation-and-avatars

This commit is contained in:
ThomasSession 2024-07-19 17:42:24 +10:00
commit 2d98da10ee
4 changed files with 140 additions and 129 deletions

View File

@ -0,0 +1,46 @@
package org.thoughtcrime.securesms.service
import android.os.Build
import android.telephony.PhoneStateListener
import android.telephony.PhoneStateListener.LISTEN_NONE
import android.telephony.TelephonyManager
import androidx.annotation.RequiresApi
import org.thoughtcrime.securesms.webrtc.HangUpRtcOnPstnCallAnsweredListener
import org.thoughtcrime.securesms.webrtc.HangUpRtcTelephonyCallback
import java.util.concurrent.ExecutorService
internal interface TelephonyHandler {
fun register(telephonyManager: TelephonyManager)
fun unregister(telephonyManager: TelephonyManager)
}
internal fun TelephonyHandler(serviceExecutor: ExecutorService, callback: () -> Unit) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
TelephonyHandlerV31(serviceExecutor, callback)
} else {
TelephonyHandlerV23(callback)
}
@RequiresApi(Build.VERSION_CODES.S)
private class TelephonyHandlerV31(val serviceExecutor: ExecutorService, callback: () -> Unit): TelephonyHandler {
private val callback = HangUpRtcTelephonyCallback(callback)
override fun register(telephonyManager: TelephonyManager) {
telephonyManager.registerTelephonyCallback(serviceExecutor, callback)
}
override fun unregister(telephonyManager: TelephonyManager) {
telephonyManager.unregisterTelephonyCallback(callback)
}
}
private class TelephonyHandlerV23(callback: () -> Unit): TelephonyHandler {
val callback = HangUpRtcOnPstnCallAnsweredListener(callback)
override fun register(telephonyManager: TelephonyManager) {
telephonyManager.listen(callback, PhoneStateListener.LISTEN_CALL_STATE)
}
override fun unregister(telephonyManager: TelephonyManager) {
telephonyManager.listen(callback, LISTEN_NONE)
}
}

View File

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

View File

@ -118,7 +118,7 @@ class CallManager(
remoteVideoEnabled = false remoteVideoEnabled = false
) )
) )
val videoState = _videoState val videoState = _videoState.asStateFlow()
private val stateProcessor = StateProcessor(CallState.Idle) private val stateProcessor = StateProcessor(CallState.Idle)
@ -137,7 +137,7 @@ class CallManager(
val currentCallState val currentCallState
get() = _callStateEvents.value get() = _callStateEvents.value
var iceState = IceConnectionState.CLOSED private var iceState = IceConnectionState.CLOSED
private var eglBase: EglBase? = null private var eglBase: EglBase? = null
@ -151,7 +151,6 @@ class CallManager(
_recipientEvents.value = RecipientUpdate(value) _recipientEvents.value = RecipientUpdate(value)
} }
var callStartTime: Long = -1 var callStartTime: Long = -1
var isReestablishing: Boolean = false
private var peerConnection: PeerConnectionWrapper? = null private var peerConnection: PeerConnectionWrapper? = null
private var dataChannel: DataChannel? = null private var dataChannel: DataChannel? = null
@ -628,12 +627,10 @@ class CallManager(
if (_videoState.value.swapped) { if (_videoState.value.swapped) {
peerConnection?.rotationVideoSink?.setSink(fullscreenRenderer) peerConnection?.rotationVideoSink?.setSink(fullscreenRenderer)
floatingRenderer?.let{remoteRotationSink?.setSink(it) } floatingRenderer?.let { remoteRotationSink?.setSink(it) }
} else { } else {
peerConnection?.rotationVideoSink?.apply { peerConnection?.rotationVideoSink?.setSink(floatingRenderer)
setSink(floatingRenderer) fullscreenRenderer?.let { remoteRotationSink?.setSink(it) }
}
fullscreenRenderer?.let{ remoteRotationSink?.setSink(it) }
} }
} }
@ -645,12 +642,12 @@ class CallManager(
/** /**
* Returns the renderer currently showing the user's video, not the contact's * Returns the renderer currently showing the user's video, not the contact's
*/ */
private fun getUserRenderer() = if(_videoState.value.swapped) fullscreenRenderer else floatingRenderer private fun getUserRenderer() = if (_videoState.value.swapped) fullscreenRenderer else floatingRenderer
/** /**
* Returns the renderer currently showing the contact's video, not the user's * Returns the renderer currently showing the contact's video, not the user's
*/ */
private fun getRemoteRenderer() = if(_videoState.value.swapped) floatingRenderer else fullscreenRenderer private fun getRemoteRenderer() = if (_videoState.value.swapped) floatingRenderer else fullscreenRenderer
/** /**
* Makes sure the user's renderer applies mirroring if necessary * Makes sure the user's renderer applies mirroring if necessary
@ -659,12 +656,12 @@ class CallManager(
val videoState = _videoState.value val videoState = _videoState.value
// if we have user video and the camera is front facing, make sure to mirror stream // if we have user video and the camera is front facing, make sure to mirror stream
if(videoState.userVideoEnabled) { if (videoState.userVideoEnabled) {
getUserRenderer()?.setMirror(isCameraFrontFacing()) getUserRenderer()?.setMirror(isCameraFrontFacing())
} }
// the remote video is never mirrored // the remote video is never mirrored
if(videoState.remoteVideoEnabled){ if (videoState.remoteVideoEnabled){
getRemoteRenderer()?.setMirror(false) getRemoteRenderer()?.setMirror(false)
} }
} }

View File

@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.webrtc
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -32,29 +31,25 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V
} }
val floatingRenderer: SurfaceViewRenderer? val floatingRenderer: SurfaceViewRenderer?
get() = callManager.floatingRenderer get() = callManager.floatingRenderer
val fullscreenRenderer: SurfaceViewRenderer? val fullscreenRenderer: SurfaceViewRenderer?
get() = callManager.fullscreenRenderer get() = callManager.fullscreenRenderer
private var _microphoneEnabled: Boolean = true var microphoneEnabled: Boolean = true
private set
val microphoneEnabled: Boolean var isSpeaker: Boolean = false
get() = _microphoneEnabled private set
private var _isSpeaker: Boolean = false
val isSpeaker: Boolean
get() = _isSpeaker
val audioDeviceState val audioDeviceState
get() = callManager.audioDeviceEvents get() = callManager.audioDeviceEvents.onEach {
.onEach { isSpeaker = it.selectedDevice == SignalAudioManager.AudioDevice.SPEAKER_PHONE
_isSpeaker = it.selectedDevice == SignalAudioManager.AudioDevice.SPEAKER_PHONE }
}
val localAudioEnabledState val localAudioEnabledState
get() = callManager.audioEvents.map { it.isEnabled } get() = callManager.audioEvents.map { it.isEnabled }
.onEach { _microphoneEnabled = it } .onEach { microphoneEnabled = it }
val videoState: StateFlow<VideoState> val videoState: StateFlow<VideoState>
get() = callManager.videoState get() = callManager.videoState
@ -65,17 +60,10 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V
callManager.setDeviceOrientation(value) callManager.setDeviceOrientation(value)
} }
val currentCallState val currentCallState get() = callManager.currentCallState
get() = callManager.currentCallState val callState get() = callManager.callStateEvents
val recipient get() = callManager.recipientEvents
val callState val callStartTime: Long get() = callManager.callStartTime
get() = callManager.callStateEvents
val recipient
get() = callManager.recipientEvents
val callStartTime: Long
get() = callManager.callStartTime
fun swapVideos() { fun swapVideos() {
callManager.swapVideos() callManager.swapVideos()