mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Handle safety number changes in a group call context.
This commit is contained in:
committed by
Greyson Parrelli
parent
112782ccaf
commit
42d61518b3
@@ -138,6 +138,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
public static final String EXTRA_GROUP_CALL_UPDATE_SENDER = "group_call_update_sender";
|
||||
public static final String EXTRA_GROUP_CALL_UPDATE_GROUP = "group_call_update_group";
|
||||
public static final String EXTRA_GROUP_CALL_ERA_ID = "era_id";
|
||||
public static final String EXTRA_RECIPIENT_IDS = "recipient_ids";
|
||||
|
||||
public static final String ACTION_PRE_JOIN_CALL = "CALL_PRE_JOIN";
|
||||
public static final String ACTION_CANCEL_PRE_JOIN_CALL = "CANCEL_PRE_JOIN_CALL";
|
||||
@@ -203,6 +204,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
public static final String ACTION_GROUP_CALL_ENDED = "GROUP_CALL_ENDED";
|
||||
public static final String ACTION_GROUP_CALL_UPDATE_MESSAGE = "GROUP_CALL_UPDATE_MESSAGE";
|
||||
public static final String ACTION_GROUP_CALL_PEEK = "GROUP_CALL_PEEK";
|
||||
public static final String ACTION_GROUP_MESSAGE_SENT_ERROR = "GROUP_MESSAGE_SENT_ERROR";
|
||||
public static final String ACTION_GROUP_APPROVE_SAFETY_CHANGE = "GROUP_APPROVE_SAFETY_CHANGE";
|
||||
|
||||
public static final int BUSY_TONE_LENGTH = 2000;
|
||||
|
||||
@@ -436,7 +439,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
state.getLocalDeviceState().isMicrophoneEnabled(),
|
||||
state.getCallSetupState().isRemoteVideoOffer(),
|
||||
state.getCallInfoState().getCallConnectedTime(),
|
||||
state.getCallInfoState().getRemoteCallParticipants()));
|
||||
state.getCallInfoState().getRemoteCallParticipants(),
|
||||
state.getCallInfoState().getIdentityChangedRecipients()));
|
||||
}
|
||||
|
||||
private @NonNull ListenableFutureTask<Boolean> sendMessage(@NonNull final RemotePeer remotePeer,
|
||||
@@ -669,7 +673,36 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
}
|
||||
|
||||
public void sendOpaqueCallMessage(@NonNull UUID uuid, @NonNull SignalServiceCallMessage opaqueMessage) {
|
||||
sendMessage(new RemotePeer(RecipientId.from(uuid, null)), opaqueMessage);
|
||||
RecipientId recipientId = RecipientId.from(uuid, null);
|
||||
ListenableFutureTask<Boolean> listenableFutureTask = sendMessage(new RemotePeer(recipientId), opaqueMessage);
|
||||
listenableFutureTask.addListener(new FutureTaskListener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
// intentionally left blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException exception) {
|
||||
Throwable error = exception.getCause();
|
||||
|
||||
Log.i(TAG, "sendOpaqueCallMessage onFailure: ", error);
|
||||
|
||||
Intent intent = new Intent(WebRtcCallService.this, WebRtcCallService.class);
|
||||
intent.setAction(ACTION_GROUP_MESSAGE_SENT_ERROR);
|
||||
|
||||
WebRtcViewModel.State state = WebRtcViewModel.State.NETWORK_FAILURE;
|
||||
|
||||
if (error instanceof UntrustedIdentityException) {
|
||||
intent.putExtra(EXTRA_ERROR_IDENTITY_KEY, new IdentityKeyParcelable(((UntrustedIdentityException) error).getIdentityKey()));
|
||||
state = WebRtcViewModel.State.UNTRUSTED_IDENTITY;
|
||||
}
|
||||
|
||||
intent.putExtra(EXTRA_ERROR_CALL_STATE, state);
|
||||
intent.putExtra(EXTRA_REMOTE_PEER, new RemotePeer(recipientId));
|
||||
|
||||
startService(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void sendGroupCallMessage(@NonNull Recipient recipient, @Nullable String groupCallEraId) {
|
||||
@@ -739,13 +772,13 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
}
|
||||
|
||||
public void updateGroupCallUpdateMessage(@NonNull RecipientId groupId, @Nullable String groupCallEraId, @NonNull Collection<UUID> joinedMembers, boolean isCallFull) {
|
||||
DatabaseFactory.getSmsDatabase(this).insertOrUpdateGroupCall(groupId,
|
||||
Recipient.self().getId(),
|
||||
System.currentTimeMillis(),
|
||||
null,
|
||||
groupCallEraId,
|
||||
joinedMembers,
|
||||
isCallFull);
|
||||
SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getSmsDatabase(this).insertOrUpdateGroupCall(groupId,
|
||||
Recipient.self().getId(),
|
||||
System.currentTimeMillis(),
|
||||
null,
|
||||
groupCallEraId,
|
||||
joinedMembers,
|
||||
isCallFull));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,16 +9,21 @@ import com.annimon.stream.Stream;
|
||||
import org.signal.ringrtc.CallException;
|
||||
import org.signal.ringrtc.GroupCall;
|
||||
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
|
||||
import org.thoughtcrime.securesms.components.webrtc.GroupCallSafetyNumberChangeNotificationUtil;
|
||||
import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.CallParticipantId;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder;
|
||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
||||
import org.webrtc.VideoTrack;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OpaqueMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||
@@ -201,6 +206,47 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleGroupMessageSentError(@NonNull WebRtcServiceState currentState,
|
||||
@NonNull RemotePeer remotePeer,
|
||||
@NonNull WebRtcViewModel.State errorCallState,
|
||||
@NonNull Optional<IdentityKey> identityKey)
|
||||
{
|
||||
Log.w(tag, "handleGroupMessageSentError(): error: " + errorCallState);
|
||||
|
||||
if (errorCallState == WebRtcViewModel.State.UNTRUSTED_IDENTITY) {
|
||||
return currentState.builder()
|
||||
.changeCallInfoState()
|
||||
.addIdentityChangedRecipient(remotePeer.getId())
|
||||
.build();
|
||||
}
|
||||
|
||||
return currentState;
|
||||
}
|
||||
|
||||
protected @NonNull WebRtcServiceState handleGroupApproveSafetyNumberChange(@NonNull WebRtcServiceState currentState,
|
||||
@NonNull List<RecipientId> recipientIds)
|
||||
{
|
||||
Log.i(tag, "handleGroupApproveSafetyNumberChange():");
|
||||
|
||||
GroupCall groupCall = currentState.getCallInfoState().getGroupCall();
|
||||
|
||||
if (groupCall != null) {
|
||||
currentState = currentState.builder()
|
||||
.changeCallInfoState()
|
||||
.removeIdentityChangedRecipients(recipientIds)
|
||||
.build();
|
||||
|
||||
try {
|
||||
groupCall.resendMediaKeys();
|
||||
} catch (CallException e) {
|
||||
return groupCallFailure(currentState, "Unable to resend media keys", e);
|
||||
}
|
||||
}
|
||||
|
||||
return currentState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleGroupCallEnded(@NonNull WebRtcServiceState currentState, int groupCallHash, @NonNull GroupCall.GroupCallEndReason groupCallEndReason) {
|
||||
Log.i(tag, "handleGroupCallEnded(): reason: " + groupCallEndReason);
|
||||
@@ -269,6 +315,8 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
WebRtcVideoUtil.deinitializeVideo(currentState);
|
||||
|
||||
GroupCallSafetyNumberChangeNotificationUtil.cancelNotification(context, currentState.getCallInfoState().getCallRecipient());
|
||||
|
||||
return new WebRtcServiceState(new IdleActionProcessor(webRtcInteractor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.ringrtc.CallState;
|
||||
import org.thoughtcrime.securesms.ringrtc.CameraState;
|
||||
@@ -60,11 +61,13 @@ import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_ENDED_
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_ENDED_SIGNALING_FAILURE;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_ENDED_TIMEOUT;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_FLIP_CAMERA;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_APPROVE_SAFETY_CHANGE;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_CALL_ENDED;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_CALL_PEEK;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_CALL_UPDATE_MESSAGE;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_JOINED_MEMBERSHIP_CHANGED;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_LOCAL_DEVICE_STATE_CHANGED;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_MESSAGE_SENT_ERROR;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_REMOTE_DEVICE_STATE_CHANGED;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_REQUEST_MEMBERSHIP_PROOF;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_GROUP_REQUEST_UPDATE_MEMBERS;
|
||||
@@ -108,6 +111,7 @@ import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_ANSWER_
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_BLUETOOTH;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_IS_ALWAYS_TURN;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_MUTE;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_RECIPIENT_IDS;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_RESULT_RECEIVER;
|
||||
import static org.thoughtcrime.securesms.service.WebRtcCallService.EXTRA_SPEAKER;
|
||||
import static org.thoughtcrime.securesms.service.webrtc.WebRtcData.AnswerMetadata;
|
||||
@@ -240,6 +244,8 @@ public abstract class WebRtcActionProcessor {
|
||||
case ACTION_GROUP_CALL_ENDED: return handleGroupCallEnded(currentState, getGroupCallHash(intent), getGroupCallEndReason(intent));
|
||||
case ACTION_GROUP_CALL_UPDATE_MESSAGE: return handleGroupCallUpdateMessage(currentState, GroupCallUpdateMetadata.fromIntent(intent));
|
||||
case ACTION_GROUP_CALL_PEEK: return handleGroupCallPeek(currentState, getRemotePeer(intent));
|
||||
case ACTION_GROUP_MESSAGE_SENT_ERROR: return handleGroupMessageSentError(currentState, getRemotePeer(intent), getErrorCallState(intent), getErrorIdentityKey(intent));
|
||||
case ACTION_GROUP_APPROVE_SAFETY_CHANGE: return handleGroupApproveSafetyNumberChange(currentState, RecipientId.fromSerializedList(intent.getStringExtra(EXTRA_RECIPIENT_IDS)));
|
||||
|
||||
case ACTION_HTTP_SUCCESS: return handleHttpSuccess(currentState, HttpData.fromIntent(intent));
|
||||
case ACTION_HTTP_FAILURE: return handleHttpFailure(currentState, HttpData.fromIntent(intent));
|
||||
@@ -734,6 +740,22 @@ public abstract class WebRtcActionProcessor {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
protected @NonNull WebRtcServiceState handleGroupMessageSentError(@NonNull WebRtcServiceState currentState,
|
||||
@NonNull RemotePeer remotePeer,
|
||||
@NonNull WebRtcViewModel.State errorCallState,
|
||||
@NonNull Optional<IdentityKey> identityKey)
|
||||
{
|
||||
Log.i(tag, "handleGroupMessageSentError not processed");
|
||||
return currentState;
|
||||
}
|
||||
|
||||
protected @NonNull WebRtcServiceState handleGroupApproveSafetyNumberChange(@NonNull WebRtcServiceState currentState,
|
||||
@NonNull List<RecipientId> recipientIds)
|
||||
{
|
||||
Log.i(tag, "handleGroupApproveSafetyNumberChange not processed");
|
||||
return currentState;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
protected @NonNull WebRtcServiceState handleHttpSuccess(@NonNull WebRtcServiceState currentState, @NonNull HttpData httpData) {
|
||||
|
||||
@@ -8,15 +8,18 @@ import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.CallParticipantId;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* General state of ongoing calls.
|
||||
@@ -31,13 +34,30 @@ public class CallInfoState {
|
||||
RemotePeer activePeer;
|
||||
GroupCall groupCall;
|
||||
WebRtcViewModel.GroupCallState groupState;
|
||||
Set<RecipientId> identityChangedRecipients;
|
||||
|
||||
public CallInfoState() {
|
||||
this(WebRtcViewModel.State.IDLE, Recipient.UNKNOWN, -1, Collections.emptyMap(), Collections.emptyMap(), null, null, WebRtcViewModel.GroupCallState.IDLE);
|
||||
this(WebRtcViewModel.State.IDLE,
|
||||
Recipient.UNKNOWN,
|
||||
-1,
|
||||
Collections.emptyMap(),
|
||||
Collections.emptyMap(),
|
||||
null,
|
||||
null,
|
||||
WebRtcViewModel.GroupCallState.IDLE,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
public CallInfoState(@NonNull CallInfoState toCopy) {
|
||||
this(toCopy.callState, toCopy.callRecipient, toCopy.callConnectedTime, toCopy.remoteParticipants, toCopy.peerMap, toCopy.activePeer, toCopy.groupCall, toCopy.groupState);
|
||||
this(toCopy.callState,
|
||||
toCopy.callRecipient,
|
||||
toCopy.callConnectedTime,
|
||||
toCopy.remoteParticipants,
|
||||
toCopy.peerMap,
|
||||
toCopy.activePeer,
|
||||
toCopy.groupCall,
|
||||
toCopy.groupState,
|
||||
toCopy.identityChangedRecipients);
|
||||
}
|
||||
|
||||
public CallInfoState(@NonNull WebRtcViewModel.State callState,
|
||||
@@ -47,16 +67,18 @@ public class CallInfoState {
|
||||
@NonNull Map<Integer, RemotePeer> peerMap,
|
||||
@Nullable RemotePeer activePeer,
|
||||
@Nullable GroupCall groupCall,
|
||||
@NonNull WebRtcViewModel.GroupCallState groupState)
|
||||
@NonNull WebRtcViewModel.GroupCallState groupState,
|
||||
@NonNull Set<RecipientId> identityChangedRecipients)
|
||||
{
|
||||
this.callState = callState;
|
||||
this.callRecipient = callRecipient;
|
||||
this.callConnectedTime = callConnectedTime;
|
||||
this.remoteParticipants = new LinkedHashMap<>(remoteParticipants);
|
||||
this.peerMap = new HashMap<>(peerMap);
|
||||
this.activePeer = activePeer;
|
||||
this.groupCall = groupCall;
|
||||
this.groupState = groupState;
|
||||
this.callState = callState;
|
||||
this.callRecipient = callRecipient;
|
||||
this.callConnectedTime = callConnectedTime;
|
||||
this.remoteParticipants = new LinkedHashMap<>(remoteParticipants);
|
||||
this.peerMap = new HashMap<>(peerMap);
|
||||
this.activePeer = activePeer;
|
||||
this.groupCall = groupCall;
|
||||
this.groupState = groupState;
|
||||
this.identityChangedRecipients = new HashSet<>(identityChangedRecipients);
|
||||
}
|
||||
|
||||
public @NonNull Recipient getCallRecipient() {
|
||||
@@ -110,4 +132,8 @@ public class CallInfoState {
|
||||
public @NonNull WebRtcViewModel.GroupCallState getGroupCallState() {
|
||||
return groupState;
|
||||
}
|
||||
|
||||
public @NonNull Set<RecipientId> getIdentityChangedRecipients() {
|
||||
return identityChangedRecipients;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,15 @@ import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.CallParticipantId;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.ringrtc.Camera;
|
||||
import org.thoughtcrime.securesms.ringrtc.CameraState;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcActionProcessor;
|
||||
import org.webrtc.EglBase;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Builder that creates a new {@link WebRtcServiceState} from an existing one and allows
|
||||
* changes to all normally immutable data.
|
||||
@@ -243,5 +246,15 @@ public class WebRtcServiceStateBuilder {
|
||||
toBuild.groupState = groupState;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull CallInfoStateBuilder addIdentityChangedRecipient(@NonNull RecipientId id) {
|
||||
toBuild.identityChangedRecipients.add(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull CallInfoStateBuilder removeIdentityChangedRecipients(@NonNull Collection<RecipientId> ids) {
|
||||
toBuild.identityChangedRecipients.removeAll(ids);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user