Better support for building webrtc call view off of model

Fixes #6144
// FREEBIE
master
Moxie Marlinspike 2017-02-02 18:34:51 -08:00
parent 8dc6f2b15b
commit 9a93a8b28d
7 changed files with 207 additions and 166 deletions

View File

@ -41,7 +41,7 @@ import org.thoughtcrime.securesms.components.webrtc.WebRtcCallScreen;
import org.thoughtcrime.securesms.components.webrtc.WebRtcIncomingCallOverlay;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.events.WebRtcCallEvent;
import org.thoughtcrime.securesms.events.WebRtcViewModel;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -66,6 +66,7 @@ public class WebRtcCallActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
Log.w(TAG, "onCreate()");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
super.onCreate(savedInstanceState);
@ -80,6 +81,7 @@ public class WebRtcCallActivity extends Activity {
@Override
public void onResume() {
Log.w(TAG, "onResume()");
super.onResume();
initializeScreenshotSecurity();
@ -89,6 +91,7 @@ public class WebRtcCallActivity extends Activity {
@Override
public void onNewIntent(Intent intent){
Log.w(TAG, "onNewIntent");
if (ANSWER_ACTION.equals(intent.getAction())) {
handleAnswerCall();
} else if (DENY_ACTION.equals(intent.getAction())) {
@ -100,6 +103,7 @@ public class WebRtcCallActivity extends Activity {
@Override
public void onPause() {
Log.w(TAG, "onPause");
super.onPause();
EventBus.getDefault().unregister(this);
@ -138,7 +142,7 @@ public class WebRtcCallActivity extends Activity {
}
private void handleSetMuteVideo(boolean muted) {
callScreen.setLocalVideoEnabled(!muted);
// callScreen.setLocalVideoEnabled(!muted);
Intent intent = new Intent(this, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_SET_MUTE_VIDEO);
@ -147,7 +151,7 @@ public class WebRtcCallActivity extends Activity {
}
private void handleAnswerCall() {
WebRtcCallEvent event = EventBus.getDefault().getStickyEvent(WebRtcCallEvent.class);
WebRtcViewModel event = EventBus.getDefault().getStickyEvent(WebRtcViewModel.class);
if (event != null) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_answering));
@ -159,7 +163,7 @@ public class WebRtcCallActivity extends Activity {
}
private void handleDenyCall() {
WebRtcCallEvent event = EventBus.getDefault().getStickyEvent(WebRtcCallEvent.class);
WebRtcViewModel event = EventBus.getDefault().getStickyEvent(WebRtcViewModel.class);
if (event != null) {
Intent intent = new Intent(this, WebRtcCallService.class);
@ -177,18 +181,18 @@ public class WebRtcCallActivity extends Activity {
intent.setAction(WebRtcCallService.ACTION_LOCAL_HANGUP);
startService(intent);
WebRtcCallEvent event = EventBus.getDefault().getStickyEvent(WebRtcCallEvent.class);
WebRtcViewModel event = EventBus.getDefault().getStickyEvent(WebRtcViewModel.class);
if (event != null) {
WebRtcCallActivity.this.handleTerminate(event.getRecipient());
}
}
private void handleIncomingCall(@NonNull WebRtcCallEvent event) {
private void handleIncomingCall(@NonNull WebRtcViewModel event) {
callScreen.setIncomingCall(event.getRecipient());
}
private void handleOutgoingCall(@NonNull WebRtcCallEvent event) {
private void handleOutgoingCall(@NonNull WebRtcViewModel event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_dialing));
}
@ -196,55 +200,37 @@ public class WebRtcCallActivity extends Activity {
Log.w(TAG, "handleTerminate called");
callScreen.setActiveCall(recipient, getString(R.string.RedPhone_ending_call));
EventBus.getDefault().removeStickyEvent(WebRtcCallEvent.class);
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
delayedFinish();
}
private void handleCallRinging(@NonNull WebRtcCallEvent event) {
private void handleCallRinging(@NonNull WebRtcViewModel event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ringing));
}
private void handleCallBusy(@NonNull WebRtcCallEvent event) {
private void handleCallBusy(@NonNull WebRtcViewModel event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_busy));
delayedFinish(BUSY_SIGNAL_DELAY_FINISH);
}
private void handleCallConnected(@NonNull WebRtcCallEvent event) {
private void handleCallConnected(@NonNull WebRtcViewModel event) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES);
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_connected), "");
}
private void handleConnectingToInitiator(@NonNull WebRtcCallEvent event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_connecting));
}
private void handleHandshakeFailed(@NonNull WebRtcCallEvent event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_handshake_failed));
delayedFinish();
}
private void handleRecipientUnavailable(@NonNull WebRtcCallEvent event) {
private void handleRecipientUnavailable(@NonNull WebRtcViewModel event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_recipient_unavailable));
delayedFinish();
}
private void handlePerformingHandshake(@NonNull WebRtcCallEvent event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_performing_handshake));
}
private void handleServerFailure(@NonNull WebRtcCallEvent event) {
private void handleServerFailure(@NonNull WebRtcViewModel event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_network_failed));
delayedFinish();
}
private void handleLoginFailed(@NonNull WebRtcCallEvent event) {
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_login_failed));
delayedFinish();
}
private void handleNoSuchUser(final @NonNull WebRtcCallEvent event) {
private void handleNoSuchUser(final @NonNull WebRtcViewModel event) {
if (isFinishing()) return; // XXX Stuart added this check above, not sure why, so I'm repeating in ignorance. - moxie
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle(R.string.RedPhone_number_not_registered);
@ -266,16 +252,8 @@ public class WebRtcCallActivity extends Activity {
dialog.show();
}
private void handleRemoteVideoDisabled(@NonNull WebRtcCallEvent event) {
callScreen.setRemoteVideoEnabled(false);
}
private void handleRemoteVideoEnabled(@NonNull WebRtcCallEvent event) {
callScreen.setRemoteVideoEnabled(true);
}
private void handleUntrustedIdentity(@NonNull WebRtcCallEvent event) {
final IdentityKey theirIdentity = (IdentityKey)event.getExtra();
private void handleUntrustedIdentity(@NonNull WebRtcViewModel event) {
final IdentityKey theirIdentity = event.getIdentityKey();
final Recipient recipient = event.getRecipient();
callScreen.setUntrustedIdentity(recipient, theirIdentity);
@ -313,27 +291,24 @@ public class WebRtcCallActivity extends Activity {
}
@SuppressWarnings("unused")
public void onEventMainThread(final WebRtcCallEvent event) {
Log.w(TAG, "Got message from service: " + event.getType());
public void onEventMainThread(final WebRtcViewModel event) {
Log.w(TAG, "Got message from service: " + event);
switch (event.getType()) {
switch (event.getState()) {
case CALL_CONNECTED: handleCallConnected(event); break;
case SERVER_FAILURE: handleServerFailure(event); break;
case PERFORMING_HANDSHAKE: handlePerformingHandshake(event); break;
case HANDSHAKE_FAILED: handleHandshakeFailed(event); break;
case CONNECTING_TO_INITIATOR: handleConnectingToInitiator(event); break;
case NETWORK_FAILURE: handleServerFailure(event); break;
case CALL_RINGING: handleCallRinging(event); break;
case CALL_DISCONNECTED: handleTerminate(event.getRecipient()); break;
case NO_SUCH_USER: handleNoSuchUser(event); break;
case RECIPIENT_UNAVAILABLE: handleRecipientUnavailable(event); break;
case INCOMING_CALL: handleIncomingCall(event); break;
case OUTGOING_CALL: handleOutgoingCall(event); break;
case CALL_INCOMING: handleIncomingCall(event); break;
case CALL_OUTGOING: handleOutgoingCall(event); break;
case CALL_BUSY: handleCallBusy(event); break;
case LOGIN_FAILED: handleLoginFailed(event); break;
case REMOTE_VIDEO_DISABLED: handleRemoteVideoDisabled(event); break;
case REMOTE_VIDEO_ENABLED: handleRemoteVideoEnabled(event); break;
case UNTRUSTED_IDENTITY: handleUntrustedIdentity(event); break;
}
callScreen.setLocalVideoEnabled(event.isLocalVideoEnabled());
callScreen.setRemoteVideoEnabled(event.isRemoteVideoEnabled());
}
private class HangupButtonListener implements WebRtcCallScreen.HangupButtonListener {

View File

@ -60,6 +60,10 @@ public class PercentFrameLayout extends ViewGroup {
this.hidden = hidden;
}
public boolean isHidden() {
return this.hidden;
}
public void setPosition(int xPercent, int yPercent, int widthPercent, int heightPercent) {
this.xPercent = xPercent;
this.yPercent = yPercent;

View File

@ -99,6 +99,10 @@ public class WebRtcCallControls extends LinearLayout {
});
}
public boolean isVideoMuted() {
return !videoMuteButton.isChecked();
}
public void setAudioButtonListener(final AudioButtonListener listener) {
audioButton.setListener(listener);
}

View File

@ -180,23 +180,23 @@ public class WebRtcCallScreen extends FrameLayout implements Recipient.Recipient
}
public void setLocalVideoEnabled(boolean enabled) {
if (enabled) {
if (enabled && this.localRenderLayout.isHidden()) {
this.localRenderLayout.setHidden(false);
} else {
this.localRenderLayout.requestLayout();
} else if (!enabled && !this.localRenderLayout.isHidden()){
this.localRenderLayout.setHidden(true);
this.localRenderLayout.requestLayout();
}
this.localRenderLayout.requestLayout();
}
public void setRemoteVideoEnabled(boolean enabled) {
if (enabled) {
if (enabled && this.remoteRenderLayout.isHidden()) {
this.remoteRenderLayout.setHidden(false);
} else {
this.remoteRenderLayout.requestLayout();
} else if (!enabled && !this.remoteRenderLayout.isHidden()){
this.remoteRenderLayout.setHidden(true);
this.remoteRenderLayout.requestLayout();
}
this.remoteRenderLayout.requestLayout();
}
private void initialize() {
@ -226,21 +226,31 @@ public class WebRtcCallScreen extends FrameLayout implements Recipient.Recipient
private void setConnected(SurfaceViewRenderer localRenderer,
SurfaceViewRenderer remoteRenderer)
{
localRenderLayout.setPosition(7, 7, 25, 25);
localRenderLayout.setSquare(true);
remoteRenderLayout.setPosition(0, 0, 100, 100);
if (localRenderLayout.getChildCount() == 0 && remoteRenderLayout.getChildCount() == 0) {
if (localRenderer.getParent() != null) {
((ViewGroup)localRenderer.getParent()).removeView(localRenderer);
}
localRenderer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
if (remoteRenderer.getParent() != null) {
((ViewGroup)remoteRenderer.getParent()).removeView(remoteRenderer);
}
remoteRenderer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
localRenderLayout.setPosition(7, 7, 25, 25);
localRenderLayout.setSquare(true);
remoteRenderLayout.setPosition(0, 0, 100, 100);
localRenderer.setMirror(true);
localRenderer.setZOrderMediaOverlay(true);
localRenderer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
localRenderLayout.addView(localRenderer);
remoteRenderLayout.addView(remoteRenderer);
remoteRenderer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
localRenderer.setMirror(true);
localRenderer.setZOrderMediaOverlay(true);
localRenderLayout.addView(localRenderer);
remoteRenderLayout.addView(remoteRenderer);
}
}
private void setPersonInfo(final @NonNull Recipient recipient) {

View File

@ -1,52 +0,0 @@
package org.thoughtcrime.securesms.events;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.recipients.Recipient;
public class WebRtcCallEvent {
public enum Type {
CALL_CONNECTED,
WAITING_FOR_RESPONDER,
SERVER_FAILURE,
PERFORMING_HANDSHAKE,
HANDSHAKE_FAILED,
CONNECTING_TO_INITIATOR,
CALL_DISCONNECTED,
CALL_RINGING,
RECIPIENT_UNAVAILABLE,
INCOMING_CALL,
OUTGOING_CALL,
CALL_BUSY,
LOGIN_FAILED,
DEBUG_INFO,
NO_SUCH_USER,
REMOTE_VIDEO_ENABLED,
REMOTE_VIDEO_DISABLED,
UNTRUSTED_IDENTITY
}
private final @NonNull Type type;
private final @NonNull Recipient recipient;
private final @Nullable Object extra;
public WebRtcCallEvent(@NonNull Type type, @NonNull Recipient recipient, @Nullable Object extra) {
this.type = type;
this.recipient = recipient;
this.extra = extra;
}
public @NonNull Type getType() {
return type;
}
public @NonNull Recipient getRecipient() {
return recipient;
}
public @Nullable Object getExtra() {
return extra;
}
}

View File

@ -0,0 +1,74 @@
package org.thoughtcrime.securesms.events;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.libsignal.IdentityKey;
public class WebRtcViewModel {
public enum State {
// Normal states
CALL_INCOMING,
CALL_OUTGOING,
CALL_CONNECTED,
CALL_RINGING,
CALL_BUSY,
CALL_DISCONNECTED,
// Error states
NETWORK_FAILURE,
RECIPIENT_UNAVAILABLE,
NO_SUCH_USER,
UNTRUSTED_IDENTITY,
}
private final @NonNull State state;
private final @NonNull Recipient recipient;
private final @Nullable IdentityKey identityKey;
private final boolean remoteVideoEnabled;
private final boolean localVideoEnabled;
public WebRtcViewModel(@NonNull State state, @NonNull Recipient recipient, boolean localVideoEnabled, boolean remoteVideoEnabled) {
this(state, recipient, null, localVideoEnabled, remoteVideoEnabled);
}
public WebRtcViewModel(@NonNull State state, @NonNull Recipient recipient,
@Nullable IdentityKey identityKey,
boolean localVideoEnabled, boolean remoteVideoEnabled)
{
this.state = state;
this.recipient = recipient;
this.identityKey = identityKey;
this.localVideoEnabled = localVideoEnabled;
this.remoteVideoEnabled = remoteVideoEnabled;
}
public @NonNull State getState() {
return state;
}
public @NonNull Recipient getRecipient() {
return recipient;
}
@Nullable
public IdentityKey getIdentityKey() {
return identityKey;
}
public boolean isRemoteVideoEnabled() {
return remoteVideoEnabled;
}
public boolean isLocalVideoEnabled() {
return localVideoEnabled;
}
public String toString() {
return "[State: " + state + ", recipient: " + recipient.getNumber() + ", identity: " + identityKey + ", remoteVideo: " + remoteVideoEnabled + ", localVideo: " + localVideoEnabled + "]";
}
}

View File

@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.events.WebRtcCallEvent;
import org.thoughtcrime.securesms.events.WebRtcViewModel;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@ -57,6 +57,7 @@ import org.webrtc.SessionDescription;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoTrack;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
@ -68,8 +69,8 @@ import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
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.util.InvalidNumberException;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -111,8 +112,8 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
public static final String EXTRA_ICE_SDP_MID = "ice_sdp_mid";
public static final String EXTRA_ICE_SDP_LINE_INDEX = "ice_sdp_line_index";
public static final String ACTION_INCOMING_CALL = "INCOMING_CALL";
public static final String ACTION_OUTGOING_CALL = "OUTGOING_CALL";
public static final String ACTION_INCOMING_CALL = "CALL_INCOMING";
public static final String ACTION_OUTGOING_CALL = "CALL_OUTGOING";
public static final String ACTION_ANSWER_CALL = "ANSWER_CALL";
public static final String ACTION_DENY_CALL = "DENY_CALL";
public static final String ACTION_LOCAL_HANGUP = "LOCAL_HANGUP";
@ -129,10 +130,11 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
public static final String ACTION_REMOTE_VIDEO_MUTE = "REMOTE_VIDEO_MUTE";
public static final String ACTION_ICE_CONNECTED = "ICE_CONNECTED";
private CallState callState = CallState.STATE_IDLE;
private boolean audioEnabled = true;
private boolean videoEnabled = false;
private Handler serviceHandler = new Handler();
private CallState callState = CallState.STATE_IDLE;
private boolean audioEnabled = true;
private boolean localVideoEnabled = false;
private boolean remoteVideoEnabled = false;
private Handler serviceHandler = new Handler();
@Inject public SignalMessageSenderFactory messageSenderFactory;
@Inject public SignalServiceAccountManager accountManager;
@ -289,7 +291,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
initializeVideo();
sendMessage(WebRtcCallEvent.Type.OUTGOING_CALL, recipient, null);
sendMessage(WebRtcViewModel.State.CALL_OUTGOING, recipient, localVideoEnabled, remoteVideoEnabled);
lockManager.updatePhoneState(LockManager.PhoneState.IN_CALL);
outgoingRinger.playSonar();
@ -317,10 +319,13 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
@Override
public void onFailureContinue(Throwable error) {
Log.w(TAG, error);
if (error instanceof IOException) {
sendMessage(WebRtcCallEvent.Type.SERVER_FAILURE, recipient, null);
} else if (error instanceof UntrustedIdentityException) {
sendMessage(WebRtcCallEvent.Type.UNTRUSTED_IDENTITY, recipient, ((UntrustedIdentityException)error).getIdentityKey());
if (error instanceof UntrustedIdentityException) {
sendMessage(WebRtcViewModel.State.UNTRUSTED_IDENTITY, recipient, ((UntrustedIdentityException)error).getIdentityKey(), localVideoEnabled, remoteVideoEnabled);
} else if (error instanceof UnregisteredUserException) {
sendMessage(WebRtcViewModel.State.NO_SUCH_USER, recipient, localVideoEnabled, remoteVideoEnabled);
} else if (error instanceof IOException) {
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, recipient, localVideoEnabled, remoteVideoEnabled);
}
terminate();
@ -357,7 +362,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
@Override
public void onFailureContinue(Throwable error) {
Log.w(TAG, error);
sendMessage(WebRtcCallEvent.Type.SERVER_FAILURE, recipient, null);
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, recipient, localVideoEnabled, remoteVideoEnabled);
terminate();
}
@ -406,7 +411,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
@Override
public void onFailureContinue(Throwable error) {
Log.w(TAG, error);
sendMessage(WebRtcCallEvent.Type.SERVER_FAILURE, recipient, null);
sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, recipient, localVideoEnabled, remoteVideoEnabled);
terminate();
}
@ -420,7 +425,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
this.callState = CallState.STATE_LOCAL_RINGING;
this.lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
sendMessage(WebRtcCallEvent.Type.INCOMING_CALL, recipient, null);
sendMessage(WebRtcViewModel.State.CALL_INCOMING, recipient, localVideoEnabled, remoteVideoEnabled);
startCallCardActivity();
incomingRinger.start();
CallNotificationManager.setCallInProgress(this, TYPE_INCOMING_RINGING, recipient);
@ -430,7 +435,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
this.callState = CallState.STATE_REMOTE_RINGING;
this.outgoingRinger.playRing();
sendMessage(WebRtcCallEvent.Type.CALL_RINGING, recipient, null);
sendMessage(WebRtcViewModel.State.CALL_RINGING, recipient, localVideoEnabled, remoteVideoEnabled);
}
}
@ -455,17 +460,17 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
outgoingRinger.playComplete();
lockManager.updatePhoneState(LockManager.PhoneState.IN_CALL);
sendMessage(WebRtcCallEvent.Type.CALL_CONNECTED, recipient, "un used");
sendMessage(WebRtcViewModel.State.CALL_CONNECTED, recipient, localVideoEnabled, remoteVideoEnabled);
CallNotificationManager.setCallInProgress(this, TYPE_ESTABLISHED, recipient);
this.peerConnection.setAudioEnabled(audioEnabled);
this.peerConnection.setVideoEnabled(videoEnabled);
this.peerConnection.setVideoEnabled(localVideoEnabled);
this.dataChannel.send(new DataChannel.Buffer(ByteBuffer.wrap(Data.newBuilder()
.setVideoStreamingStatus(WebRtcDataProtos.VideoStreamingStatus.newBuilder()
.setId(this.callId)
.setEnabled(videoEnabled))
.setEnabled(localVideoEnabled))
.build().toByteArray()), false));
}
@ -488,7 +493,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
return;
}
sendMessage(WebRtcCallEvent.Type.CALL_BUSY, recipient, null);
sendMessage(WebRtcViewModel.State.CALL_BUSY, recipient, localVideoEnabled, remoteVideoEnabled);
outgoingRinger.playBusy();
serviceHandler.postDelayed(new Runnable() {
@ -505,7 +510,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
this.callState != CallState.STATE_CONNECTED)
{
Log.w(TAG, "Timing out call: " + this.callId);
sendMessage(WebRtcCallEvent.Type.CALL_DISCONNECTED, this.recipient, null);
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, this.recipient, localVideoEnabled, remoteVideoEnabled);
terminate();
}
}
@ -580,9 +585,9 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
}
if (this.callState == CallState.STATE_DIALING || this.callState == CallState.STATE_REMOTE_RINGING) {
sendMessage(WebRtcCallEvent.Type.RECIPIENT_UNAVAILABLE, this.recipient, null);
sendMessage(WebRtcViewModel.State.RECIPIENT_UNAVAILABLE, this.recipient, localVideoEnabled, remoteVideoEnabled);
} else {
sendMessage(WebRtcCallEvent.Type.CALL_DISCONNECTED, this.recipient, null);
sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, this.recipient, localVideoEnabled, remoteVideoEnabled);
}
if (this.callState == CallState.STATE_ANSWERING || this.callState == CallState.STATE_LOCAL_RINGING) {
@ -603,19 +608,21 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
private void handleSetMuteVideo(Intent intent) {
boolean muted = intent.getBooleanExtra(EXTRA_MUTE, false);
this.videoEnabled = !muted;
this.localVideoEnabled = !muted;
if (this.peerConnection != null) {
this.peerConnection.setVideoEnabled(this.videoEnabled);
this.peerConnection.setVideoEnabled(this.localVideoEnabled);
}
if (this.callId != null && this.dataChannel != null) {
this.dataChannel.send(new DataChannel.Buffer(ByteBuffer.wrap(Data.newBuilder()
.setVideoStreamingStatus(WebRtcDataProtos.VideoStreamingStatus.newBuilder()
.setId(this.callId)
.setEnabled(videoEnabled))
.setEnabled(localVideoEnabled))
.build().toByteArray()), false));
}
sendMessage(viewModelStateFor(callState), this.recipient, localVideoEnabled, remoteVideoEnabled);
}
private void handleRemoteVideoMute(Intent intent) {
@ -627,11 +634,8 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
return;
}
if (muted) {
sendMessage(WebRtcCallEvent.Type.REMOTE_VIDEO_DISABLED, this.recipient, null);
} else {
sendMessage(WebRtcCallEvent.Type.REMOTE_VIDEO_ENABLED, this.recipient, null);
}
this.remoteVideoEnabled = !muted;
sendMessage(WebRtcViewModel.State.CALL_CONNECTED, this.recipient, localVideoEnabled, remoteVideoEnabled);
}
/// Helper Methods
@ -709,21 +713,30 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
shutdownAudio();
this.callState = CallState.STATE_IDLE;
this.recipient = null;
this.callId = null;
this.audioEnabled = true;
this.videoEnabled = false;
this.pendingIceUpdates = null;
this.callState = CallState.STATE_IDLE;
this.recipient = null;
this.callId = null;
this.audioEnabled = true;
this.localVideoEnabled = false;
this.remoteVideoEnabled = false;
this.pendingIceUpdates = null;
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
}
private void sendMessage(@NonNull WebRtcCallEvent.Type type,
private void sendMessage(@NonNull WebRtcViewModel.State state,
@NonNull Recipient recipient,
@Nullable Object extra)
boolean localVideoEnabled, boolean remoteVideoEnabled)
{
EventBus.getDefault().postSticky(new WebRtcCallEvent(type, recipient, extra));
EventBus.getDefault().postSticky(new WebRtcViewModel(state, recipient, localVideoEnabled, remoteVideoEnabled));
}
private void sendMessage(@NonNull WebRtcViewModel.State state,
@NonNull Recipient recipient,
@NonNull IdentityKey identityKey,
boolean localVideoEnabled, boolean remoteVideoEnabled)
{
EventBus.getDefault().postSticky(new WebRtcViewModel(state, recipient, identityKey, localVideoEnabled, remoteVideoEnabled));
}
private ListenableFutureTask<Boolean> sendMessage(@NonNull final Recipient recipient,
@ -952,6 +965,19 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
return futureTask;
}
private WebRtcViewModel.State viewModelStateFor(CallState state) {
switch (state) {
case STATE_CONNECTED: return WebRtcViewModel.State.CALL_CONNECTED;
case STATE_DIALING: return WebRtcViewModel.State.CALL_OUTGOING;
case STATE_REMOTE_RINGING: return WebRtcViewModel.State.CALL_RINGING;
case STATE_LOCAL_RINGING: return WebRtcViewModel.State.CALL_INCOMING;
case STATE_ANSWERING: return WebRtcViewModel.State.CALL_INCOMING;
case STATE_IDLE: return WebRtcViewModel.State.CALL_DISCONNECTED;
}
return WebRtcViewModel.State.CALL_DISCONNECTED;
}
private class TimeoutRunnable implements Runnable {
private final long callId;