Asserted identity: handle if needed and use the data
This commit is contained in:
parent
0098d435b3
commit
0eca809b83
@ -144,6 +144,10 @@ android {
|
|||||||
|
|
||||||
buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
|
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"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// Keep abiFilter for the universalApk
|
// Keep abiFilter for the universalApk
|
||||||
|
@ -221,7 +221,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
|
|||||||
views.callStatusText.setText(R.string.call_held_by_you)
|
views.callStatusText.setText(R.string.call_held_by_you)
|
||||||
} else {
|
} else {
|
||||||
views.callActionText.isInvisible = true
|
views.callActionText.isInvisible = true
|
||||||
state.callInfo.otherUserItem?.let {
|
state.callInfo?.opponentUserItem?.let {
|
||||||
views.callStatusText.text = getString(R.string.call_held_by_user, it.getBestName())
|
views.callStatusText.text = getString(R.string.call_held_by_user, it.getBestName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) {
|
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)
|
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
|
||||||
avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter)
|
avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter)
|
||||||
if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) {
|
if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) {
|
||||||
@ -269,13 +269,13 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
|
|||||||
avatarRenderer.render(it, views.otherMemberAvatar)
|
avatarRenderer.render(it, views.otherMemberAvatar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state.otherKnownCallInfo?.otherUserItem == null) {
|
if (state.otherKnownCallInfo?.opponentUserItem == null) {
|
||||||
views.otherKnownCallLayout.isVisible = false
|
views.otherKnownCallLayout.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId)
|
val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId)
|
||||||
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
|
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
|
||||||
avatarRenderer.renderBlur(
|
avatarRenderer.renderBlur(
|
||||||
matrixItem = state.otherKnownCallInfo.otherUserItem,
|
matrixItem = state.otherKnownCallInfo.opponentUserItem,
|
||||||
imageView = views.otherKnownCallAvatarView,
|
imageView = views.otherKnownCallAvatarView,
|
||||||
sampling = 20,
|
sampling = 20,
|
||||||
rounded = false,
|
rounded = false,
|
||||||
|
@ -34,11 +34,13 @@ import im.vector.app.features.call.webrtc.getOpponentAsMatrixItem
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
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.Session
|
||||||
import org.matrix.android.sdk.api.session.call.CallState
|
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.MxCall
|
||||||
import org.matrix.android.sdk.api.session.call.MxPeerConnectionState
|
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.session.room.model.call.supportCallTransfer
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
class VectorCallViewModel @AssistedInject constructor(
|
class VectorCallViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: VectorCallViewState,
|
@Assisted initialState: VectorCallViewState,
|
||||||
@ -87,6 +89,12 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun assertedIdentityChanged(){
|
||||||
|
setState {
|
||||||
|
copy(callInfo = call?.extractCallInfo())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStateUpdate(call: MxCall) {
|
override fun onStateUpdate(call: MxCall) {
|
||||||
val callState = call.state
|
val callState = call.state
|
||||||
if (callState is CallState.Connected && callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
|
if (callState is CallState.Connected && callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
|
||||||
@ -160,8 +168,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||||||
if (otherCall == null) {
|
if (otherCall == null) {
|
||||||
copy(otherKnownCallInfo = null)
|
copy(otherKnownCallInfo = null)
|
||||||
} else {
|
} else {
|
||||||
val otherUserItem = otherCall.getOpponentAsMatrixItem(session)
|
copy(otherKnownCallInfo = otherCall.extractCallInfo())
|
||||||
copy(otherKnownCallInfo = VectorCallViewState.CallInfo(otherCall.callId, otherUserItem))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,7 +182,6 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||||||
} else {
|
} else {
|
||||||
call = webRtcCall
|
call = webRtcCall
|
||||||
callManager.addCurrentCallListener(currentCallListener)
|
callManager.addCurrentCallListener(currentCallListener)
|
||||||
val item = webRtcCall.getOpponentAsMatrixItem(session)
|
|
||||||
webRtcCall.addListener(callListener)
|
webRtcCall.addListener(callListener)
|
||||||
val currentSoundDevice = callManager.audioManager.selectedDevice
|
val currentSoundDevice = callManager.audioManager.selectedDevice
|
||||||
if (currentSoundDevice == CallAudioManager.Device.PHONE) {
|
if (currentSoundDevice == CallAudioManager.Device.PHONE) {
|
||||||
@ -185,7 +191,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||||||
copy(
|
copy(
|
||||||
isVideoCall = webRtcCall.mxCall.isVideoCall,
|
isVideoCall = webRtcCall.mxCall.isVideoCall,
|
||||||
callState = Success(webRtcCall.mxCall.state),
|
callState = Success(webRtcCall.mxCall.state),
|
||||||
callInfo = VectorCallViewState.CallInfo(callId, item),
|
callInfo = webRtcCall.extractCallInfo(),
|
||||||
device = currentSoundDevice ?: CallAudioManager.Device.PHONE,
|
device = currentSoundDevice ?: CallAudioManager.Device.PHONE,
|
||||||
isLocalOnHold = webRtcCall.isLocalOnHold,
|
isLocalOnHold = webRtcCall.isLocalOnHold,
|
||||||
isRemoteOnHold = webRtcCall.remoteOnHold,
|
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() {
|
override fun onCleared() {
|
||||||
callManager.removeCurrentCallListener(currentCallListener)
|
callManager.removeCurrentCallListener(currentCallListener)
|
||||||
call?.removeListener(callListener)
|
call?.removeListener(callListener)
|
||||||
|
@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async
|
|||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import im.vector.app.features.call.audio.CallAudioManager
|
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.session.call.CallState
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ data class VectorCallViewState(
|
|||||||
val availableDevices: Set<CallAudioManager.Device> = emptySet(),
|
val availableDevices: Set<CallAudioManager.Device> = emptySet(),
|
||||||
val callState: Async<CallState> = Uninitialized,
|
val callState: Async<CallState> = Uninitialized,
|
||||||
val otherKnownCallInfo: CallInfo? = null,
|
val otherKnownCallInfo: CallInfo? = null,
|
||||||
val callInfo: CallInfo = CallInfo(callId),
|
val callInfo: CallInfo? = null,
|
||||||
val formattedDuration: String = "",
|
val formattedDuration: String = "",
|
||||||
val canOpponentBeTransferred: Boolean = false,
|
val canOpponentBeTransferred: Boolean = false,
|
||||||
val transferee: TransfereeState = TransfereeState.NoTransferee
|
val transferee: TransfereeState = TransfereeState.NoTransferee
|
||||||
@ -53,7 +54,7 @@ data class VectorCallViewState(
|
|||||||
|
|
||||||
data class CallInfo(
|
data class CallInfo(
|
||||||
val callId: String,
|
val callId: String,
|
||||||
val otherUserItem: MatrixItem? = null
|
val opponentUserItem: MatrixItem? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(callArgs: CallArgs) : this(
|
constructor(callArgs: CallArgs) : this(
|
||||||
|
@ -27,6 +27,7 @@ import im.vector.app.features.call.CameraProxy
|
|||||||
import im.vector.app.features.call.CameraType
|
import im.vector.app.features.call.CameraType
|
||||||
import im.vector.app.features.call.CaptureFormat
|
import im.vector.app.features.call.CaptureFormat
|
||||||
import im.vector.app.features.call.VectorCallActivity
|
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.asWebRTC
|
||||||
import im.vector.app.features.call.utils.awaitCreateAnswer
|
import im.vector.app.features.call.utils.awaitCreateAnswer
|
||||||
import im.vector.app.features.call.utils.awaitCreateOffer
|
import im.vector.app.features.call.utils.awaitCreateOffer
|
||||||
@ -882,12 +883,36 @@ class WebRtcCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
|
fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
|
||||||
if (callAssertedIdentityContent.assertedIdentity == null) return
|
sessionScope?.launch(dispatcher) {
|
||||||
remoteAssertedIdentity = callAssertedIdentityContent.assertedIdentity
|
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 {
|
listeners.forEach {
|
||||||
tryOrNull { it.assertedIdentityChanged() }
|
tryOrNull { it.assertedIdentityChanged() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MxCall.StateListener
|
// MxCall.StateListener
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import androidx.lifecycle.Lifecycle
|
|||||||
import androidx.lifecycle.LifecycleObserver
|
import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import im.vector.app.ActiveSessionDataSource
|
import im.vector.app.ActiveSessionDataSource
|
||||||
|
import im.vector.app.BuildConfig
|
||||||
import im.vector.app.core.services.CallService
|
import im.vector.app.core.services.CallService
|
||||||
import im.vector.app.features.call.VectorCallActivity
|
import im.vector.app.features.call.VectorCallActivity
|
||||||
import im.vector.app.features.call.audio.CallAudioManager
|
import im.vector.app.features.call.audio.CallAudioManager
|
||||||
@ -423,6 +424,9 @@ class WebRtcCallManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
|
override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
|
||||||
|
if(!BuildConfig.handleCallAssertedIdentityEvents){
|
||||||
|
return
|
||||||
|
}
|
||||||
val call = callsByCallId[callAssertedIdentityContent.callId]
|
val call = callsByCallId[callAssertedIdentityContent.callId]
|
||||||
?: return Unit.also {
|
?: return Unit.also {
|
||||||
Timber.w("onCallAssertedIdentityReceived for non active call? ${callAssertedIdentityContent.callId}")
|
Timber.w("onCallAssertedIdentityReceived for non active call? ${callAssertedIdentityContent.callId}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user