Ensure serial handling of calling events and improve busy UX.
parent
7b24e66ed3
commit
ed9acd25f9
|
@ -64,7 +64,6 @@ public class WebRtcCallActivity extends AppCompatActivity implements SafetyNumbe
|
||||||
private static final String TAG = WebRtcCallActivity.class.getSimpleName();
|
private static final String TAG = WebRtcCallActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final int STANDARD_DELAY_FINISH = 1000;
|
private static final int STANDARD_DELAY_FINISH = 1000;
|
||||||
public static final int BUSY_SIGNAL_DELAY_FINISH = 5500;
|
|
||||||
|
|
||||||
public static final String ANSWER_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".ANSWER_ACTION";
|
public static final String ANSWER_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".ANSWER_ACTION";
|
||||||
public static final String DENY_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".DENY_ACTION";
|
public static final String DENY_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".DENY_ACTION";
|
||||||
|
@ -408,8 +407,7 @@ public class WebRtcCallActivity extends AppCompatActivity implements SafetyNumbe
|
||||||
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
|
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
|
||||||
callScreen.setRecipient(event.getRecipient());
|
callScreen.setRecipient(event.getRecipient());
|
||||||
callScreen.setStatus(getString(R.string.RedPhone_busy));
|
callScreen.setStatus(getString(R.string.RedPhone_busy));
|
||||||
|
delayedFinish(WebRtcCallService.BUSY_TONE_LENGTH);
|
||||||
delayedFinish(BUSY_SIGNAL_DELAY_FINISH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCallConnected(@NonNull WebRtcViewModel event) {
|
private void handleCallConnected(@NonNull WebRtcViewModel event) {
|
||||||
|
|
|
@ -10,10 +10,10 @@ public enum CallState {
|
||||||
/** Idle, setting up objects */
|
/** Idle, setting up objects */
|
||||||
IDLE,
|
IDLE,
|
||||||
|
|
||||||
/** Dialing. Outgoing call is signaling the remote peer */
|
/** Dialing. Outgoing call is signaling the remote peer */
|
||||||
DIALING,
|
DIALING,
|
||||||
|
|
||||||
/** Answering. Incoming call is responding to remote peer */
|
/** Answering. Incoming call is responding to remote peer */
|
||||||
ANSWERING,
|
ANSWERING,
|
||||||
|
|
||||||
/** Remote ringing. Outgoing call, ICE negotiation is complete */
|
/** Remote ringing. Outgoing call, ICE negotiation is complete */
|
||||||
|
@ -25,10 +25,9 @@ public enum CallState {
|
||||||
/** Connected. Incoming/Outgoing call, the call is connected */
|
/** Connected. Incoming/Outgoing call, the call is connected */
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
|
|
||||||
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
||||||
TERMINATED,
|
TERMINATED,
|
||||||
|
|
||||||
/** Busy. Outgoing call received a busy notification */
|
/** Busy. Outgoing call received a busy notification */
|
||||||
RECEIVED_BUSY;
|
RECEIVED_BUSY;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ public final class RemotePeer implements Remote, Parcelable
|
||||||
return callId;
|
return callId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCallId(@NonNull CallId callId) {
|
||||||
|
this.callId = callId;
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull CallState getState() {
|
public @NonNull CallState getState() {
|
||||||
return callState;
|
return callState;
|
||||||
}
|
}
|
||||||
|
@ -73,21 +77,19 @@ public final class RemotePeer implements Remote, Parcelable
|
||||||
return remotePeer != null && this.callId.equals(remotePeer.callId);
|
return remotePeer != null && this.callId.equals(remotePeer.callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dialing(@NonNull CallId callId) {
|
public void dialing() {
|
||||||
if (callState != CallState.IDLE) {
|
if (callState != CallState.IDLE) {
|
||||||
throw new IllegalStateException("Cannot transition to DIALING from state: " + callState);
|
throw new IllegalStateException("Cannot transition to DIALING from state: " + callState);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callId = callId;
|
|
||||||
this.callState = CallState.DIALING;
|
this.callState = CallState.DIALING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void answering(@NonNull CallId callId) {
|
public void answering() {
|
||||||
if (callState != CallState.IDLE) {
|
if (callState != CallState.IDLE) {
|
||||||
throw new IllegalStateException("Cannot transition to ANSWERING from state: " + callState);
|
throw new IllegalStateException("Cannot transition to ANSWERING from state: " + callState);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callId = callId;
|
|
||||||
this.callState = CallState.ANSWERING;
|
this.callState = CallState.ANSWERING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +101,6 @@ public final class RemotePeer implements Remote, Parcelable
|
||||||
this.callState = CallState.REMOTE_RINGING;
|
this.callState = CallState.REMOTE_RINGING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receivedBusy() {
|
|
||||||
if (callState != CallState.DIALING) {
|
|
||||||
Log.w(TAG, "RECEIVED_BUSY from unexpected state: " + callState);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.callState = CallState.RECEIVED_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void localRinging() {
|
public void localRinging() {
|
||||||
if (callState != CallState.ANSWERING) {
|
if (callState != CallState.ANSWERING) {
|
||||||
throw new IllegalStateException("Cannot transition to LOCAL_RINGING from state: " + callState);
|
throw new IllegalStateException("Cannot transition to LOCAL_RINGING from state: " + callState);
|
||||||
|
@ -123,6 +117,14 @@ public final class RemotePeer implements Remote, Parcelable
|
||||||
this.callState = CallState.CONNECTED;
|
this.callState = CallState.CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void receivedBusy() {
|
||||||
|
if (callState != CallState.DIALING) {
|
||||||
|
Log.w(TAG, "RECEIVED_BUSY from unexpected state: " + callState);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.callState = CallState.RECEIVED_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import android.os.IBinder;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.telephony.PhoneStateListener;
|
import android.telephony.PhoneStateListener;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
@ -47,6 +48,7 @@ import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
|
||||||
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
||||||
import org.thoughtcrime.securesms.webrtc.IncomingPstnCallReceiver;
|
import org.thoughtcrime.securesms.webrtc.IncomingPstnCallReceiver;
|
||||||
import org.thoughtcrime.securesms.webrtc.UncaughtExceptionHandlerManager;
|
import org.thoughtcrime.securesms.webrtc.UncaughtExceptionHandlerManager;
|
||||||
|
@ -68,7 +70,6 @@ import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -102,6 +103,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
public static final String EXTRA_SPEAKER = "audio_speaker";
|
public static final String EXTRA_SPEAKER = "audio_speaker";
|
||||||
public static final String EXTRA_BLUETOOTH = "audio_bluetooth";
|
public static final String EXTRA_BLUETOOTH = "audio_bluetooth";
|
||||||
public static final String EXTRA_REMOTE_PEER = "remote_peer";
|
public static final String EXTRA_REMOTE_PEER = "remote_peer";
|
||||||
|
public static final String EXTRA_REMOTE_PEER_KEY = "remote_peer_key";
|
||||||
public static final String EXTRA_REMOTE_DEVICE = "remote_device";
|
public static final String EXTRA_REMOTE_DEVICE = "remote_device";
|
||||||
public static final String EXTRA_OFFER_OPAQUE = "offer_opaque";
|
public static final String EXTRA_OFFER_OPAQUE = "offer_opaque";
|
||||||
public static final String EXTRA_OFFER_SDP = "offer_sdp";
|
public static final String EXTRA_OFFER_SDP = "offer_sdp";
|
||||||
|
@ -161,6 +163,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
public static final String ACTION_ENDED_RX_OFFER_WHILE_ACTIVE = "ENDED_RX_OFFER_WHILE_ACTIVE";
|
public static final String ACTION_ENDED_RX_OFFER_WHILE_ACTIVE = "ENDED_RX_OFFER_WHILE_ACTIVE";
|
||||||
public static final String ACTION_CALL_CONCLUDED = "CALL_CONCLUDED";
|
public static final String ACTION_CALL_CONCLUDED = "CALL_CONCLUDED";
|
||||||
|
|
||||||
|
public static final int BUSY_TONE_LENGTH = 2000;
|
||||||
|
|
||||||
private CameraState localCameraState = CameraState.UNKNOWN;
|
private CameraState localCameraState = CameraState.UNKNOWN;
|
||||||
private boolean microphoneEnabled = true;
|
private boolean microphoneEnabled = true;
|
||||||
private boolean remoteVideoEnabled = false;
|
private boolean remoteVideoEnabled = false;
|
||||||
|
@ -181,12 +185,14 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
private IncomingPstnCallReceiver callReceiver;
|
private IncomingPstnCallReceiver callReceiver;
|
||||||
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
||||||
|
|
||||||
@Nullable private CallManager callManager;
|
@Nullable private CallManager callManager;
|
||||||
@Nullable private RemotePeer activePeer;
|
@Nullable private RemotePeer activePeer;
|
||||||
@Nullable private TextureViewRenderer localRenderer;
|
@Nullable private RemotePeer busyPeer;
|
||||||
@Nullable private TextureViewRenderer remoteRenderer;
|
@Nullable private SparseArray<RemotePeer> peerMap;
|
||||||
@Nullable private EglBase eglBase;
|
@Nullable private TextureViewRenderer localRenderer;
|
||||||
@Nullable private Camera camera;
|
@Nullable private TextureViewRenderer remoteRenderer;
|
||||||
|
@Nullable private EglBase eglBase;
|
||||||
|
@Nullable private Camera camera;
|
||||||
|
|
||||||
private final ExecutorService serviceExecutor = Executors.newSingleThreadExecutor();
|
private final ExecutorService serviceExecutor = Executors.newSingleThreadExecutor();
|
||||||
private final ExecutorService networkExecutor = Executors.newSingleThreadExecutor();
|
private final ExecutorService networkExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
@ -257,7 +263,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
else if (intent.getAction().equals(ACTION_ENDED_RX_OFFER_EXPIRED)) handleEndedReceivedOfferExpired(intent);
|
else if (intent.getAction().equals(ACTION_ENDED_RX_OFFER_EXPIRED)) handleEndedReceivedOfferExpired(intent);
|
||||||
else if (intent.getAction().equals(ACTION_ENDED_RX_OFFER_WHILE_ACTIVE)) handleEndedReceivedOfferWhileActive(intent);
|
else if (intent.getAction().equals(ACTION_ENDED_RX_OFFER_WHILE_ACTIVE)) handleEndedReceivedOfferWhileActive(intent);
|
||||||
else if (intent.getAction().equals(ACTION_CALL_CONCLUDED)) handleCallConcluded(intent);
|
else if (intent.getAction().equals(ACTION_CALL_CONCLUDED)) handleCallConcluded(intent);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
|
@ -322,15 +327,13 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initializers
|
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
this.messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
this.messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||||
this.accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
this.accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
this.lockManager = new LockManager(this);
|
this.lockManager = new LockManager(this);
|
||||||
this.audioManager = new SignalAudioManager(this);
|
this.audioManager = new SignalAudioManager(this);
|
||||||
this.bluetoothStateManager = new BluetoothStateManager(this, this);
|
this.bluetoothStateManager = new BluetoothStateManager(this, this);
|
||||||
|
this.peerMap = new SparseArray<>();
|
||||||
|
|
||||||
this.messageSender.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
this.messageSender.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
||||||
this.accountManager.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
this.accountManager.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
||||||
|
@ -340,7 +343,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
} catch (CallException e) {
|
} catch (CallException e) {
|
||||||
callFailure("Unable to create Call Manager: ", e);
|
callFailure("Unable to create Call Manager: ", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerIncomingPstnCallReceiver() {
|
private void registerIncomingPstnCallReceiver() {
|
||||||
|
@ -383,8 +385,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handlers
|
|
||||||
|
|
||||||
private void handleReceivedOffer(Intent intent) {
|
private void handleReceivedOffer(Intent intent) {
|
||||||
CallId callId = getCallId(intent);
|
CallId callId = getCallId(intent);
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeer(intent);
|
||||||
|
@ -399,7 +399,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
Log.i(TAG, "handleReceivedOffer(): id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleReceivedOffer(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
if (TelephonyUtil.isAnyPstnLineBusy(this)) {
|
if (TelephonyUtil.isAnyPstnLineBusy(this)) {
|
||||||
Log.i(TAG, "handleReceivedOffer(): PSTN line is busy.");
|
Log.i(TAG, "PSTN line is busy.");
|
||||||
intent.putExtra(EXTRA_BROADCAST, true);
|
intent.putExtra(EXTRA_BROADCAST, true);
|
||||||
handleSendBusy(intent);
|
handleSendBusy(intent);
|
||||||
insertMissedCall(remotePeer, true);
|
insertMissedCall(remotePeer, true);
|
||||||
|
@ -407,7 +407,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remotePeer.getRecipient() == null || !RecipientUtil.isCallRequestAccepted(getApplicationContext(), remotePeer.getRecipient())) {
|
if (remotePeer.getRecipient() == null || !RecipientUtil.isCallRequestAccepted(getApplicationContext(), remotePeer.getRecipient())) {
|
||||||
Log.i(TAG, "handleReceivedOffer(): Caller is untrusted.");
|
Log.w(TAG, "Caller is untrusted.");
|
||||||
intent.putExtra(EXTRA_BROADCAST, true);
|
intent.putExtra(EXTRA_BROADCAST, true);
|
||||||
intent.putExtra(EXTRA_HANGUP_TYPE, HangupMessage.Type.NEED_PERMISSION.getCode());
|
intent.putExtra(EXTRA_HANGUP_TYPE, HangupMessage.Type.NEED_PERMISSION.getCode());
|
||||||
handleSendHangup(intent);
|
handleSendHangup(intent);
|
||||||
|
@ -415,12 +415,15 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerMap.append(remotePeer.hashCode(), remotePeer);
|
||||||
|
Log.i(TAG, "add remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode());
|
||||||
|
|
||||||
isRemoteVideoOffer = offerType == OfferMessage.Type.VIDEO_CALL;
|
isRemoteVideoOffer = offerType == OfferMessage.Type.VIDEO_CALL;
|
||||||
|
|
||||||
CallManager.CallMediaType callType = getCallMediaTypeFromOfferType(offerType);
|
CallManager.CallMediaType callType = getCallMediaTypeFromOfferType(offerType);
|
||||||
|
|
||||||
long messageAgeSec = Math.max(serverDeliveredTimestamp - serverReceivedTimestamp, 0) / 1000;
|
long messageAgeSec = Math.max(serverDeliveredTimestamp - serverReceivedTimestamp, 0) / 1000;
|
||||||
Log.i(TAG, "handleReceivedOffer(): messageAgeSec: " + messageAgeSec + ", serverReceivedTimestamp: " + serverReceivedTimestamp + ", serverDeliveredTimestamp: " + serverDeliveredTimestamp);
|
Log.i(TAG, "messageAgeSec: " + messageAgeSec + ", serverReceivedTimestamp: " + serverReceivedTimestamp + ", serverDeliveredTimestamp: " + serverDeliveredTimestamp);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
callManager.receivedOffer(callId, remotePeer, remoteDevice, opaque, sdp, messageAgeSec, callType, 1, isMultiRing, true);
|
callManager.receivedOffer(callId, remotePeer, remoteDevice, opaque, sdp, messageAgeSec, callType, 1, isMultiRing, true);
|
||||||
|
@ -430,15 +433,19 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleOutgoingCall(Intent intent) {
|
private void handleOutgoingCall(Intent intent) {
|
||||||
|
Log.i(TAG, "handleOutgoingCall():");
|
||||||
|
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeer(intent);
|
||||||
|
|
||||||
if (remotePeer.getState() != CallState.IDLE) {
|
if (remotePeer.getState() != CallState.IDLE) {
|
||||||
throw new IllegalStateException("Dialing from non-idle?");
|
throw new IllegalStateException("Dialing from non-idle?");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "handleOutgoingCall():");
|
|
||||||
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
|
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
|
||||||
|
|
||||||
|
peerMap.append(remotePeer.hashCode(), remotePeer);
|
||||||
|
Log.i(TAG, "add remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode());
|
||||||
|
|
||||||
initializeVideo();
|
initializeVideo();
|
||||||
|
|
||||||
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
||||||
|
@ -480,6 +487,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
try {
|
try {
|
||||||
callManager.hangup();
|
callManager.hangup();
|
||||||
DatabaseFactory.getSmsDatabase(this).insertMissedCall(activePeer.getId());
|
DatabaseFactory.getSmsDatabase(this).insertMissedCall(activePeer.getId());
|
||||||
|
terminate(activePeer);
|
||||||
} catch (CallException e) {
|
} catch (CallException e) {
|
||||||
callFailure("hangup() failed: ", e);
|
callFailure("hangup() failed: ", e);
|
||||||
}
|
}
|
||||||
|
@ -591,7 +599,19 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStartOutgoingCall(Intent intent) {
|
private void handleStartOutgoingCall(Intent intent) {
|
||||||
Log.i(TAG, "handleStartOutgoingCall(): callId: " + activePeer.getCallId());
|
Log.i(TAG, "handleStartOutgoingCall():");
|
||||||
|
|
||||||
|
if (activePeer != null) {
|
||||||
|
throw new IllegalStateException("handleStartOutgoingCall(): activePeer already set");
|
||||||
|
}
|
||||||
|
|
||||||
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
activePeer = remotePeer;
|
||||||
|
activePeer.dialing();
|
||||||
|
Log.i(TAG, "assign activePeer callId: " + activePeer.getCallId() + " key: " + activePeer.hashCode());
|
||||||
|
|
||||||
|
AudioManager androidAudioManager = ServiceUtil.getAudioManager(this);
|
||||||
|
androidAudioManager.setSpeakerphoneOn(false);
|
||||||
|
|
||||||
sendMessage(WebRtcViewModel.State.CALL_OUTGOING, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_OUTGOING, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
lockManager.updatePhoneState(getInCallPhoneState());
|
lockManager.updatePhoneState(getInCallPhoneState());
|
||||||
|
@ -609,9 +629,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
|
|
||||||
boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this);
|
boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this);
|
||||||
|
|
||||||
LinkedList<Integer> deviceList = new LinkedList<Integer>();
|
|
||||||
deviceList.add(SignalServiceAddress.DEFAULT_DEVICE_ID);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
callManager.proceed(activePeer.getCallId(),
|
callManager.proceed(activePeer.getCallId(),
|
||||||
WebRtcCallService.this,
|
WebRtcCallService.this,
|
||||||
|
@ -635,11 +652,19 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStartIncomingCall(Intent intent) {
|
private void handleStartIncomingCall(Intent intent) {
|
||||||
if (activePeer.getState() != CallState.ANSWERING) {
|
Log.i(TAG, "handleStartIncomingCall():");
|
||||||
throw new IllegalStateException("StartIncoming while non-ANSWERING");
|
|
||||||
|
if (activePeer != null) {
|
||||||
|
throw new IllegalStateException("handleStartIncomingCall(): activePeer already set");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "handleStartIncomingCall(): callId: " + activePeer.getCallId());
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
activePeer = remotePeer;
|
||||||
|
activePeer.answering();
|
||||||
|
Log.i(TAG, "assign activePeer callId: " + activePeer.getCallId() + " key: " + activePeer.hashCode());
|
||||||
|
|
||||||
|
AudioManager androidAudioManager = ServiceUtil.getAudioManager(this);
|
||||||
|
androidAudioManager.setSpeakerphoneOn(false);
|
||||||
|
|
||||||
initializeVideo();
|
initializeVideo();
|
||||||
|
|
||||||
|
@ -648,12 +673,9 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
retrieveTurnServers().addListener(new SuccessOnlyListener<List<PeerConnection.IceServer>>(this.activePeer.getState(), this.activePeer.getCallId()) {
|
retrieveTurnServers().addListener(new SuccessOnlyListener<List<PeerConnection.IceServer>>(this.activePeer.getState(), this.activePeer.getCallId()) {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccessContinue(List<PeerConnection.IceServer> iceServers) {
|
public void onSuccessContinue(List<PeerConnection.IceServer> iceServers) {
|
||||||
|
|
||||||
boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this);
|
boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this);
|
||||||
boolean hideIp = !activePeer.getRecipient().isSystemContact() || isAlwaysTurn;
|
boolean hideIp = !activePeer.getRecipient().isSystemContact() || isAlwaysTurn;
|
||||||
|
|
||||||
LinkedList<Integer> deviceList = new LinkedList<>();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
callManager.proceed(activePeer.getCallId(),
|
callManager.proceed(activePeer.getCallId(),
|
||||||
WebRtcCallService.this,
|
WebRtcCallService.this,
|
||||||
|
@ -677,7 +699,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAcceptCall(Intent intent) {
|
private void handleAcceptCall(Intent intent) {
|
||||||
|
|
||||||
if (activePeer != null && activePeer.getState() != CallState.LOCAL_RINGING) {
|
if (activePeer != null && activePeer.getState() != CallState.LOCAL_RINGING) {
|
||||||
Log.w(TAG, "handleAcceptCall(): Ignoring for inactive call.");
|
Log.w(TAG, "handleAcceptCall(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
|
@ -705,7 +726,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
String sdp = intent.getStringExtra(EXTRA_OFFER_SDP);
|
String sdp = intent.getStringExtra(EXTRA_OFFER_SDP);
|
||||||
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
||||||
|
|
||||||
Log.i(TAG, "handleSendOffer: id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleSendOffer(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
OfferMessage offerMessage = new OfferMessage(callId.longValue(), sdp, offerType, opaque);
|
OfferMessage offerMessage = new OfferMessage(callId.longValue(), sdp, offerType, opaque);
|
||||||
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
||||||
|
@ -722,7 +743,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
byte[] opaque = intent.getByteArrayExtra(EXTRA_ANSWER_OPAQUE);
|
byte[] opaque = intent.getByteArrayExtra(EXTRA_ANSWER_OPAQUE);
|
||||||
String sdp = intent.getStringExtra(EXTRA_ANSWER_SDP);
|
String sdp = intent.getStringExtra(EXTRA_ANSWER_SDP);
|
||||||
|
|
||||||
Log.i(TAG, "handleSendAnswer: id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleSendAnswer(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
AnswerMessage answerMessage = new AnswerMessage(callId.longValue(), sdp, opaque);
|
AnswerMessage answerMessage = new AnswerMessage(callId.longValue(), sdp, opaque);
|
||||||
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
||||||
|
@ -738,7 +759,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
boolean broadcast = intent.getBooleanExtra(EXTRA_BROADCAST, false);
|
boolean broadcast = intent.getBooleanExtra(EXTRA_BROADCAST, false);
|
||||||
ArrayList<IceCandidateParcel> iceCandidates = intent.getParcelableArrayListExtra(EXTRA_ICE_CANDIDATES);
|
ArrayList<IceCandidateParcel> iceCandidates = intent.getParcelableArrayListExtra(EXTRA_ICE_CANDIDATES);
|
||||||
|
|
||||||
Log.i(TAG, "handleSendIceCandidates: id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleSendIceCandidates(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
LinkedList<IceUpdateMessage> iceUpdateMessages = new LinkedList();
|
LinkedList<IceUpdateMessage> iceUpdateMessages = new LinkedList();
|
||||||
for (IceCandidateParcel parcel : iceCandidates) {
|
for (IceCandidateParcel parcel : iceCandidates) {
|
||||||
|
@ -760,7 +781,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
boolean isLegacy = intent.getBooleanExtra(EXTRA_HANGUP_IS_LEGACY, true);
|
boolean isLegacy = intent.getBooleanExtra(EXTRA_HANGUP_IS_LEGACY, true);
|
||||||
int deviceId = intent.getIntExtra(EXTRA_HANGUP_DEVICE_ID, 0);
|
int deviceId = intent.getIntExtra(EXTRA_HANGUP_DEVICE_ID, 0);
|
||||||
|
|
||||||
Log.i(TAG, "handleSendHangup: id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleSendHangup(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
HangupMessage hangupMessage = new HangupMessage(callId.longValue(), type, deviceId, isLegacy);
|
HangupMessage hangupMessage = new HangupMessage(callId.longValue(), type, deviceId, isLegacy);
|
||||||
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
||||||
|
@ -775,7 +796,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
||||||
boolean broadcast = intent.getBooleanExtra(EXTRA_BROADCAST, false);
|
boolean broadcast = intent.getBooleanExtra(EXTRA_BROADCAST, false);
|
||||||
|
|
||||||
Log.i(TAG, "handleSendBusy: id: " + callId.format(remoteDevice));
|
Log.i(TAG, "handleSendBusy(): id: " + callId.format(remoteDevice));
|
||||||
|
|
||||||
BusyMessage busyMessage = new BusyMessage(callId.longValue());
|
BusyMessage busyMessage = new BusyMessage(callId.longValue());
|
||||||
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
Integer destinationDeviceId = broadcast ? null : remoteDevice;
|
||||||
|
@ -805,7 +826,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
||||||
ArrayList<IceCandidateParcel> iceCandidateParcels = intent.getParcelableArrayListExtra(EXTRA_ICE_CANDIDATES);
|
ArrayList<IceCandidateParcel> iceCandidateParcels = intent.getParcelableArrayListExtra(EXTRA_ICE_CANDIDATES);
|
||||||
|
|
||||||
Log.i(TAG, "handleReceivedIceCandidates: id: " + callId.format(remoteDevice) + ", count: " + iceCandidateParcels.size());
|
Log.i(TAG, "handleReceivedIceCandidates(): id: " + callId.format(remoteDevice) + ", count: " + iceCandidateParcels.size());
|
||||||
|
|
||||||
LinkedList<IceCandidate> iceCandidates = new LinkedList();
|
LinkedList<IceCandidate> iceCandidates = new LinkedList();
|
||||||
for (IceCandidateParcel parcel : iceCandidateParcels) {
|
for (IceCandidateParcel parcel : iceCandidateParcels) {
|
||||||
|
@ -849,16 +870,16 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLocalRinging(Intent intent) {
|
private void handleLocalRinging(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
Recipient recipient = remotePeer.getRecipient();
|
Recipient recipient = remotePeer.getRecipient();
|
||||||
|
|
||||||
Log.i(TAG, "handleLocalRinging(): call_id: " + remotePeer.getCallId());
|
|
||||||
|
|
||||||
if (!remotePeer.callIdEquals(activePeer)) {
|
if (!remotePeer.callIdEquals(activePeer)) {
|
||||||
Log.w(TAG, "handleLocalRinging(): Ignoring for inactive call.");
|
Log.w(TAG, "handleLocalRinging(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "handleLocalRinging(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
activePeer.localRinging();
|
activePeer.localRinging();
|
||||||
lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
||||||
|
|
||||||
|
@ -883,30 +904,29 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRemoteRinging(Intent intent) {
|
private void handleRemoteRinging(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
Recipient recipient = remotePeer.getRecipient();
|
|
||||||
|
|
||||||
Log.i(TAG, "handleRemoteRinging(): call_id: " + remotePeer.getCallId());
|
|
||||||
|
|
||||||
if (!remotePeer.callIdEquals(activePeer)) {
|
if (!remotePeer.callIdEquals(activePeer)) {
|
||||||
Log.w(TAG, "handleRemoteRinging(): Ignoring for inactive call.");
|
Log.w(TAG, "handleRemoteRinging(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "handleRemoteRinging(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
activePeer.remoteRinging();
|
activePeer.remoteRinging();
|
||||||
sendMessage(WebRtcViewModel.State.CALL_RINGING, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_RINGING, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCallConnected(Intent intent) {
|
private void handleCallConnected(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleCallConnected: call_id: " + remotePeer.getCallId());
|
|
||||||
|
|
||||||
if (!remotePeer.callIdEquals(activePeer)) {
|
if (!remotePeer.callIdEquals(activePeer)) {
|
||||||
Log.w(TAG, "handleCallConnected(): Ignoring for inactive call.");
|
Log.w(TAG, "handleCallConnected(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "handleCallConnected(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
audioManager.startCommunication(activePeer.getState() == CallState.REMOTE_RINGING);
|
audioManager.startCommunication(activePeer.getState() == CallState.REMOTE_RINGING);
|
||||||
bluetoothStateManager.setWantsConnection(true);
|
bluetoothStateManager.setWantsConnection(true);
|
||||||
|
|
||||||
|
@ -947,7 +967,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "handleRemoteVideoEnable: call_id: " + activePeer.getCallId());
|
Log.i(TAG, "handleRemoteVideoEnable(): call_id: " + activePeer.getCallId());
|
||||||
|
|
||||||
remoteVideoEnabled = enable;
|
remoteVideoEnabled = enable;
|
||||||
sendMessage(WebRtcViewModel.State.CALL_CONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_CONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
|
@ -1007,46 +1027,49 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
|
|
||||||
private void handleLocalHangup(Intent intent) {
|
private void handleLocalHangup(Intent intent) {
|
||||||
if (activePeer == null) {
|
if (activePeer == null) {
|
||||||
|
if (busyPeer != null) {
|
||||||
|
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, busyPeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
|
busyPeer = null;
|
||||||
|
}
|
||||||
|
|
||||||
Log.w(TAG, "handleLocalHangup(): Ignoring for inactive call.");
|
Log.w(TAG, "handleLocalHangup(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "handleLocalHangup(): call_id: " + activePeer.getCallId());
|
Log.i(TAG, "handleLocalHangup(): call_id: " + activePeer.getCallId());
|
||||||
|
|
||||||
if (activePeer.getState() == CallState.RECEIVED_BUSY) {
|
accountManager.cancelInFlightRequests();
|
||||||
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
messageSender.cancelInFlightRequests();
|
||||||
terminate();
|
|
||||||
} else {
|
|
||||||
accountManager.cancelInFlightRequests();
|
|
||||||
messageSender.cancelInFlightRequests();
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
callManager.hangup();
|
||||||
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
|
terminate(activePeer);
|
||||||
try {
|
} catch (CallException e) {
|
||||||
callManager.hangup();
|
callFailure("hangup() failed: ", e);
|
||||||
} catch (CallException e) {
|
|
||||||
callFailure("hangup() failed: ", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedReceivedOfferExpired(Intent intent) {
|
private void handleEndedReceivedOfferExpired(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedReceivedOfferExpired(): call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "handleEndedReceivedOfferExpired(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
insertMissedCall(remotePeer, true);
|
insertMissedCall(remotePeer, true);
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedReceivedOfferWhileActive(Intent intent) {
|
private void handleEndedReceivedOfferWhileActive(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedReceivedOfferWhileActive(): call_id: " + remotePeer.getCallId());
|
|
||||||
|
|
||||||
if (activePeer == null) {
|
if (activePeer == null) {
|
||||||
Log.w(TAG, "handleEndedReceivedOfferWhileActive(): ignoring call with null activePeer");
|
Log.w(TAG, "handleEndedReceivedOfferWhileActive(): Ignoring for inactive call.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "handleEndedReceivedOfferWhileActive(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
switch (activePeer.getState()) {
|
switch (activePeer.getState()) {
|
||||||
case DIALING:
|
case DIALING:
|
||||||
case REMOTE_RINGING: setCallInProgressNotification(TYPE_OUTGOING_RINGING, activePeer); break;
|
case REMOTE_RINGING: setCallInProgressNotification(TYPE_OUTGOING_RINGING, activePeer); break;
|
||||||
|
@ -1062,10 +1085,12 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
insertMissedCall(remotePeer, true);
|
insertMissedCall(remotePeer, true);
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteHangup(Intent intent) {
|
private void handleEndedRemoteHangup(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedRemoteHangup(): call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "handleEndedRemoteHangup(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
|
@ -1082,80 +1107,102 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
if (incomingBeforeAccept) {
|
if (incomingBeforeAccept) {
|
||||||
insertMissedCall(remotePeer, true);
|
insertMissedCall(remotePeer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteHangupAccepted(Intent intent) {
|
private void handleEndedRemoteHangupAccepted(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
|
Log.i(TAG, "handleEndedRemoteHangupAccepted(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
sendMessage(WebRtcViewModel.State.CALL_ACCEPTED_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_ACCEPTED_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteHangupBusy(Intent intent) {
|
private void handleEndedRemoteHangupBusy(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
|
Log.i(TAG, "handleEndedRemoteHangupBusy(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
sendMessage(WebRtcViewModel.State.CALL_ONGOING_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_ONGOING_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteHangupDeclined(Intent intent) {
|
private void handleEndedRemoteHangupDeclined(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
|
Log.i(TAG, "handleEndedRemoteHangupDeclined(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
sendMessage(WebRtcViewModel.State.CALL_DECLINED_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_DECLINED_ELSEWHERE, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void delayedBusyFinish(CallId callId) {
|
terminate(remotePeer);
|
||||||
if (activePeer != null && callId.equals(activePeer.getCallId())) {
|
|
||||||
Log.i(TAG, "delayedBusyFinish(): calling terminate()");
|
|
||||||
terminate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteBusy(Intent intent) {
|
private void handleEndedRemoteBusy(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
CallId callId = remotePeer.getCallId();
|
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedRemoteBusy(): call_id: " + callId);
|
Log.i(TAG, "handleEndedRemoteBusy(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (!remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
Log.w(TAG, "handleEndedRemoteBusy(): Ignoring for inactive call.");
|
activePeer.receivedBusy();
|
||||||
return;
|
busyPeer = activePeer;
|
||||||
|
|
||||||
|
OutgoingRinger ringer = new OutgoingRinger(this);
|
||||||
|
ringer.start(OutgoingRinger.Type.BUSY);
|
||||||
|
Util.runOnMainDelayed(() -> {
|
||||||
|
ringer.stop();
|
||||||
|
busyPeer = null;
|
||||||
|
}, BUSY_TONE_LENGTH);
|
||||||
|
|
||||||
|
sendMessage(WebRtcViewModel.State.CALL_BUSY, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
activePeer.receivedBusy();
|
terminate(remotePeer);
|
||||||
sendMessage(WebRtcViewModel.State.CALL_BUSY, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
|
||||||
|
|
||||||
audioManager.startOutgoingRinger(OutgoingRinger.Type.BUSY);
|
|
||||||
Util.runOnMainDelayed(() -> {
|
|
||||||
delayedBusyFinish(callId);
|
|
||||||
}, WebRtcCallActivity.BUSY_SIGNAL_DELAY_FINISH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteNeedPermission(Intent intent) {
|
private void handleEndedRemoteNeedPermission(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedRemoteNeedPermission(): call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "handleEndedRemoteNeedPermission(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
sendMessage(WebRtcViewModel.State.CALL_NEEDS_PERMISSION, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_NEEDS_PERMISSION, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedRemoteGlare(Intent intent) {
|
private void handleEndedRemoteGlare(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedRemoteGlare(): call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "handleEndedRemoteGlare(): call_id: " + remotePeer.getCallId());
|
||||||
handleEndedRemoteBusy(intent);
|
|
||||||
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
|
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, remotePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean incomingBeforeAccept = remotePeer.getState() == CallState.ANSWERING || remotePeer.getState() == CallState.LOCAL_RINGING;
|
||||||
|
if (incomingBeforeAccept) {
|
||||||
|
insertMissedCall(remotePeer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedFailure(Intent intent) {
|
private void handleEndedFailure(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
|
|
||||||
Log.i(TAG, "handleEndedFailure(): call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "handleEndedFailure(): call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
if (remotePeer.callIdEquals(activePeer)) {
|
if (remotePeer.callIdEquals(activePeer)) {
|
||||||
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
@ -1163,6 +1210,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
if (remotePeer.getState() == CallState.ANSWERING || remotePeer.getState() == CallState.LOCAL_RINGING) {
|
if (remotePeer.getState() == CallState.ANSWERING || remotePeer.getState() == CallState.LOCAL_RINGING) {
|
||||||
insertMissedCall(remotePeer, true);
|
insertMissedCall(remotePeer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminate(remotePeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEndedTimeout(Intent intent) {
|
private void handleEndedTimeout(Intent intent) {
|
||||||
|
@ -1190,22 +1239,15 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCallConcluded(Intent intent) {
|
private void handleCallConcluded(Intent intent) {
|
||||||
RemotePeer remotePeer = getRemotePeer(intent);
|
Log.i(TAG, "handleCallConcluded():");
|
||||||
|
|
||||||
Log.i(TAG, "handleCallConcluded(): call_id: " + remotePeer.getCallId());
|
RemotePeer remotePeer = getRemotePeerFromMap(intent);
|
||||||
if (!remotePeer.callIdEquals(activePeer)) {
|
|
||||||
Log.w(TAG, "handleCallConcluded(): Ignoring for inactive call.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean terminateAlreadyScheduled = activePeer.getState() == CallState.RECEIVED_BUSY;
|
Log.i(TAG, "delete remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode());
|
||||||
if (!terminateAlreadyScheduled) {
|
|
||||||
terminate();
|
peerMap.delete(remotePeer.hashCode());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper Methods
|
|
||||||
|
|
||||||
private boolean isIdle() {
|
private boolean isIdle() {
|
||||||
return activePeer == null;
|
return activePeer == null;
|
||||||
}
|
}
|
||||||
|
@ -1222,7 +1264,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
|
|
||||||
camera = new Camera(WebRtcCallService.this, WebRtcCallService.this, eglBase);
|
camera = new Camera(WebRtcCallService.this, WebRtcCallService.this, eglBase);
|
||||||
localCameraState = camera.getCameraState();
|
localCameraState = camera.getCameraState();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1231,11 +1272,16 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
CallNotificationBuilder.getCallInProgressNotification(this, type, remotePeer.getRecipient()));
|
CallNotificationBuilder.getCallInProgressNotification(this, type, remotePeer.getRecipient()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void terminate() {
|
private synchronized void terminate(RemotePeer remotePeer) {
|
||||||
Log.i(TAG, "terminate()");
|
Log.i(TAG, "terminate():");
|
||||||
|
|
||||||
if (activePeer == null) {
|
if (activePeer == null) {
|
||||||
Log.i(TAG, "terminate(): skipping with no active peer");
|
Log.i(TAG, "skipping with no active peer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remotePeer.callIdEquals(activePeer)) {
|
||||||
|
Log.i(TAG, "skipping remotePeer is not active peer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1264,11 +1310,13 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localCameraState = CameraState.UNKNOWN;
|
this.localCameraState = CameraState.UNKNOWN;
|
||||||
this.activePeer = null;
|
|
||||||
this.microphoneEnabled = true;
|
this.microphoneEnabled = true;
|
||||||
this.remoteVideoEnabled = false;
|
this.remoteVideoEnabled = false;
|
||||||
this.enableVideoOnCreate = false;
|
this.enableVideoOnCreate = false;
|
||||||
|
|
||||||
|
Log.i(TAG, "clear activePeer callId: " + activePeer.getCallId() + " key: " + activePeer.hashCode());
|
||||||
|
this.activePeer = null;
|
||||||
|
|
||||||
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,8 +1404,29 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
return remotePeer;
|
return remotePeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static @NonNull int getRemotePeerKey(Intent intent) {
|
||||||
|
if (!intent.getExtras().containsKey(EXTRA_REMOTE_PEER_KEY)) {
|
||||||
|
throw new AssertionError("No RemotePeer key in intent!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default of -1 should never be applied since the key exists.
|
||||||
|
int remotePeerKey = intent.getIntExtra(EXTRA_REMOTE_PEER_KEY, -1);
|
||||||
|
|
||||||
|
return remotePeerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NonNull RemotePeer getRemotePeerFromMap(Intent intent) {
|
||||||
|
int remotePeerKey = getRemotePeerKey(intent);
|
||||||
|
RemotePeer remotePeer = peerMap.get(remotePeerKey);
|
||||||
|
if (remotePeer == null) {
|
||||||
|
throw new AssertionError("No RemotePeer in map for key: " + remotePeerKey + "!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return remotePeer;
|
||||||
|
}
|
||||||
|
|
||||||
private void callFailure(String message, Throwable error) {
|
private void callFailure(String message, Throwable error) {
|
||||||
Log.w(TAG, message, error);
|
Log.w(TAG, "callFailure(): " + message, error);
|
||||||
|
|
||||||
if (activePeer != null) {
|
if (activePeer != null) {
|
||||||
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
|
@ -1373,7 +1442,9 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
Log.w(TAG, "No call manager, not reseting. Error message: " + message , error);
|
Log.w(TAG, "No call manager, not reseting. Error message: " + message , error);
|
||||||
}
|
}
|
||||||
|
|
||||||
terminate();
|
terminate(activePeer);
|
||||||
|
|
||||||
|
peerMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull CallManager.CallMediaType getCallMediaTypeFromOfferType(@NonNull OfferMessage.Type offerType) {
|
private static @NonNull CallManager.CallMediaType getCallMediaTypeFromOfferType(@NonNull OfferMessage.Type offerType) {
|
||||||
|
@ -1645,7 +1716,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
} else if (error instanceof IOException) {
|
} else if (error instanceof IOException) {
|
||||||
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, activePeer, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled, isRemoteVideoOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1663,34 +1733,32 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallManager observer callbacks
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartCall(Remote remote, CallId callId, Boolean isOutgoing, CallManager.CallMediaType callMediaType) {
|
public void onStartCall(Remote remote, CallId callId, Boolean isOutgoing, CallManager.CallMediaType callMediaType) {
|
||||||
Log.i(TAG, "onStartCall: callId: " + callId + ", outgoing: " + isOutgoing + ", type: " + callMediaType);
|
Log.i(TAG, "onStartCall(): callId: " + callId + ", outgoing: " + isOutgoing + ", type: " + callMediaType);
|
||||||
|
|
||||||
if (activePeer != null) {
|
|
||||||
throw new IllegalStateException("activePeer already set for START_OUTGOING_CALL");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remote instanceof RemotePeer) {
|
if (remote instanceof RemotePeer) {
|
||||||
activePeer = (RemotePeer)remote;
|
RemotePeer remotePeer = (RemotePeer) remote;
|
||||||
|
if (peerMap.get(remotePeer.hashCode()) == null) {
|
||||||
|
Log.w(TAG, "remotePeer not found in map with key: " + remotePeer.hashCode() + "! Dropping.");
|
||||||
|
try {
|
||||||
|
callManager.drop(callId);
|
||||||
|
} catch (CallException e) {
|
||||||
|
callFailure("callManager.drop() failed: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remotePeer.setCallId(callId);
|
||||||
|
|
||||||
Intent intent = new Intent(this, WebRtcCallService.class);
|
Intent intent = new Intent(this, WebRtcCallService.class);
|
||||||
|
|
||||||
AudioManager audioManager = ServiceUtil.getAudioManager(this);
|
|
||||||
audioManager.setSpeakerphoneOn(false);
|
|
||||||
|
|
||||||
if (isOutgoing) {
|
if (isOutgoing) {
|
||||||
intent.setAction(ACTION_START_OUTGOING_CALL);
|
intent.setAction(ACTION_START_OUTGOING_CALL);
|
||||||
activePeer.dialing(callId);
|
|
||||||
} else {
|
} else {
|
||||||
intent.setAction(ACTION_START_INCOMING_CALL);
|
intent.setAction(ACTION_START_INCOMING_CALL);
|
||||||
activePeer.answering(callId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intent.putExtra(EXTRA_REMOTE_PEER, activePeer)
|
intent.putExtra(EXTRA_REMOTE_PEER_KEY, remotePeer.hashCode());
|
||||||
.putExtra(EXTRA_CALL_ID, callId.longValue());
|
|
||||||
|
|
||||||
startService(intent);
|
startService(intent);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1701,11 +1769,15 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
@Override
|
@Override
|
||||||
public void onCallEvent(Remote remote, CallEvent event) {
|
public void onCallEvent(Remote remote, CallEvent event) {
|
||||||
if (remote instanceof RemotePeer) {
|
if (remote instanceof RemotePeer) {
|
||||||
RemotePeer remotePeer = (RemotePeer)remote;
|
RemotePeer remotePeer = (RemotePeer) remote;
|
||||||
Intent intent = new Intent(this, WebRtcCallService.class);
|
if (peerMap.get(remotePeer.hashCode()) == null) {
|
||||||
|
throw new AssertionError("remotePeer not found in map!");
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "onCallEvent: call_id: " + remotePeer.getCallId() + ", event: " + event);
|
Log.i(TAG, "onCallEvent(): call_id: " + remotePeer.getCallId() + ", state: " + remotePeer.getState() + ", event: " + event);
|
||||||
intent.putExtra(EXTRA_REMOTE_PEER, remotePeer);
|
|
||||||
|
Intent intent = new Intent(this, WebRtcCallService.class);
|
||||||
|
intent.putExtra(EXTRA_REMOTE_PEER_KEY, remotePeer.hashCode());
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case LOCAL_RINGING:
|
case LOCAL_RINGING:
|
||||||
|
@ -1790,11 +1862,13 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||||
public void onCallConcluded(Remote remote) {
|
public void onCallConcluded(Remote remote) {
|
||||||
if (remote instanceof RemotePeer) {
|
if (remote instanceof RemotePeer) {
|
||||||
RemotePeer remotePeer = (RemotePeer)remote;
|
RemotePeer remotePeer = (RemotePeer)remote;
|
||||||
Intent intent = new Intent(this, WebRtcCallService.class);
|
|
||||||
|
|
||||||
Log.i(TAG, "onCallConcluded: call_id: " + remotePeer.getCallId());
|
Log.i(TAG, "onCallConcluded: call_id: " + remotePeer.getCallId());
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, WebRtcCallService.class);
|
||||||
intent.setAction(ACTION_CALL_CONCLUDED)
|
intent.setAction(ACTION_CALL_CONCLUDED)
|
||||||
.putExtra(EXTRA_REMOTE_PEER, remotePeer);
|
.putExtra(EXTRA_REMOTE_PEER_KEY, remotePeer.hashCode());
|
||||||
|
|
||||||
startService(intent);
|
startService(intent);
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError("Received remote is not instanceof RemotePeer");
|
throw new AssertionError("Received remote is not instanceof RemotePeer");
|
||||||
|
|
Loading…
Reference in New Issue