From 5cff5ffb450521185e28ecefcf395ee097d05353 Mon Sep 17 00:00:00 2001 From: jubb Date: Thu, 4 Nov 2021 12:07:06 +1100 Subject: [PATCH] feat: adding more lifecycle vm and callmanager / call service functionality --- app/src/main/AndroidManifest.xml | 2 +- ...TestsActivity.kt => WebRtcCallActivity.kt} | 10 +- .../v2/menus/ConversationMenuHelper.kt | 12 +- .../securesms/home/HomeActivity.kt | 4 +- .../securesms/service/WebRtcCallService.kt | 111 ++++++++++++++++++ .../securesms/util/CallNotificationBuilder.kt | 107 +++++++++++++++++ .../securesms/webrtc/CallBottomSheet.kt | 12 +- .../securesms/webrtc/CallManager.kt | 34 ++++-- .../securesms/webrtc/CallViewModel.kt | 23 +++- .../webrtc/audio/SignalAudioManager.kt | 6 +- app/src/main/res/values/strings.xml | 8 ++ 11 files changed, 295 insertions(+), 34 deletions(-) rename app/src/main/java/org/thoughtcrime/securesms/calls/{WebRtcTestsActivity.kt => WebRtcCallActivity.kt} (97%) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/CallNotificationBuilder.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0b5c2cbae1..5dee3345a0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -297,7 +297,7 @@ android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:exported="true" android:theme="@style/Theme.Session.DayNight.NoActionBar" /> - () @@ -135,7 +135,7 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity() { } if (answer != null) { peerConnection.setRemoteDescription( - this@WebRtcTestsActivity, + this@WebRtcCallActivity, SessionDescription(SessionDescription.Type.ANSWER, answer.sdps[0]) ) break @@ -153,7 +153,7 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity() { lifecycleScope.launchWhenResumed { while (this.isActive) { delay(2_000L) - peerConnection.getStats(this@WebRtcTestsActivity) + peerConnection.getStats(this@WebRtcCallActivity) synchronized(WebRtcUtils.callCache) { val set = WebRtcUtils.callCache[callId] ?: mutableSetOf() set.filter { it.hashCode() !in acceptedCallMessageHashes diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt index bdcca6bf84..014def0457 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt @@ -36,7 +36,7 @@ import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.utilities.guava.Optional import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.* -import org.thoughtcrime.securesms.calls.WebRtcTestsActivity +import org.thoughtcrime.securesms.calls.WebRtcCallActivity import org.thoughtcrime.securesms.contacts.SelectContactsActivity import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils @@ -187,15 +187,15 @@ object ConversationMenuHelper { .setTitle("Call") .setMessage("Use relay?") .setPositiveButton("Use Relay") { d, w -> - val intent = Intent(context, WebRtcTestsActivity::class.java) - intent.putExtra(WebRtcTestsActivity.EXTRA_CALL_ID, UUID.randomUUID().toString()) - intent.putExtra(WebRtcTestsActivity.EXTRA_ADDRESS, thread.address) + val intent = Intent(context, WebRtcCallActivity::class.java) + intent.putExtra(WebRtcCallActivity.EXTRA_CALL_ID, UUID.randomUUID().toString()) + intent.putExtra(WebRtcCallActivity.EXTRA_ADDRESS, thread.address) val activity = context as AppCompatActivity activity.startActivity(intent) } .setNeutralButton("P2P only") { d, w -> - val intent = Intent(context, WebRtcTestsActivity::class.java) - intent.putExtra(WebRtcTestsActivity.EXTRA_ADDRESS, thread.address) + val intent = Intent(context, WebRtcCallActivity::class.java) + intent.putExtra(WebRtcCallActivity.EXTRA_ADDRESS, thread.address) val activity = context as AppCompatActivity activity.startActivity(intent) } 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 7d30987463..85c6236f0c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -45,7 +45,7 @@ import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.MuteDialog import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity -import org.thoughtcrime.securesms.calls.WebRtcTestsActivity +import org.thoughtcrime.securesms.calls.WebRtcCallActivity import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils import org.thoughtcrime.securesms.crypto.IdentityKeyUtil @@ -185,7 +185,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis synchronized(WebRtcUtils.callCache) { WebRtcUtils.callCache[callId] = mutableSetOf() } - sendBroadcast(Intent(WebRtcTestsActivity.ACTION_END)) + sendBroadcast(Intent(WebRtcCallActivity.ACTION_END)) } else -> { /* do nothing */ } } 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 8019692ebd..276a44466f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt @@ -6,18 +6,32 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.media.AudioManager +import android.os.Build import android.os.IBinder import android.os.ResultReceiver import android.telephony.PhoneStateListener import android.telephony.TelephonyManager import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint +import org.session.libsession.utilities.Address import org.session.libsession.utilities.FutureTaskListener +import org.session.libsession.utilities.Util +import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.calls.WebRtcCallActivity +import org.thoughtcrime.securesms.util.CallNotificationBuilder +import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_ESTABLISHED +import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.TYPE_INCOMING_CONNECTING +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.CallManager.CallState.* +import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger +import java.lang.AssertionError import java.util.* import java.util.concurrent.ExecutionException import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit import javax.inject.Inject @AndroidEntryPoint @@ -26,6 +40,9 @@ class WebRtcCallService: Service() { @Inject lateinit var callManager: CallManager companion object { + + private val TAG = Log.tag(WebRtcCallService::class.java) + const val ACTION_INCOMING_CALL = "CALL_INCOMING" const val ACTION_OUTGOING_CALL = "CALL_OUTGOING" const val ACTION_ANSWER_CALL = "ANSWER_CALL" @@ -168,6 +185,100 @@ class WebRtcCallService: Service() { registerReceiver(wiredHeadsetStateReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG)) } + private fun handleBusyCall(intent: Intent) { + val recipient = getRemoteRecipient(intent) + val callId = getCallId(intent) + val callState = callManager.currentConnectionState + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + when (callState) { + STATE_DIALING, + STATE_REMOTE_RINGING -> setCallInProgressNotification(TYPE_OUTGOING_RINGING, callManager.recipient) + STATE_IDLE -> setCallInProgressNotification(TYPE_INCOMING_CONNECTING, recipient) + STATE_ANSWERING -> setCallInProgressNotification(TYPE_INCOMING_CONNECTING, callManager.recipient) + STATE_LOCAL_RINGING -> setCallInProgressNotification(TYPE_INCOMING_RINGING, callManager.recipient) + STATE_CONNECTED -> setCallInProgressNotification(TYPE_ESTABLISHED, callManager.recipient) + else -> throw AssertionError() + } + } + + if (callState == STATE_IDLE) { + stopForeground(true) + } + + // TODO: send hangup via messageSender + insertMissedCall(getRemoteRecipient(intent), false) + } + + private fun handleBusyMessage(intent: Intent) { + val recipient = getRemoteRecipient(intent) + val callId = getCallId(intent) + if (callManager.currentConnectionState != STATE_DIALING || callManager.callId != callManager.callId || callManager.recipient != callManager.recipient) { + Log.w(TAG,"Got busy message for inactive session...") + return + } + callManager.postViewModelState(CallViewModel.State.CALL_BUSY) + callManager.startOutgoingRinger(OutgoingRinger.Type.BUSY) + Util.runOnMainDelayed({ + startService( + Intent(this, WebRtcCallService::class.java) + .setAction(ACTION_LOCAL_HANGUP) + ) + }, WebRtcCallActivity.BUSY_SIGNAL_DELAY_FINISH) + } + + private fun handleIncomingCall(intent: Intent) { + if (callManager.currentConnectionState != STATE_IDLE) throw IllegalStateException("Incoming on non-idle") + + val offer = intent.getStringExtra(EXTRA_REMOTE_DESCRIPTION) + callManager.postConnectionEvent(STATE_ANSWERING) + callManager.callId = getCallId(intent) + callManager.clearPendingIceUpdates() + val recipient = getRemoteRecipient(intent) + callManager.recipient = recipient + if (isIncomingMessageExpired(intent)) { + insertMissedCall(recipient, true) + } + } + + private fun handleCheckTimeout(intent: Intent) { + val callId = callManager.callId ?: return + val callState = callManager.currentConnectionState + + if (callId == getCallId(intent) && callState != STATE_CONNECTED) { + Log.w(TAG, "Timing out call: $callId") + callManager.postViewModelState(CallViewModel.State.CALL_DISCONNECTED) + } + } + + private fun setCallInProgressNotification(type: Int, recipient: Recipient?) { + startForeground( + CallNotificationBuilder.WEBRTC_NOTIFICATION, + CallNotificationBuilder.getCallInProgressNotification(this, type, recipient) + ) + } + + private fun getRemoteRecipient(intent: Intent): Recipient { + val remoteAddress = intent.getParcelableExtra
(EXTRA_RECIPIENT_ADDRESS) + ?: throw AssertionError("No recipient in intent!") + + return Recipient.from(this, remoteAddress, true) + } + + private fun getCallId(intent: Intent) : UUID { + return intent.getSerializableExtra(EXTRA_CALL_ID) as? UUID + ?: throw AssertionError("No callId in intent!") + } + + private fun insertMissedCall(recipient: Recipient, signal: Boolean) { + // TODO +// val messageAndThreadId = DatabaseComponent.get(this).smsDatabase().insertReceivedCall(recipient.address) +// MessageNotifier.updateNotification(this, messageAndThreadId.second, signal) + } + + private fun isIncomingMessageExpired(intent: Intent) = + System.currentTimeMillis() - intent.getLongExtra(EXTRA_TIMESTAMP, -1) > TimeUnit.MINUTES.toMillis(2) + override fun onDestroy() { super.onDestroy() callReceiver?.let { receiver -> diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/CallNotificationBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/util/CallNotificationBuilder.kt new file mode 100644 index 0000000000..46723b4109 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/CallNotificationBuilder.kt @@ -0,0 +1,107 @@ +package org.thoughtcrime.securesms.util + +import android.app.Notification +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.core.app.NotificationCompat +import network.loki.messenger.R +import org.session.libsession.utilities.recipients.Recipient +import org.thoughtcrime.securesms.calls.WebRtcCallActivity +import org.thoughtcrime.securesms.notifications.NotificationChannels +import org.thoughtcrime.securesms.service.WebRtcCallService + +class CallNotificationBuilder { + + companion object { + const val WEBRTC_NOTIFICATION = 313388 + + const val TYPE_INCOMING_RINGING = 1 + const val TYPE_OUTGOING_RINGING = 2 + const val TYPE_ESTABLISHED = 3 + const val TYPE_INCOMING_CONNECTING = 4 + + @JvmStatic + fun getCallInProgressNotification(context: Context, type: Int, recipient: Recipient?): Notification { + val contentIntent = Intent(context, WebRtcCallActivity::class.java) + .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) + + val pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0) + + val builder = NotificationCompat.Builder(context, NotificationChannels.CALLS) + .setSmallIcon(R.drawable.ic_baseline_call_24) + .setContentIntent(pendingIntent) + .setOngoing(true) + + recipient?.name?.let { name -> + builder.setContentTitle(name) + } + + when (type) { + TYPE_INCOMING_CONNECTING -> { + builder.setContentText(context.getString(R.string.CallNotificationBuilder_connecting)) + builder.priority = NotificationCompat.PRIORITY_MIN + } + TYPE_INCOMING_RINGING -> { + builder.setContentText(context.getString(R.string.NotificationBarManager__incoming_signal_call)) + builder.addAction(getServiceNotificationAction( + context, + WebRtcCallService.ACTION_DENY_CALL, + R.drawable.ic_close_grey600_32dp, + R.string.NotificationBarManager__deny_call + )) + builder.addAction(getActivityNotificationAction( + context, + WebRtcCallActivity.ACTION_ANSWER, + R.drawable.ic_phone_grey600_32dp, + R.string.NotificationBarManager__answer_call + )) + } + TYPE_OUTGOING_RINGING -> { + builder.setContentText(context.getString(R.string.NotificationBarManager__establishing_signal_call)) + builder.addAction(getServiceNotificationAction( + context, + WebRtcCallService.ACTION_LOCAL_HANGUP, + R.drawable.ic_call_end_grey600_32dp, + R.string.NotificationBarManager__cancel_call + )) + } + else -> { + builder.setContentText(context.getString(R.string.NotificationBarManager_call_in_progress)) + builder.addAction(getServiceNotificationAction( + context, + WebRtcCallService.ACTION_LOCAL_HANGUP, + R.drawable.ic_call_end_grey600_32dp, + R.string.NotificationBarManager__end_call + )) + } + } + + return builder.build() + } + + @JvmStatic + private fun getServiceNotificationAction(context: Context, action: String, iconResId: Int, titleResId: Int): NotificationCompat.Action { + val intent = Intent(context, WebRtcCallService::class.java) + .setAction(action) + + val pendingIntent = PendingIntent.getService(context, 0, intent, 0) + + return NotificationCompat.Action(iconResId, context.getString(titleResId), pendingIntent) + } + + @JvmStatic + private fun getActivityNotificationAction(context: Context, action: String, + @DrawableRes iconResId: Int, @StringRes titleResId: Int): NotificationCompat.Action { + val intent = Intent(context, WebRtcCallActivity::class.java) + .setAction(action) + + val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0) + + return NotificationCompat.Action(iconResId, context.getString(titleResId), pendingIntent) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallBottomSheet.kt index 114304b4c3..8318ad69f2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallBottomSheet.kt @@ -15,7 +15,7 @@ import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.utilities.Address import org.session.libsession.utilities.recipients.Recipient -import org.thoughtcrime.securesms.calls.WebRtcTestsActivity +import org.thoughtcrime.securesms.calls.WebRtcCallActivity import org.thoughtcrime.securesms.mms.GlideApp import java.util.* @@ -54,13 +54,13 @@ class CallBottomSheet: BottomSheetDialogFragment() { nameTextView.text = recipient.name ?: address.serialize() acceptButton.setOnClickListener { - val intent = Intent(requireContext(), WebRtcTestsActivity::class.java) + val intent = Intent(requireContext(), WebRtcCallActivity::class.java) val bundle = bundleOf( - WebRtcTestsActivity.EXTRA_ADDRESS to address, - WebRtcTestsActivity.EXTRA_CALL_ID to callId + WebRtcCallActivity.EXTRA_ADDRESS to address, + WebRtcCallActivity.EXTRA_CALL_ID to callId ) - intent.action = WebRtcTestsActivity.ACTION_ANSWER - bundle.putStringArray(WebRtcTestsActivity.EXTRA_SDP, sdp) + intent.action = WebRtcCallActivity.ACTION_ANSWER + bundle.putStringArray(WebRtcCallActivity.EXTRA_SDP, sdp) intent.putExtras(bundle) startActivity(intent) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt index 6552398e2b..dd8633a25a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt @@ -11,6 +11,7 @@ import org.session.libsignal.protos.SignalServiceProtos import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.service.WebRtcCallService import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat +import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager import org.thoughtcrime.securesms.webrtc.video.CameraState import org.webrtc.* @@ -59,19 +60,21 @@ class CallManager(context: Context, audioManager: AudioManagerCompat): PeerConne val remoteVideoEvents = _remoteVideoEvents.asSharedFlow() private val _connectionEvents = MutableStateFlow(StateEvent.CallStateUpdate(CallState.STATE_IDLE)) val connectionEvents = _connectionEvents.asSharedFlow() + private val _callStateEvents = MutableStateFlow(CallViewModel.State.CALL_PENDING) + val callStateEvents = _callStateEvents.asSharedFlow() private var localCameraState: CameraState = CameraState.UNKNOWN private var microphoneEnabled = true private var remoteVideoEnabled = false private var bluetoothAvailable = false - private val currentCallState = (_connectionEvents.value as StateEvent.CallStateUpdate).state + val currentConnectionState = (_connectionEvents.value as StateEvent.CallStateUpdate).state private val networkExecutor = Executors.newSingleThreadExecutor() private var eglBase: EglBase? = null - private var callId: UUID? = null - private var recipient: Recipient? = null + var callId: UUID? = null + var recipient: Recipient? = null private var peerConnectionWrapper: PeerConnectionWrapper? = null private var dataChannel: DataChannel? = null @@ -82,6 +85,23 @@ class CallManager(context: Context, audioManager: AudioManagerCompat): PeerConne private var remoteRenderer: SurfaceViewRenderer? = null private var peerConnectionFactory: PeerConnectionFactory? = null + fun clearPendingIceUpdates() { + pendingOutgoingIceUpdates.clear() + pendingIncomingIceUpdates.clear() + } + + fun startOutgoingRinger(ringerType: OutgoingRinger.Type) { + signalAudioManager.startOutgoingRinger(ringerType) + } + + fun postConnectionEvent(newState: CallState) { + _connectionEvents.value = StateEvent.CallStateUpdate(newState) + } + + fun postViewModelState(newState: CallViewModel.State) { + _callStateEvents.value = newState + } + private fun createCameraCapturer(enumerator: CameraEnumerator): CameraVideoCapturer? { val deviceNames = enumerator.deviceNames @@ -128,7 +148,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat): PeerConne } - fun isBusy(context: Context) = currentCallState != CallState.STATE_IDLE + fun isBusy(context: Context) = currentConnectionState != CallState.STATE_IDLE || context.getSystemService(TelephonyManager::class.java).callState != TelephonyManager.CALL_STATE_IDLE fun initializeVideo(context: Context) { @@ -162,14 +182,14 @@ class CallManager(context: Context, audioManager: AudioManagerCompat): PeerConne } fun setAudioEnabled(isEnabled: Boolean) { - currentCallState.withState(*(CONNECTED_STATES + PENDING_CONNECTION_STATES)) { + currentConnectionState.withState(*(CONNECTED_STATES + PENDING_CONNECTION_STATES)) { peerConnectionWrapper?.setAudioEnabled(isEnabled) _audioEvents.value = StateEvent.AudioEnabled(true) } } fun setVideoEnabled(isEnabled: Boolean) { - currentCallState.withState(*(CONNECTED_STATES + PENDING_CONNECTION_STATES)) { + currentConnectionState.withState(*(CONNECTED_STATES + PENDING_CONNECTION_STATES)) { peerConnectionWrapper?.setVideoEnabled(isEnabled) _audioEvents.value = StateEvent.AudioEnabled(true) } @@ -236,7 +256,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat): PeerConne } fun stop() { - signalAudioManager.stop(currentCallState in OUTGOING_STATES) + signalAudioManager.stop(currentConnectionState in OUTGOING_STATES) peerConnectionWrapper?.dispose() peerConnectionWrapper = null diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt index d3866bf1ee..351e4673ca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt @@ -14,15 +14,30 @@ import javax.inject.Inject @HiltViewModel class CallViewModel @Inject constructor(private val callManager: CallManager): ViewModel() { + enum class State { + CALL_PENDING, + + CALL_INCOMING, + CALL_OUTGOING, + CALL_CONNECTED, + CALL_RINGING, + CALL_BUSY, + CALL_DISCONNECTED, + + NETWORK_FAILURE, + RECIPIENT_UNAVAILABLE, + NO_SUCH_USER, + UNTRUSTED_IDENTITY, + } + val localAudioEnabledState = callManager.audioEvents.map { it.isEnabled } val localVideoEnabledState = callManager.videoEvents.map { it.isEnabled } val remoteVideoEnabledState = callManager.remoteVideoEvents.map { it.isEnabled } + val callState = callManager.callStateEvents + // set up listeners for establishing connection toggling video / audio init { - callManager.audioEvents.onEach { (enabled) -> callManager.setAudioEnabled(enabled) } - .launchIn(viewModelScope) - callManager.videoEvents.onEach { (enabled) -> callManager.setVideoEnabled(enabled) } - .launchIn(viewModelScope) + } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt index 2c6136e39f..0b2c864338 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt @@ -58,8 +58,8 @@ class SignalAudioManager(private val context: Context, private val connectedSoundId = soundPool.load(context, R.raw.webrtc_completed, 1) private val disconnectedSoundId = soundPool.load(context, R.raw.webrtc_disconnected, 1) - private val incomingRinger = IncomingRinger(context) - private val outgoingRinger = OutgoingRinger(context) + val incomingRinger = IncomingRinger(context) + val outgoingRinger = OutgoingRinger(context) private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null @@ -340,7 +340,7 @@ class SignalAudioManager(private val context: Context, incomingRinger.stop() } - private fun startOutgoingRinger() { + fun startOutgoingRinger(type: OutgoingRinger.Type) { Log.i(TAG, "startOutgoingRinger(): currentDevice: $selectedAudioDevice") androidAudioManager.mode = AudioManager.MODE_IN_COMMUNICATION diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e94799e8d4..621db91f0a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -903,5 +903,13 @@ Debug Log Share Logs Would you like to export your application logs to be able to share for troubleshooting? + Connecting… + Incoming call + Deny call + Answer call + Call in progress + Cancel call + Establishing call + End call