diff --git a/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt b/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt index 83aaca1a3..6b9a7ec7d 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt @@ -23,6 +23,7 @@ import androidx.lifecycle.MutableLiveData import org.linphone.R import org.linphone.activities.main.settings.SettingListenerStub import org.linphone.core.MediaEncryption +import org.linphone.core.tools.Log import org.linphone.mediastream.Version import org.linphone.telecom.TelecomHelper import org.linphone.utils.Event @@ -67,7 +68,11 @@ class CallSettingsViewModel : GenericSettingsViewModel() { if (newValue) { enableTelecomManagerEvent.value = Event(true) } else { - if (TelecomHelper.exists()) TelecomHelper.get().removeAccount() + if (TelecomHelper.exists()) { + Log.i("[Call Settings] Removing Telecom Manager account & destroying singleton") + TelecomHelper.get().removeAccount() + TelecomHelper.destroy() + } prefs.useTelecomManager = newValue } } diff --git a/app/src/main/java/org/linphone/core/CoreContext.kt b/app/src/main/java/org/linphone/core/CoreContext.kt index 60eed1a72..b611f0258 100644 --- a/app/src/main/java/org/linphone/core/CoreContext.kt +++ b/app/src/main/java/org/linphone/core/CoreContext.kt @@ -136,7 +136,7 @@ class CoreContext(val context: Context, coreConfig: Config) { ) { Log.i("[Context] Call state changed [$state]") if (state == Call.State.IncomingReceived || state == Call.State.IncomingEarlyMedia) { - if (!corePreferences.useTelecomManager) { + if (!corePreferences.useTelecomManager) { // Can't use the following call with Telecom Manager API as it will "fake" GSM calls var gsmCallActive = false if (::phoneStateListener.isInitialized) { gsmCallActive = phoneStateListener.isInCall() @@ -147,6 +147,18 @@ class CoreContext(val context: Context, coreConfig: Config) { call.decline(Reason.Busy) return } + } else { + if (TelecomHelper.exists()) { + if (!TelecomHelper.get().isIncomingCallPermitted() || + TelecomHelper.get().isInManagedCall() + ) { + Log.w("[Context] Refusing the call with reason busy because Telecom Manager will reject the call") + call.decline(Reason.Busy) + return + } + } else { + Log.e("[Context] Telecom Manager singleton wasn't created!") + } } // Starting SDK 24 (Android 7.0) we rely on the fullscreen intent of the call incoming notification @@ -297,13 +309,14 @@ class CoreContext(val context: Context, coreConfig: Config) { notificationsManager.onCoreReady() + core.addListener(listener) + + // CoreContext listener must be added first! if (Version.sdkAboveOrEqual(Version.API26_O_80) && corePreferences.useTelecomManager) { Log.i("[Context] Creating telecom helper") TelecomHelper.create(context) } - core.addListener(listener) - if (isPush) { Log.i("[Context] Push received, assume in background") core.enterBackground() diff --git a/app/src/main/java/org/linphone/telecom/NativeCallWrapper.kt b/app/src/main/java/org/linphone/telecom/NativeCallWrapper.kt index 7df07f695..3e497809b 100644 --- a/app/src/main/java/org/linphone/telecom/NativeCallWrapper.kt +++ b/app/src/main/java/org/linphone/telecom/NativeCallWrapper.kt @@ -23,7 +23,6 @@ import android.graphics.drawable.Icon import android.os.Bundle import android.telecom.CallAudioState import android.telecom.Connection -import android.telecom.DisconnectCause import android.telecom.StatusHints import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R @@ -95,7 +94,6 @@ class NativeCallWrapper(var callId: String) : Connection() { override fun onReject() { Log.i("[Connection] Rejecting telecom call with id: $callId") - setDisconnected(DisconnectCause(DisconnectCause.REJECTED)) getCall()?.terminate() } diff --git a/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt b/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt index 252bfbfda..de424cdd3 100644 --- a/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt +++ b/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt @@ -48,6 +48,7 @@ class TelecomConnectionService : ConnectionService() { } } } + Call.State.Error -> onCallError(call) Call.State.End, Call.State.Released -> onCallEnded(call) Call.State.Connected -> onCallConnected(call) } @@ -160,12 +161,23 @@ class TelecomConnectionService : ConnectionService() { } } + private fun onCallError(call: Call) { + val connection = getConnectionForCallId(call.callLog.callId) + connection ?: return + + connections.remove(connection) + connection.setDisconnected(DisconnectCause(DisconnectCause.ERROR)) + connection.destroy() + } + private fun onCallEnded(call: Call) { val connection = getConnectionForCallId(call.callLog.callId) connection ?: return connections.remove(connection) - connection.setDisconnected(DisconnectCause(DisconnectCause.REJECTED)) + val reason = call.reason + Log.i("[Telecom Connection Service] Call ended with reason: $reason") + connection.setDisconnected(DisconnectCause(DisconnectCause.LOCAL)) connection.destroy() } diff --git a/app/src/main/java/org/linphone/telecom/TelecomHelper.kt b/app/src/main/java/org/linphone/telecom/TelecomHelper.kt index 6174faad4..88dda9f2b 100644 --- a/app/src/main/java/org/linphone/telecom/TelecomHelper.kt +++ b/app/src/main/java/org/linphone/telecom/TelecomHelper.kt @@ -50,13 +50,17 @@ class TelecomHelper private constructor(context: Context) { private var account: PhoneAccount = initPhoneAccount(context) private val listener: CoreListenerStub = object : CoreListenerStub() { - override fun onFirstCallStarted(core: Core) { - val call = core.calls.firstOrNull() - call ?: return + override fun onCallStateChanged( + core: Core, + call: Call, + state: Call.State?, + message: String + ) { + Log.i("[Telecom Helper] Call state changed: ${call.state}") - if (call.dir == Call.Dir.Incoming) { + if (call.dir == Call.Dir.Incoming && call.state == Call.State.IncomingReceived) { onIncomingCall(call) - } else { + } else if (call.dir == Call.Dir.Outgoing && call.state == Call.State.OutgoingProgress) { onOutgoingCall(call) } } @@ -72,6 +76,20 @@ class TelecomHelper private constructor(context: Context) { Log.i("[Telecom Helper] Destroyed") } + fun isIncomingCallPermitted(): Boolean { + val incomingCallPermitted = telecomManager.isIncomingCallPermitted(account.accountHandle) + Log.i("[Telecom Helper] Is incoming call permitted? $incomingCallPermitted") + return incomingCallPermitted + } + + @SuppressLint("MissingPermission") + fun isInManagedCall(): Boolean { + // Don't use telecomManager.isInCall as our own self-managed calls will be considered! + val isInManagedCall = telecomManager.isInManagedCall + Log.i("[Telecom Helper] Is in managed call? $isInManagedCall") + return isInManagedCall + } + fun isAccountEnabled(): Boolean { val enabled = account.isEnabled Log.i("[Telecom Helper] Is account enabled ? $enabled")