From 0eca809b83fc3bf9def1a48bcdae7f4a65cc28b6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 1 Jun 2021 18:12:10 +0200 Subject: [PATCH] Asserted identity: handle if needed and use the data --- vector/build.gradle | 4 +++ .../app/features/call/VectorCallActivity.kt | 8 ++--- .../app/features/call/VectorCallViewModel.kt | 30 ++++++++++++++--- .../app/features/call/VectorCallViewState.kt | 5 +-- .../app/features/call/webrtc/WebRtcCall.kt | 33 ++++++++++++++++--- .../features/call/webrtc/WebRtcCallManager.kt | 4 +++ 6 files changed, 70 insertions(+), 14 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index 8af6e80479..c8399b2fb9 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -144,6 +144,10 @@ android { buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping" + // If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity. + // This *must* only be set in trusted environments. + buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Keep abiFilter for the universalApk diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt index ad04e33414..a18f5bb918 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt @@ -221,7 +221,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro views.callStatusText.setText(R.string.call_held_by_you) } else { views.callActionText.isInvisible = true - state.callInfo.otherUserItem?.let { + state.callInfo?.opponentUserItem?.let { views.callStatusText.text = getString(R.string.call_held_by_user, it.getBestName()) } } @@ -255,7 +255,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro } private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) { - state.callInfo.otherUserItem?.let { + state.callInfo?.opponentUserItem?.let { val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen) avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter) if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) { @@ -269,13 +269,13 @@ class VectorCallActivity : VectorBaseActivity(), CallContro avatarRenderer.render(it, views.otherMemberAvatar) } } - if (state.otherKnownCallInfo?.otherUserItem == null) { + if (state.otherKnownCallInfo?.opponentUserItem == null) { views.otherKnownCallLayout.isVisible = false } else { val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId) val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen) avatarRenderer.renderBlur( - matrixItem = state.otherKnownCallInfo.otherUserItem, + matrixItem = state.otherKnownCallInfo.opponentUserItem, imageView = views.otherKnownCallAvatarView, sampling = 20, rounded = false, diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index 18eda0fd6f..68905b6c49 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -34,11 +34,13 @@ import im.vector.app.features.call.webrtc.getOpponentAsMatrixItem import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.call.CallState import org.matrix.android.sdk.api.session.call.MxCall import org.matrix.android.sdk.api.session.call.MxPeerConnectionState import org.matrix.android.sdk.api.session.room.model.call.supportCallTransfer +import org.matrix.android.sdk.api.util.MatrixItem class VectorCallViewModel @AssistedInject constructor( @Assisted initialState: VectorCallViewState, @@ -87,6 +89,12 @@ class VectorCallViewModel @AssistedInject constructor( } } + override fun assertedIdentityChanged(){ + setState { + copy(callInfo = call?.extractCallInfo()) + } + } + override fun onStateUpdate(call: MxCall) { val callState = call.state if (callState is CallState.Connected && callState.iceConnectionState == MxPeerConnectionState.CONNECTED) { @@ -160,8 +168,7 @@ class VectorCallViewModel @AssistedInject constructor( if (otherCall == null) { copy(otherKnownCallInfo = null) } else { - val otherUserItem = otherCall.getOpponentAsMatrixItem(session) - copy(otherKnownCallInfo = VectorCallViewState.CallInfo(otherCall.callId, otherUserItem)) + copy(otherKnownCallInfo = otherCall.extractCallInfo()) } } } @@ -175,7 +182,6 @@ class VectorCallViewModel @AssistedInject constructor( } else { call = webRtcCall callManager.addCurrentCallListener(currentCallListener) - val item = webRtcCall.getOpponentAsMatrixItem(session) webRtcCall.addListener(callListener) val currentSoundDevice = callManager.audioManager.selectedDevice if (currentSoundDevice == CallAudioManager.Device.PHONE) { @@ -185,7 +191,7 @@ class VectorCallViewModel @AssistedInject constructor( copy( isVideoCall = webRtcCall.mxCall.isVideoCall, callState = Success(webRtcCall.mxCall.state), - callInfo = VectorCallViewState.CallInfo(callId, item), + callInfo = webRtcCall.extractCallInfo(), device = currentSoundDevice ?: CallAudioManager.Device.PHONE, isLocalOnHold = webRtcCall.isLocalOnHold, isRemoteOnHold = webRtcCall.remoteOnHold, @@ -202,6 +208,22 @@ class VectorCallViewModel @AssistedInject constructor( } } + private fun WebRtcCall.extractCallInfo(): VectorCallViewState.CallInfo{ + val assertedIdentity = this.remoteAssertedIdentity + val matrixItem = if(assertedIdentity != null){ + val userId = if (MatrixPatterns.isUserId(assertedIdentity.id)) { + assertedIdentity.id!! + } else { + // Need an id starting with @ + "@${assertedIdentity.displayName}" + } + MatrixItem.UserItem(userId,assertedIdentity.displayName, assertedIdentity.avatarUrl) + }else { + getOpponentAsMatrixItem(session) + } + return VectorCallViewState.CallInfo(callId, matrixItem) + } + override fun onCleared() { callManager.removeCurrentCallListener(currentCallListener) call?.removeListener(callListener) diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt index c5ae61cf60..b6c226564e 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt @@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized import im.vector.app.features.call.audio.CallAudioManager +import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.session.call.CallState import org.matrix.android.sdk.api.util.MatrixItem @@ -39,7 +40,7 @@ data class VectorCallViewState( val availableDevices: Set = emptySet(), val callState: Async = Uninitialized, val otherKnownCallInfo: CallInfo? = null, - val callInfo: CallInfo = CallInfo(callId), + val callInfo: CallInfo? = null, val formattedDuration: String = "", val canOpponentBeTransferred: Boolean = false, val transferee: TransfereeState = TransfereeState.NoTransferee @@ -53,7 +54,7 @@ data class VectorCallViewState( data class CallInfo( val callId: String, - val otherUserItem: MatrixItem? = null + val opponentUserItem: MatrixItem? = null, ) constructor(callArgs: CallArgs) : this( diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt index 319fef87f9..4212a4e789 100644 --- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt @@ -27,6 +27,7 @@ import im.vector.app.features.call.CameraProxy import im.vector.app.features.call.CameraType import im.vector.app.features.call.CaptureFormat import im.vector.app.features.call.VectorCallActivity +import im.vector.app.features.call.lookup.sipNativeLookup import im.vector.app.features.call.utils.asWebRTC import im.vector.app.features.call.utils.awaitCreateAnswer import im.vector.app.features.call.utils.awaitCreateOffer @@ -882,10 +883,34 @@ class WebRtcCall( } fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) { - if (callAssertedIdentityContent.assertedIdentity == null) return - remoteAssertedIdentity = callAssertedIdentityContent.assertedIdentity - listeners.forEach { - tryOrNull { it.assertedIdentityChanged() } + sessionScope?.launch(dispatcher) { + val session = sessionProvider.get() ?: return@launch + val newAssertedIdentity = callAssertedIdentityContent.assertedIdentity ?: return@launch + if (newAssertedIdentity.id == null && newAssertedIdentity.displayName == null) { + Timber.v("Asserted identity received with no relevant information, skip") + return@launch + } + remoteAssertedIdentity = newAssertedIdentity + if (newAssertedIdentity.id != null) { + val nativeUserId = session.sipNativeLookup(newAssertedIdentity.id!!).firstOrNull()?.userId + if (nativeUserId != null) { + val resolvedUser = tryOrNull { + session.resolveUser(nativeUserId) + } + if (resolvedUser != null) { + remoteAssertedIdentity = newAssertedIdentity.copy( + id = nativeUserId, + avatarUrl = resolvedUser.avatarUrl, + displayName = resolvedUser.displayName + ) + } else { + remoteAssertedIdentity = newAssertedIdentity.copy(id = nativeUserId) + } + } + } + listeners.forEach { + tryOrNull { it.assertedIdentityChanged() } + } } } 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 a333d5e81b..d56f1aa015 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 @@ -21,6 +21,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import im.vector.app.ActiveSessionDataSource +import im.vector.app.BuildConfig import im.vector.app.core.services.CallService import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.audio.CallAudioManager @@ -423,6 +424,9 @@ class WebRtcCallManager @Inject constructor( } override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) { + if(!BuildConfig.handleCallAssertedIdentityEvents){ + return + } val call = callsByCallId[callAssertedIdentityContent.callId] ?: return Unit.also { Timber.w("onCallAssertedIdentityReceived for non active call? ${callAssertedIdentityContent.callId}")