mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Add call disposition syncing.
This commit is contained in:
committed by
Greyson Parrelli
parent
d471647e12
commit
06b414f4ef
@@ -0,0 +1,36 @@
|
||||
package org.thoughtcrime.securesms.service.webrtc
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.CallEvent
|
||||
|
||||
/**
|
||||
* Helper for creating call event sync messages.
|
||||
*/
|
||||
object CallEventSyncMessageUtil {
|
||||
@JvmStatic
|
||||
fun createAcceptedSyncMessage(remotePeer: RemotePeer, timestamp: Long, isOutgoing: Boolean, isVideoCall: Boolean): CallEvent {
|
||||
return CallEvent
|
||||
.newBuilder()
|
||||
.setPeerUuid(Recipient.resolved(remotePeer.id).requireServiceId().toByteString())
|
||||
.setId(remotePeer.callId.longValue())
|
||||
.setTimestamp(timestamp)
|
||||
.setType(if (isVideoCall) CallEvent.Type.VIDEO_CALL else CallEvent.Type.AUDIO_CALL)
|
||||
.setDirection(if (isOutgoing) CallEvent.Direction.OUTGOING else CallEvent.Direction.INCOMING)
|
||||
.setEvent(CallEvent.Event.ACCEPTED)
|
||||
.build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createNotAcceptedSyncMessage(remotePeer: RemotePeer, timestamp: Long, isOutgoing: Boolean, isVideoCall: Boolean): CallEvent {
|
||||
return CallEvent
|
||||
.newBuilder()
|
||||
.setPeerUuid(Recipient.resolved(remotePeer.id).requireServiceId().toByteString())
|
||||
.setId(remotePeer.callId.longValue())
|
||||
.setTimestamp(timestamp)
|
||||
.setType(if (isVideoCall) CallEvent.Type.VIDEO_CALL else CallEvent.Type.AUDIO_CALL)
|
||||
.setDirection(if (isOutgoing) CallEvent.Direction.OUTGOING else CallEvent.Direction.INCOMING)
|
||||
.setEvent(CallEvent.Event.NOT_ACCEPTED)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,12 @@ public class CallSetupActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
|
||||
RemotePeer activePeer = currentState.getCallInfoState().requireActivePeer();
|
||||
|
||||
webRtcInteractor.sendAcceptedCallEventSyncMessage(
|
||||
activePeer,
|
||||
currentState.getCallInfoState().getCallState() == WebRtcViewModel.State.CALL_RINGING,
|
||||
currentState.getCallSetupState(activePeer).isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled()
|
||||
);
|
||||
|
||||
ApplicationDependencies.getAppForegroundObserver().removeListener(webRtcInteractor.getForegroundListener());
|
||||
webRtcInteractor.startAudioCommunication();
|
||||
webRtcInteractor.activateCall(activePeer.getId());
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.signal.ringrtc.CallException;
|
||||
import org.signal.ringrtc.CallId;
|
||||
import org.signal.ringrtc.CallManager;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
@@ -130,8 +131,6 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
Log.i(TAG, "handleAcceptCall(): call_id: " + activePeer.getCallId());
|
||||
|
||||
SignalDatabase.messages().insertReceivedCall(activePeer.getId(), currentState.getCallSetupState(activePeer).isRemoteVideoOffer());
|
||||
|
||||
currentState = currentState.builder()
|
||||
.changeCallSetupState(activePeer.getCallId())
|
||||
.acceptWithVideo(answerWithVideo)
|
||||
@@ -156,10 +155,13 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
Log.i(TAG, "handleDenyCall():");
|
||||
|
||||
webRtcInteractor.sendNotAcceptedCallEventSyncMessage(activePeer,
|
||||
false,
|
||||
currentState.getCallSetupState(activePeer).isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled());
|
||||
|
||||
try {
|
||||
webRtcInteractor.rejectIncomingCall(activePeer.getId());
|
||||
webRtcInteractor.getCallManager().hangup();
|
||||
SignalDatabase.messages().insertMissedCall(activePeer.getId(), System.currentTimeMillis(), currentState.getCallSetupState(activePeer).isRemoteVideoOffer());
|
||||
return terminate(currentState, activePeer);
|
||||
} catch (CallException e) {
|
||||
return callFailure(currentState, "hangup() failed: ", e);
|
||||
@@ -173,6 +175,14 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
Recipient recipient = remotePeer.getRecipient();
|
||||
|
||||
activePeer.localRinging();
|
||||
|
||||
SignalDatabase.calls().insertCall(remotePeer.getCallId().longValue(),
|
||||
System.currentTimeMillis(),
|
||||
remotePeer.getId(),
|
||||
currentState.getCallSetupState(activePeer).isRemoteVideoOffer() ? CallTable.Type.VIDEO_CALL : CallTable.Type.AUDIO_CALL,
|
||||
CallTable.Direction.INCOMING,
|
||||
CallTable.Event.ONGOING);
|
||||
|
||||
webRtcInteractor.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
||||
|
||||
boolean shouldDisturbUserWithCall = DoNotDisturbUtil.shouldDisturbUserWithCall(context.getApplicationContext(), recipient);
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.signal.ringrtc.CallException;
|
||||
import org.signal.ringrtc.CallId;
|
||||
import org.signal.ringrtc.CallManager;
|
||||
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
@@ -83,7 +84,13 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
}
|
||||
|
||||
RecipientUtil.setAndSendUniversalExpireTimerIfNecessary(context, Recipient.resolved(remotePeer.getId()), SignalDatabase.threads().getThreadIdIfExistsFor(remotePeer.getId()));
|
||||
SignalDatabase.messages().insertOutgoingCall(remotePeer.getId(), isVideoCall);
|
||||
|
||||
SignalDatabase.calls().insertCall(remotePeer.getCallId().longValue(),
|
||||
System.currentTimeMillis(),
|
||||
remotePeer.getId(),
|
||||
isVideoCall ? CallTable.Type.VIDEO_CALL : CallTable.Type.AUDIO_CALL,
|
||||
CallTable.Direction.OUTGOING,
|
||||
CallTable.Event.ONGOING);
|
||||
|
||||
EglBaseWrapper.replaceHolder(EglBaseWrapper.OUTGOING_PLACEHOLDER, remotePeer.getCallId().longValue());
|
||||
|
||||
@@ -236,6 +243,13 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleLocalHangup(@NonNull WebRtcServiceState currentState) {
|
||||
RemotePeer activePeer = currentState.getCallInfoState().getActivePeer();
|
||||
if (activePeer != null) {
|
||||
webRtcInteractor.sendNotAcceptedCallEventSyncMessage(activePeer,
|
||||
true,
|
||||
currentState.getCallSetupState(activePeer).isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled());
|
||||
}
|
||||
|
||||
return activeCallDelegate.handleLocalHangup(currentState);
|
||||
}
|
||||
|
||||
@@ -246,6 +260,19 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleEndedRemote(@NonNull WebRtcServiceState currentState, @NonNull CallManager.CallEvent endedRemoteEvent, @NonNull RemotePeer remotePeer) {
|
||||
RemotePeer activePeer = currentState.getCallInfoState().getActivePeer();
|
||||
if (activePeer != null &&
|
||||
(endedRemoteEvent == CallManager.CallEvent.ENDED_REMOTE_HANGUP ||
|
||||
endedRemoteEvent == CallManager.CallEvent.ENDED_REMOTE_HANGUP_NEED_PERMISSION ||
|
||||
endedRemoteEvent == CallManager.CallEvent.ENDED_REMOTE_BUSY ||
|
||||
endedRemoteEvent == CallManager.CallEvent.ENDED_TIMEOUT ||
|
||||
endedRemoteEvent == CallManager.CallEvent.ENDED_REMOTE_GLARE))
|
||||
{
|
||||
webRtcInteractor.sendNotAcceptedCallEventSyncMessage(activePeer,
|
||||
true,
|
||||
currentState.getCallSetupState(activePeer).isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled());
|
||||
}
|
||||
|
||||
return activeCallDelegate.handleEndedRemote(currentState, endedRemoteEvent, remotePeer);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.signal.storageservice.protos.groups.GroupExternalCredential;
|
||||
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.events.GroupCallPeekEvent;
|
||||
@@ -66,8 +67,10 @@ import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OpaqueMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
@@ -521,7 +524,7 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
Log.i(TAG, "Ignoring event: " + event);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unexpected event: " + event.toString());
|
||||
throw new AssertionError("Unexpected event: " + event);
|
||||
}
|
||||
|
||||
return s;
|
||||
@@ -825,18 +828,28 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
});
|
||||
}
|
||||
|
||||
public void insertMissedCall(@NonNull RemotePeer remotePeer, boolean signal, long timestamp, boolean isVideoOffer) {
|
||||
Pair<Long, Long> messageAndThreadId = SignalDatabase.messages().insertMissedCall(remotePeer.getId(), timestamp, isVideoOffer);
|
||||
public void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) {
|
||||
CallTable.Call call = SignalDatabase.calls()
|
||||
.updateCall(remotePeer.getCallId().longValue(), CallTable.Event.MISSED);
|
||||
|
||||
ApplicationDependencies.getMessageNotifier()
|
||||
.updateNotification(context, ConversationId.forConversation(messageAndThreadId.second()), signal);
|
||||
if (call == null) {
|
||||
CallTable.Type type = isVideoOffer ? CallTable.Type.VIDEO_CALL : CallTable.Type.AUDIO_CALL;
|
||||
|
||||
SignalDatabase.calls()
|
||||
.insertCall(remotePeer.getCallId().longValue(), timestamp, remotePeer.getId(), type, CallTable.Direction.INCOMING, CallTable.Event.MISSED);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertReceivedCall(@NonNull RemotePeer remotePeer, boolean signal, boolean isVideoOffer) {
|
||||
Pair<Long, Long> messageAndThreadId = SignalDatabase.messages().insertReceivedCall(remotePeer.getId(), isVideoOffer);
|
||||
public void insertReceivedCall(@NonNull RemotePeer remotePeer, boolean isVideoOffer) {
|
||||
CallTable.Call call = SignalDatabase.calls()
|
||||
.updateCall(remotePeer.getCallId().longValue(), CallTable.Event.ACCEPTED);
|
||||
|
||||
ApplicationDependencies.getMessageNotifier()
|
||||
.updateNotification(context, ConversationId.forConversation(messageAndThreadId.second()), signal);
|
||||
if (call == null) {
|
||||
CallTable.Type type = isVideoOffer ? CallTable.Type.VIDEO_CALL : CallTable.Type.AUDIO_CALL;
|
||||
|
||||
SignalDatabase.calls()
|
||||
.insertCall(remotePeer.getCallId().longValue(), System.currentTimeMillis(), remotePeer.getId(), type, CallTable.Direction.INCOMING, CallTable.Event.ACCEPTED);
|
||||
}
|
||||
}
|
||||
|
||||
public void retrieveTurnServers(@NonNull RemotePeer remotePeer) {
|
||||
@@ -919,6 +932,40 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
});
|
||||
}
|
||||
|
||||
public void sendAcceptedCallEventSyncMessage(@NonNull RemotePeer remotePeer, boolean isOutgoing, boolean isVideoCall) {
|
||||
SignalDatabase
|
||||
.calls()
|
||||
.updateCall(remotePeer.getCallId().longValue(), CallTable.Event.ACCEPTED);
|
||||
|
||||
if (TextSecurePreferences.isMultiDevice(context)) {
|
||||
networkExecutor.execute(() -> {
|
||||
try {
|
||||
SyncMessage.CallEvent callEvent = CallEventSyncMessageUtil.createAcceptedSyncMessage(remotePeer, System.currentTimeMillis(), isOutgoing, isVideoCall);
|
||||
ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(SignalServiceSyncMessage.forCallEvent(callEvent), Optional.empty());
|
||||
} catch (IOException | UntrustedIdentityException e) {
|
||||
Log.w(TAG, "Unable to send call event sync message for " + remotePeer.getCallId().longValue(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void sendNotAcceptedCallEventSyncMessage(@NonNull RemotePeer remotePeer, boolean isOutgoing, boolean isVideoCall) {
|
||||
SignalDatabase
|
||||
.calls()
|
||||
.updateCall(remotePeer.getCallId().longValue(), CallTable.Event.NOT_ACCEPTED);
|
||||
|
||||
if (TextSecurePreferences.isMultiDevice(context)) {
|
||||
networkExecutor.execute(() -> {
|
||||
try {
|
||||
SyncMessage.CallEvent callEvent = CallEventSyncMessageUtil.createNotAcceptedSyncMessage(remotePeer, System.currentTimeMillis(), isOutgoing, isVideoCall);
|
||||
ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(SignalServiceSyncMessage.forCallEvent(callEvent), Optional.empty());
|
||||
} catch (IOException | UntrustedIdentityException e) {
|
||||
Log.w(TAG, "Unable to send call event sync message for " + remotePeer.getCallId().longValue(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void processSendMessageFailureWithChangeDetection(@NonNull RemotePeer remotePeer,
|
||||
@NonNull ProcessAction failureProcessAction)
|
||||
{
|
||||
|
||||
@@ -109,11 +109,11 @@ public class WebRtcInteractor {
|
||||
}
|
||||
|
||||
void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) {
|
||||
signalCallManager.insertMissedCall(remotePeer, true, timestamp, isVideoOffer);
|
||||
signalCallManager.insertMissedCall(remotePeer, timestamp, isVideoOffer);
|
||||
}
|
||||
|
||||
void insertReceivedCall(@NonNull RemotePeer remotePeer, boolean isVideoOffer) {
|
||||
signalCallManager.insertReceivedCall(remotePeer, true, isVideoOffer);
|
||||
signalCallManager.insertReceivedCall(remotePeer, isVideoOffer);
|
||||
}
|
||||
|
||||
boolean startWebRtcCallActivityIfPossible() {
|
||||
@@ -187,4 +187,12 @@ public class WebRtcInteractor {
|
||||
public void requestGroupMembershipProof(GroupId.V2 groupId, int groupCallHashCode) {
|
||||
signalCallManager.requestGroupMembershipToken(groupId, groupCallHashCode);
|
||||
}
|
||||
|
||||
public void sendAcceptedCallEventSyncMessage(@NonNull RemotePeer remotePeer, boolean isOutgoing, boolean isVideoCall) {
|
||||
signalCallManager.sendAcceptedCallEventSyncMessage(remotePeer, isOutgoing, isVideoCall);
|
||||
}
|
||||
|
||||
public void sendNotAcceptedCallEventSyncMessage(@NonNull RemotePeer remotePeer, boolean isOutgoing, boolean isVideoCall) {
|
||||
signalCallManager.sendNotAcceptedCallEventSyncMessage(remotePeer, isOutgoing, isVideoCall);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user