From 201a346d415090737a722a43e6e5e2023f296f6a Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Jan 2021 12:20:50 +0100 Subject: [PATCH] VoIP: check for support of PSTN protocol --- .../app/features/call/webrtc/PSTNProtocol.kt | 42 +++++++++++++++++++ .../features/call/webrtc/WebRtcCallManager.kt | 27 ++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/call/webrtc/PSTNProtocol.kt diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/PSTNProtocol.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/PSTNProtocol.kt new file mode 100644 index 0000000000..599768a584 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/PSTNProtocol.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.call.webrtc + +import kotlinx.coroutines.delay +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol +import org.matrix.android.sdk.internal.util.awaitCallback + +private const val PSTN_VECTOR_KEY = "im.vector.protocol.pstn" +private const val PSTN_MATRIX_KEY = "m.protocol.pstn" + +suspend fun Session.supportPSTN(maxTries: Int): Boolean { + val thirdPartyProtocols: Map = try { + awaitCallback { + getThirdPartyProtocol(it) + } + } catch (failure: Throwable) { + if (maxTries == 1) { + return false + } else { + // Wait for 10s before trying again + delay(10_000L) + return supportPSTN(maxTries - 1) + } + } ?: return false + return thirdPartyProtocols.containsKey(PSTN_VECTOR_KEY) || thirdPartyProtocols.containsKey(PSTN_MATRIX_KEY) +} diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt index f6fcfd446e..bdd9272e0d 100644 --- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt @@ -28,7 +28,10 @@ import im.vector.app.features.call.CallAudioManager import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.utils.EglUtils import im.vector.app.push.fcm.FcmHelper +import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.call.CallListener @@ -67,6 +70,19 @@ class WebRtcCallManager @Inject constructor( fun onAudioDevicesChange() {} } + interface PSTNSupportListener { + fun onPSTNSupportUpdated() + } + + private val pstnSupportListeners = emptyList().toMutableList() + fun addPstnSupportListener(listener: PSTNSupportListener) { + pstnSupportListeners.add(listener) + } + + fun removePstnSupportListener(listener: PSTNSupportListener) { + pstnSupportListeners.remove(listener) + } + private val currentCallsListeners = emptyList().toMutableList() fun addCurrentCallListener(listener: CurrentCallListener) { currentCallsListeners.add(listener) @@ -85,11 +101,22 @@ class WebRtcCallManager @Inject constructor( private var peerConnectionFactory: PeerConnectionFactory? = null private val executor = Executors.newSingleThreadExecutor() private val dispatcher = executor.asCoroutineDispatcher() + var supportsPSTNProtocol: Boolean = false + private set private val rootEglBase by lazy { EglUtils.rootEglBase } private var isInBackground: Boolean = true + init { + GlobalScope.launch { + supportsPSTNProtocol = currentSession?.supportPSTN(3).orFalse() + if (supportsPSTNProtocol) { + pstnSupportListeners.forEach { it.onPSTNSupportUpdated() } + } + } + } + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun entersForeground() { isInBackground = false