mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-20 17:57:29 +00:00
Fix call setup state management bugs.
This commit is contained in:
@@ -84,15 +84,15 @@ class WebRtcViewModel(state: WebRtcServiceState) {
|
||||
val state: State = state.callInfoState.callState
|
||||
val groupState: GroupCallState = state.callInfoState.groupCallState
|
||||
val recipient: Recipient = state.callInfoState.callRecipient
|
||||
val isRemoteVideoOffer: Boolean = state.callSetupState.isRemoteVideoOffer
|
||||
val isRemoteVideoOffer: Boolean = state.getCallSetupState(state.callInfoState.activePeer?.callId).isRemoteVideoOffer
|
||||
val callConnectedTime: Long = state.callInfoState.callConnectedTime
|
||||
val remoteParticipants: List<CallParticipant> = state.callInfoState.remoteCallParticipants
|
||||
val identityChangedParticipants: Set<RecipientId> = state.callInfoState.identityChangedRecipients
|
||||
val remoteDevicesCount: OptionalLong = state.callInfoState.remoteDevicesCount
|
||||
val participantLimit: Long? = state.callInfoState.participantLimit
|
||||
@get:JvmName("shouldRingGroup")
|
||||
val ringGroup: Boolean = state.callSetupState.ringGroup
|
||||
val ringerRecipient: Recipient = state.callSetupState.ringerRecipient
|
||||
val ringGroup: Boolean = state.getCallSetupState(state.callInfoState.activePeer?.callId).ringGroup
|
||||
val ringerRecipient: Recipient = state.getCallSetupState(state.callInfoState.activePeer?.callId).ringerRecipient
|
||||
val activeDevice: SignalAudioManager.AudioDevice = state.localDeviceState.activeDevice
|
||||
val availableDevices: Set<SignalAudioManager.AudioDevice> = state.localDeviceState.availableDevices
|
||||
|
||||
@@ -123,6 +123,7 @@ class WebRtcViewModel(state: WebRtcServiceState) {
|
||||
participantLimit=$participantLimit,
|
||||
activeDevice=$activeDevice,
|
||||
availableDevices=$availableDevices,
|
||||
ringGroup=$ringGroup
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
@@ -551,11 +551,11 @@ public final class MessageContentProcessor {
|
||||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL);
|
||||
} else {
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
|
||||
byte[] remoteIdentityKey = ApplicationDependencies.getIdentityStore().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedOffer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
|
||||
.receivedOffer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
|
||||
new WebRtcData.OfferMetadata(message.getOpaque(), message.getSdp(), message.getType()),
|
||||
new WebRtcData.ReceivedOfferMetadata(remoteIdentityKey,
|
||||
content.getServerReceivedTimestamp(),
|
||||
@@ -569,11 +569,11 @@ public final class MessageContentProcessor {
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content), "handleCallAnswerMessage...");
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
|
||||
byte[] remoteIdentityKey = ApplicationDependencies.getIdentityStore().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedAnswer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
|
||||
.receivedAnswer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
|
||||
new WebRtcData.AnswerMetadata(message.getOpaque(), message.getSdp()),
|
||||
new WebRtcData.ReceivedAnswerMetadata(remoteIdentityKey, content.getCallMessage().get().isMultiRing()));
|
||||
}
|
||||
@@ -592,10 +592,10 @@ public final class MessageContentProcessor {
|
||||
callId = iceMessage.getId();
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(callId));
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedIceCandidates(new WebRtcData.CallMetadata(remotePeer, new CallId(callId), content.getSenderDevice()),
|
||||
.receivedIceCandidates(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
|
||||
iceCandidates);
|
||||
}
|
||||
|
||||
@@ -608,10 +608,10 @@ public final class MessageContentProcessor {
|
||||
if (smsMessageId.isPresent()) {
|
||||
DatabaseFactory.getSmsDatabase(context).markAsMissedCall(smsMessageId.get(), false);
|
||||
} else {
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedCallHangup(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
|
||||
.receivedCallHangup(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
|
||||
new WebRtcData.HangupMetadata(message.getType(), message.isLegacy(), message.getDeviceId()));
|
||||
}
|
||||
}
|
||||
@@ -622,10 +622,10 @@ public final class MessageContentProcessor {
|
||||
{
|
||||
log(String.valueOf(content.getTimestamp()), "handleCallBusyMessage");
|
||||
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedCallBusy(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()));
|
||||
.receivedCallBusy(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()));
|
||||
}
|
||||
|
||||
private void handleCallOpaqueMessage(@NonNull SignalServiceContent content,
|
||||
|
||||
@@ -22,15 +22,22 @@ public final class RemotePeer implements Remote, Parcelable
|
||||
{
|
||||
private static final String TAG = Log.tag(RemotePeer.class);
|
||||
|
||||
public static final CallId NO_CALL_ID = new CallId(-1L);
|
||||
public static final CallId GROUP_CALL_ID = new CallId(-2L);
|
||||
|
||||
@NonNull private final RecipientId recipientId;
|
||||
@NonNull private CallState callState;
|
||||
@NonNull private CallId callId;
|
||||
private long callStartTimestamp;
|
||||
|
||||
public RemotePeer(@NonNull RecipientId recipientId) {
|
||||
this(recipientId, new CallId(-1L));
|
||||
}
|
||||
|
||||
public RemotePeer(@NonNull RecipientId recipientId, @NonNull CallId callId) {
|
||||
this.recipientId = recipientId;
|
||||
this.callState = CallState.IDLE;
|
||||
this.callId = new CallId(-1L);
|
||||
this.callId = callId;
|
||||
this.callStartTimestamp = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
webRtcInteractor.stopForegroundService();
|
||||
}
|
||||
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
|
||||
return terminate(currentState, remotePeer);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
}
|
||||
|
||||
if (incomingBeforeAccept) {
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
}
|
||||
} else if (endedRemoteEvent == CallEvent.ENDED_REMOTE_BUSY && remotePeerIsActive) {
|
||||
activePeer.receivedBusy();
|
||||
@@ -199,11 +199,11 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
ringer.start(OutgoingRinger.Type.BUSY);
|
||||
ThreadUtil.runOnMainDelayed(ringer::stop, SignalCallManager.BUSY_TONE_LENGTH);
|
||||
} else if (endedRemoteEvent == CallEvent.ENDED_REMOTE_GLARE && incomingBeforeAccept) {
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
}
|
||||
|
||||
if (state == WebRtcViewModel.State.CALL_ACCEPTED_ELSEWHERE) {
|
||||
webRtcInteractor.insertReceivedCall(remotePeer, currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertReceivedCall(remotePeer, currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
}
|
||||
|
||||
currentState = currentState.builder()
|
||||
@@ -230,7 +230,7 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
}
|
||||
|
||||
if (remotePeer.getState() == CallState.ANSWERING || remotePeer.getState() == CallState.LOCAL_RINGING) {
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
}
|
||||
|
||||
return terminate(currentState, remotePeer);
|
||||
@@ -261,7 +261,7 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
webRtcInteractor.postStateUpdate(currentState);
|
||||
|
||||
if (activePeer.getState() == CallState.ANSWERING || activePeer.getState() == CallState.LOCAL_RINGING) {
|
||||
webRtcInteractor.insertMissedCall(activePeer, activePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(activePeer, activePeer.getCallStartTimestamp(), currentState.getCallSetupState(activePeer).isRemoteVideoOffer());
|
||||
}
|
||||
|
||||
return terminate(currentState, activePeer);
|
||||
|
||||
@@ -71,11 +71,11 @@ public class CallSetupActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
return callFailure(currentState, "Enabling audio/video failed: ", e);
|
||||
}
|
||||
|
||||
if (currentState.getCallSetupState().isAcceptWithVideo()) {
|
||||
if (currentState.getCallSetupState(activePeer).isAcceptWithVideo()) {
|
||||
currentState = currentState.getActionProcessor().handleSetEnableVideo(currentState, true);
|
||||
}
|
||||
|
||||
if (currentState.getCallSetupState().isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled()) {
|
||||
if (currentState.getCallSetupState(activePeer).isAcceptWithVideo() || currentState.getLocalDeviceState().getCameraState().isEnabled()) {
|
||||
webRtcInteractor.setDefaultAudioDevice(SignalAudioManager.AudioDevice.SPEAKER_PHONE, false);
|
||||
} else {
|
||||
webRtcInteractor.setDefaultAudioDevice(SignalAudioManager.AudioDevice.EARPIECE, false);
|
||||
@@ -95,9 +95,6 @@ public class CallSetupActionProcessorDelegate extends WebRtcActionProcessor {
|
||||
}
|
||||
|
||||
currentState = currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.enableVideoOnCreate(enable)
|
||||
.commit()
|
||||
.changeLocalDeviceState()
|
||||
.cameraState(camera.getCameraState())
|
||||
.build();
|
||||
|
||||
@@ -185,14 +185,14 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleSetRingGroup(@NonNull WebRtcServiceState currentState, boolean ringGroup) {
|
||||
Log.i(tag, "handleReceivedOpaqueMessage(): ring: " + ringGroup);
|
||||
Log.i(tag, "handleSetRingGroup(): ring: " + ringGroup);
|
||||
|
||||
if (currentState.getCallSetupState().shouldRingGroup() == ringGroup) {
|
||||
if (currentState.getCallSetupState(RemotePeer.GROUP_CALL_ID).shouldRingGroup() == ringGroup) {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
return currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||
.setRingGroup(ringGroup)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.signal.ringrtc.PeekInfo;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.ringrtc.Camera;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -114,7 +115,7 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
if (currentState.getCallSetupState().hasSentJoinedMessage()) {
|
||||
if (currentState.getCallSetupState(RemotePeer.GROUP_CALL_ID).hasSentJoinedMessage()) {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
@@ -128,7 +129,7 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
|
||||
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, WebRtcUtil.isCallFull(peekInfo));
|
||||
|
||||
return currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||
.sentJoinedMessage(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.signal.ringrtc.CallException;
|
||||
import org.signal.ringrtc.GroupCall;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.ringrtc.Camera;
|
||||
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.util.FeatureFlags;
|
||||
@@ -80,7 +81,7 @@ public class GroupJoiningActionProcessor extends GroupActionProcessor {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (FeatureFlags.groupCallRinging() && currentState.getCallSetupState().shouldRingGroup()) {
|
||||
if (FeatureFlags.groupCallRinging() && currentState.getCallSetupState(RemotePeer.GROUP_CALL_ID).shouldRingGroup()) {
|
||||
try {
|
||||
groupCall.ringAll();
|
||||
} catch (CallException e) {
|
||||
|
||||
@@ -62,6 +62,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
|
||||
.changeCallInfoState()
|
||||
.groupCall(groupCall)
|
||||
.groupCallState(WebRtcViewModel.GroupCallState.DISCONNECTED)
|
||||
.activePeer(new RemotePeer(currentState.getCallInfoState().getCallRecipient().getId(), RemotePeer.GROUP_CALL_ID))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
|
||||
|
||||
currentState.getVideoState().requireCamera().setEnabled(enable);
|
||||
return currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||
.enableVideoOnCreate(enable)
|
||||
.commit()
|
||||
.changeLocalDeviceState()
|
||||
|
||||
@@ -93,10 +93,10 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
Log.i(TAG, "handleAcceptCall(): call_id: " + activePeer.getCallId());
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).insertReceivedCall(activePeer.getId(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
DatabaseFactory.getSmsDatabase(context).insertReceivedCall(activePeer.getId(), currentState.getCallSetupState(activePeer).isRemoteVideoOffer());
|
||||
|
||||
currentState = currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(activePeer.getCallId())
|
||||
.acceptWithVideo(answerWithVideo)
|
||||
.build();
|
||||
|
||||
@@ -121,7 +121,7 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
try {
|
||||
webRtcInteractor.getCallManager().hangup();
|
||||
DatabaseFactory.getSmsDatabase(context).insertMissedCall(activePeer.getId(), System.currentTimeMillis(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
DatabaseFactory.getSmsDatabase(context).insertMissedCall(activePeer.getId(), System.currentTimeMillis(), currentState.getCallSetupState(activePeer).isRemoteVideoOffer());
|
||||
return terminate(currentState, activePeer);
|
||||
} catch (CallException e) {
|
||||
return callFailure(currentState, "hangup() failed: ", e);
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
Log.i(TAG, "handleGroupCallRingUpdate(): recipient: " + remotePeerGroup.getId() + " ring: " + ringId + " update: " + ringUpdate);
|
||||
|
||||
Recipient recipient = remotePeerGroup.getRecipient();
|
||||
boolean updateForCurrentRingId = ringId == currentState.getCallSetupState().getRingId();
|
||||
boolean updateForCurrentRingId = ringId == currentState.getCallSetupState(RemotePeer.GROUP_CALL_ID).getRingId();
|
||||
boolean isCurrentlyRinging = currentState.getCallInfoState().getGroupCallState().isRinging();
|
||||
|
||||
if (DatabaseFactory.getGroupCallRingDatabase(context).isCancelled(ringId)) {
|
||||
@@ -134,12 +134,13 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
webRtcInteractor.registerPowerButtonReceiver();
|
||||
|
||||
return currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||
.isRemoteVideoOffer(true)
|
||||
.ringId(ringId)
|
||||
.ringerRecipient(Recipient.externalPush(context, ACI.from(uuid), null, false))
|
||||
.commit()
|
||||
.changeCallInfoState()
|
||||
.activePeer(new RemotePeer(currentState.getCallInfoState().getCallRecipient().getId(), RemotePeer.GROUP_CALL_ID))
|
||||
.callRecipient(remotePeerGroup.getRecipient())
|
||||
.callState(WebRtcViewModel.State.CALL_INCOMING)
|
||||
.groupCallState(WebRtcViewModel.GroupCallState.RINGING)
|
||||
@@ -186,7 +187,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
.groupCall(groupCall)
|
||||
.groupCallState(WebRtcViewModel.GroupCallState.DISCONNECTED)
|
||||
.commit()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||
.isRemoteVideoOffer(false)
|
||||
.enableVideoOnCreate(answerWithVideo)
|
||||
.build();
|
||||
@@ -220,7 +221,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
protected @NonNull WebRtcServiceState handleDenyCall(@NonNull WebRtcServiceState currentState) {
|
||||
Recipient recipient = currentState.getCallInfoState().getCallRecipient();
|
||||
Optional<GroupId> groupId = recipient.getGroupId();
|
||||
long ringId = currentState.getCallSetupState().getRingId();
|
||||
long ringId = currentState.getCallSetupState(RemotePeer.GROUP_CALL_ID).getRingId();
|
||||
|
||||
DatabaseFactory.getGroupCallRingDatabase(context).insertOrUpdateGroupRing(ringId,
|
||||
System.currentTimeMillis(),
|
||||
@@ -242,7 +243,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
return WebRtcVideoUtil.deinitializeVideo(currentState)
|
||||
.builder()
|
||||
.actionProcessor(new IdleActionProcessor(webRtcInteractor))
|
||||
.terminate()
|
||||
.terminate(RemotePeer.GROUP_CALL_ID)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcData.CallMetadata;
|
||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcData.OfferMetadata;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.VideoState;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder;
|
||||
@@ -26,7 +25,6 @@ import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
||||
import org.webrtc.PeerConnection;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -57,28 +55,33 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleStartOutgoingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) {
|
||||
protected @NonNull WebRtcServiceState handleStartOutgoingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer, @NonNull OfferMessage.Type offerType) {
|
||||
Log.i(TAG, "handleStartOutgoingCall():");
|
||||
WebRtcServiceStateBuilder builder = currentState.builder();
|
||||
|
||||
remotePeer.dialing();
|
||||
|
||||
Log.i(TAG, "assign activePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode());
|
||||
Log.i(TAG, "assign activePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode() + " type: " + offerType);
|
||||
|
||||
boolean isVideoCall = offerType == OfferMessage.Type.VIDEO_CALL;
|
||||
|
||||
webRtcInteractor.setCallInProgressNotification(TYPE_OUTGOING_RINGING, remotePeer);
|
||||
webRtcInteractor.setDefaultAudioDevice(currentState.getCallSetupState().isEnableVideoOnCreate() ? SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
||||
: SignalAudioManager.AudioDevice.EARPIECE,
|
||||
webRtcInteractor.setDefaultAudioDevice(isVideoCall ? SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
||||
: SignalAudioManager.AudioDevice.EARPIECE,
|
||||
false);
|
||||
webRtcInteractor.updatePhoneState(WebRtcUtil.getInCallPhoneState(context));
|
||||
webRtcInteractor.initializeAudioForCall();
|
||||
webRtcInteractor.startOutgoingRinger();
|
||||
|
||||
RecipientUtil.setAndSendUniversalExpireTimerIfNecessary(context, Recipient.resolved(remotePeer.getId()), DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(remotePeer.getId()));
|
||||
DatabaseFactory.getSmsDatabase(context).insertOutgoingCall(remotePeer.getId(), currentState.getCallSetupState().isEnableVideoOnCreate());
|
||||
DatabaseFactory.getSmsDatabase(context).insertOutgoingCall(remotePeer.getId(), isVideoCall);
|
||||
|
||||
webRtcInteractor.retrieveTurnServers(remotePeer);
|
||||
|
||||
return builder.changeCallInfoState()
|
||||
return builder.changeCallSetupState(remotePeer.getCallId())
|
||||
.enableVideoOnCreate(isVideoCall)
|
||||
.commit()
|
||||
.changeCallInfoState()
|
||||
.activePeer(remotePeer)
|
||||
.callState(WebRtcViewModel.State.CALL_OUTGOING)
|
||||
.commit()
|
||||
@@ -105,7 +108,7 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
iceServers,
|
||||
isAlwaysTurn,
|
||||
NetworkUtil.getCallingBandwidthMode(context),
|
||||
currentState.getCallSetupState().isEnableVideoOnCreate());
|
||||
currentState.getCallSetupState(activePeer).isEnableVideoOnCreate());
|
||||
} catch (CallException e) {
|
||||
return callFailure(currentState, "Unable to proceed with call: ", e);
|
||||
}
|
||||
@@ -173,7 +176,7 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleRemoteVideoEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
|
||||
protected @NonNull WebRtcServiceState handleRemoteVideoEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
|
||||
return activeCallDelegate.handleRemoteVideoEnable(currentState, enable);
|
||||
}
|
||||
|
||||
@@ -203,7 +206,7 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
|
||||
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
|
||||
return activeCallDelegate.handleSetupFailure(currentState, callId);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,6 @@ public class PreJoinActionProcessor extends DeviceAwareActionProcessor {
|
||||
|
||||
currentState.getVideoState().getCamera().setEnabled(enable);
|
||||
return currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.enableVideoOnCreate(enable)
|
||||
.commit()
|
||||
.changeLocalDeviceState()
|
||||
.cameraState(currentState.getVideoState().getCamera().getCameraState())
|
||||
.build();
|
||||
|
||||
@@ -142,6 +142,9 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
}
|
||||
|
||||
private void process(@NonNull ProcessAction action) {
|
||||
Throwable t = new Throwable();
|
||||
String caller = t.getStackTrace().length > 1 ? t.getStackTrace()[1].getMethodName() : "unknown";
|
||||
|
||||
if (callManager == null) {
|
||||
Log.w(TAG, "Unable to process action, call manager is not initialized");
|
||||
return;
|
||||
@@ -157,7 +160,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
}
|
||||
}
|
||||
|
||||
Log.v(TAG, "Processing action, handler: " + serviceState.getActionProcessor().getTag());
|
||||
Log.v(TAG, "Processing action: " + caller + ", handler: " + serviceState.getActionProcessor().getTag());
|
||||
WebRtcServiceState previous = serviceState;
|
||||
serviceState = action.process(previous, previous.getActionProcessor());
|
||||
|
||||
@@ -395,7 +398,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
remotePeer.setCallId(callId);
|
||||
|
||||
if (isOutgoing) {
|
||||
return p.handleStartOutgoingCall(s, remotePeer);
|
||||
return p.handleStartOutgoingCall(s, remotePeer, WebRtcUtil.getOfferTypeFromCallMediaType(callMediaType));
|
||||
} else {
|
||||
return p.handleStartIncomingCall(s, remotePeer);
|
||||
}
|
||||
@@ -503,16 +506,15 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
@NonNull byte[] opaque,
|
||||
@NonNull CallManager.CallMediaType callMediaType)
|
||||
{
|
||||
Log.i(TAG, "onSendOffer: id: " + callId.format(remoteDevice) + " type: " + callMediaType.name());
|
||||
|
||||
if (!(remote instanceof RemotePeer)) {
|
||||
return;
|
||||
}
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
OfferMessage.Type offerType = WebRtcUtil.getOfferTypeFromCallMediaType(callMediaType);
|
||||
Log.i(TAG, "onSendOffer: id: " + remotePeer.getCallId().format(remoteDevice) + " type: " + callMediaType.name());
|
||||
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, callId, remoteDevice);
|
||||
OfferMessage.Type offerType = WebRtcUtil.getOfferTypeFromCallMediaType(callMediaType);
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, remoteDevice);
|
||||
WebRtcData.OfferMetadata offerMetadata = new WebRtcData.OfferMetadata(opaque, null, offerType);
|
||||
|
||||
process((s, p) -> p.handleSendOffer(s, callMetadata, offerMetadata, broadcast));
|
||||
@@ -525,14 +527,15 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
@NonNull Boolean broadcast,
|
||||
@NonNull byte[] opaque)
|
||||
{
|
||||
Log.i(TAG, "onSendAnswer: id: " + callId.format(remoteDevice));
|
||||
|
||||
if (!(remote instanceof RemotePeer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, callId, remoteDevice);
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
|
||||
Log.i(TAG, "onSendAnswer: id: " + remotePeer.getCallId().format(remoteDevice));
|
||||
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, remoteDevice);
|
||||
WebRtcData.AnswerMetadata answerMetadata = new WebRtcData.AnswerMetadata(opaque, null);
|
||||
|
||||
process((s, p) -> p.handleSendAnswer(s, callMetadata, answerMetadata, broadcast));
|
||||
@@ -545,28 +548,30 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
@NonNull Boolean broadcast,
|
||||
@NonNull List<byte[]> iceCandidates)
|
||||
{
|
||||
Log.i(TAG, "onSendIceCandidates: id: " + callId.format(remoteDevice));
|
||||
|
||||
if (!(remote instanceof RemotePeer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, callId, remoteDevice);
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
|
||||
Log.i(TAG, "onSendIceCandidates: id: " + remotePeer.getCallId().format(remoteDevice));
|
||||
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, remoteDevice);
|
||||
|
||||
process((s, p) -> p.handleSendIceCandidates(s, callMetadata, broadcast, iceCandidates));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendHangup(@NonNull CallId callId, @Nullable Remote remote, @NonNull Integer remoteDevice, @NonNull Boolean broadcast, @NonNull CallManager.HangupType hangupType, @NonNull Integer deviceId, @NonNull Boolean useLegacyHangupMessage) {
|
||||
Log.i(TAG, "onSendHangup: id: " + callId.format(remoteDevice) + " type: " + hangupType.name() + " isLegacy: " + useLegacyHangupMessage);
|
||||
|
||||
if (!(remote instanceof RemotePeer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, callId, remoteDevice);
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
|
||||
Log.i(TAG, "onSendHangup: id: " + remotePeer.getCallId().format(remoteDevice) + " type: " + hangupType.name() + " isLegacy: " + useLegacyHangupMessage);
|
||||
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, remoteDevice);
|
||||
WebRtcData.HangupMetadata hangupMetadata = new WebRtcData.HangupMetadata(WebRtcUtil.getHangupTypeFromCallHangupType(hangupType), useLegacyHangupMessage, deviceId);
|
||||
|
||||
process((s, p) -> p.handleSendHangup(s, callMetadata, hangupMetadata, broadcast));
|
||||
@@ -574,14 +579,15 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
|
||||
@Override
|
||||
public void onSendBusy(@NonNull CallId callId, @Nullable Remote remote, @NonNull Integer remoteDevice, @NonNull Boolean broadcast) {
|
||||
Log.i(TAG, "onSendBusy: id: " + callId.format(remoteDevice));
|
||||
|
||||
if (!(remote instanceof RemotePeer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, callId, remoteDevice);
|
||||
RemotePeer remotePeer = (RemotePeer) remote;
|
||||
|
||||
Log.i(TAG, "onSendBusy: id: " + remotePeer.getCallId().format(remoteDevice));
|
||||
|
||||
WebRtcData.CallMetadata callMetadata = new WebRtcData.CallMetadata(remotePeer, remoteDevice);
|
||||
|
||||
process((s, p) -> p.handleSendBusy(s, callMetadata, broadcast));
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public abstract class WebRtcActionProcessor {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
protected @NonNull WebRtcServiceState handleStartOutgoingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) {
|
||||
protected @NonNull WebRtcServiceState handleStartOutgoingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer, @NonNull OfferMessage.Type offerType) {
|
||||
Log.i(tag, "handleStartOutgoingCall not processed");
|
||||
return currentState;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public abstract class WebRtcActionProcessor {
|
||||
@NonNull OfferMetadata offerMetadata,
|
||||
@NonNull ReceivedOfferMetadata receivedOfferMetadata)
|
||||
{
|
||||
Log.i(tag, "handleReceivedOffer(): id: " + callMetadata.getCallId().format(callMetadata.getRemoteDevice()));
|
||||
Log.i(tag, "handleReceivedOffer(): id: " + callMetadata.getCallId().format(callMetadata.getRemoteDevice()) + " offer_type:" + offerMetadata.getOfferType());
|
||||
|
||||
if (TelephonyUtil.isAnyPstnLineBusy(context)) {
|
||||
Log.i(tag, "PSTN line is busy.");
|
||||
@@ -191,7 +191,7 @@ public abstract class WebRtcActionProcessor {
|
||||
callMetadata.getRemotePeer().setCallStartTimestamp(receivedOfferMetadata.getServerReceivedTimestamp());
|
||||
|
||||
currentState = currentState.builder()
|
||||
.changeCallSetupState()
|
||||
.changeCallSetupState(callMetadata.getCallId())
|
||||
.isRemoteVideoOffer(offerMetadata.getOfferType() == OfferMessage.Type.VIDEO_CALL)
|
||||
.commit()
|
||||
.changeCallInfoState()
|
||||
@@ -228,7 +228,7 @@ public abstract class WebRtcActionProcessor {
|
||||
{
|
||||
Log.i(tag, "handleReceivedOfferExpired(): call_id: " + remotePeer.getCallId());
|
||||
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer());
|
||||
webRtcInteractor.insertMissedCall(remotePeer, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState(remotePeer).isRemoteVideoOffer());
|
||||
|
||||
return terminate(currentState, remotePeer);
|
||||
}
|
||||
@@ -597,7 +597,7 @@ public abstract class WebRtcActionProcessor {
|
||||
.changeLocalDeviceState()
|
||||
.commit()
|
||||
.actionProcessor(currentState.getCallInfoState().getCallState() == WebRtcViewModel.State.CALL_DISCONNECTED ? new DisconnectingCallActionProcessor(webRtcInteractor) : new IdleActionProcessor(webRtcInteractor))
|
||||
.terminate()
|
||||
.terminate(remotePeer.getCallId())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,10 @@ public class WebRtcData {
|
||||
*/
|
||||
public static class CallMetadata {
|
||||
private final @NonNull RemotePeer remotePeer;
|
||||
private final @NonNull CallId callId;
|
||||
private final int remoteDevice;
|
||||
|
||||
public CallMetadata(@NonNull RemotePeer remotePeer, @NonNull CallId callId, int remoteDevice) {
|
||||
public CallMetadata(@NonNull RemotePeer remotePeer, int remoteDevice) {
|
||||
this.remotePeer = remotePeer;
|
||||
this.callId = callId;
|
||||
this.remoteDevice = remoteDevice;
|
||||
}
|
||||
|
||||
@@ -35,7 +33,7 @@ public class WebRtcData {
|
||||
}
|
||||
|
||||
@NonNull CallId getCallId() {
|
||||
return callId;
|
||||
return remotePeer.getCallId();
|
||||
}
|
||||
|
||||
int getRemoteDevice() {
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class WebRtcUtil {
|
||||
return offerType == OfferMessage.Type.VIDEO_CALL ? CallManager.CallMediaType.VIDEO_CALL : CallManager.CallMediaType.AUDIO_CALL;
|
||||
}
|
||||
|
||||
public static @NonNull OfferMessage.Type getOfferTypeFromCallMediaType(@NonNull CallManager.CallMediaType callMediaType) {
|
||||
public static @NonNull OfferMessage.Type getOfferTypeFromCallMediaType(@Nullable CallManager.CallMediaType callMediaType) {
|
||||
return callMediaType == CallManager.CallMediaType.VIDEO_CALL ? OfferMessage.Type.VIDEO_CALL : OfferMessage.Type.AUDIO_CALL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
package org.thoughtcrime.securesms.service.webrtc.state;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.ringrtc.CallId;
|
||||
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcActionProcessor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represent the entire state of the call system.
|
||||
*/
|
||||
public final class WebRtcServiceState {
|
||||
|
||||
WebRtcActionProcessor actionProcessor;
|
||||
CallSetupState callSetupState;
|
||||
CallInfoState callInfoState;
|
||||
LocalDeviceState localDeviceState;
|
||||
VideoState videoState;
|
||||
WebRtcActionProcessor actionProcessor;
|
||||
Map<CallId, CallSetupState> callSetupStates;
|
||||
CallInfoState callInfoState;
|
||||
LocalDeviceState localDeviceState;
|
||||
VideoState videoState;
|
||||
|
||||
public WebRtcServiceState(@NonNull WebRtcActionProcessor actionProcessor) {
|
||||
this.actionProcessor = actionProcessor;
|
||||
this.callSetupState = new CallSetupState();
|
||||
this.callSetupStates = new HashMap<>();
|
||||
this.callInfoState = new CallInfoState();
|
||||
this.localDeviceState = new LocalDeviceState();
|
||||
this.videoState = new VideoState();
|
||||
@@ -25,18 +31,36 @@ public final class WebRtcServiceState {
|
||||
|
||||
public WebRtcServiceState(@NonNull WebRtcServiceState toCopy) {
|
||||
this.actionProcessor = toCopy.actionProcessor;
|
||||
this.callSetupState = toCopy.callSetupState.duplicate();
|
||||
this.callInfoState = new CallInfoState(toCopy.callInfoState);
|
||||
this.localDeviceState = toCopy.localDeviceState.duplicate();
|
||||
this.videoState = new VideoState(toCopy.videoState);
|
||||
this.callSetupStates = new HashMap<>();
|
||||
|
||||
for (Map.Entry<CallId, CallSetupState> entry : toCopy.callSetupStates.entrySet()) {
|
||||
this.callSetupStates.put(entry.getKey(), entry.getValue().duplicate());
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull WebRtcActionProcessor getActionProcessor() {
|
||||
return actionProcessor;
|
||||
}
|
||||
|
||||
public @NonNull CallSetupState getCallSetupState() {
|
||||
return callSetupState;
|
||||
|
||||
public @NonNull CallSetupState getCallSetupState(@NonNull RemotePeer remotePeer) {
|
||||
return getCallSetupState(remotePeer.getCallId());
|
||||
}
|
||||
|
||||
public @NonNull CallSetupState getCallSetupState(@Nullable CallId callId) {
|
||||
if (callId == null) {
|
||||
return new CallSetupState();
|
||||
}
|
||||
|
||||
if (!callSetupStates.containsKey(callId)) {
|
||||
callSetupStates.put(callId, new CallSetupState());
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
return callSetupStates.get(callId);
|
||||
}
|
||||
|
||||
public @NonNull CallInfoState getCallInfoState() {
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.OptionalLong;
|
||||
|
||||
import org.signal.ringrtc.CallId;
|
||||
import org.signal.ringrtc.GroupCall;
|
||||
import org.thoughtcrime.securesms.components.sensors.Orientation;
|
||||
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
|
||||
@@ -43,8 +44,8 @@ public class WebRtcServiceStateBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull CallSetupStateBuilder changeCallSetupState() {
|
||||
return new CallSetupStateBuilder();
|
||||
public @NonNull CallSetupStateBuilder changeCallSetupState(@NonNull CallId callId) {
|
||||
return new CallSetupStateBuilder(callId);
|
||||
}
|
||||
|
||||
public @NonNull CallInfoStateBuilder changeCallInfoState() {
|
||||
@@ -59,8 +60,7 @@ public class WebRtcServiceStateBuilder {
|
||||
return new VideoStateBuilder();
|
||||
}
|
||||
|
||||
public @NonNull WebRtcServiceStateBuilder terminate() {
|
||||
toBuild.callSetupState = new CallSetupState();
|
||||
public @NonNull WebRtcServiceStateBuilder terminate(@NonNull CallId callId) {
|
||||
toBuild.localDeviceState = new LocalDeviceState();
|
||||
toBuild.videoState = new VideoState();
|
||||
|
||||
@@ -68,6 +68,8 @@ public class WebRtcServiceStateBuilder {
|
||||
newCallInfoState.peerMap.putAll(toBuild.callInfoState.peerMap);
|
||||
toBuild.callInfoState = newCallInfoState;
|
||||
|
||||
toBuild.callSetupStates.remove(callId);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -126,13 +128,15 @@ public class WebRtcServiceStateBuilder {
|
||||
|
||||
public class CallSetupStateBuilder {
|
||||
private CallSetupState toBuild;
|
||||
private CallId callId;
|
||||
|
||||
public CallSetupStateBuilder() {
|
||||
toBuild = WebRtcServiceStateBuilder.this.toBuild.callSetupState.duplicate();
|
||||
public CallSetupStateBuilder(@NonNull CallId callId) {
|
||||
this.toBuild = WebRtcServiceStateBuilder.this.toBuild.getCallSetupState(callId).duplicate();
|
||||
this.callId = callId;
|
||||
}
|
||||
|
||||
public @NonNull WebRtcServiceStateBuilder commit() {
|
||||
WebRtcServiceStateBuilder.this.toBuild.callSetupState = toBuild;
|
||||
WebRtcServiceStateBuilder.this.toBuild.callSetupStates.put(callId, toBuild);
|
||||
return WebRtcServiceStateBuilder.this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user