mirror of
				https://github.com/oxen-io/session-android.git
				synced 2025-11-04 01:01:22 +00:00 
			
		
		
		
	Better support for building webrtc call view off of model
Fixes #6144 // FREEBIE
This commit is contained in:
		@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -99,6 +99,10 @@ public class WebRtcCallControls extends LinearLayout {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isVideoMuted() {
 | 
			
		||||
    return !videoMuteButton.isChecked();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void setAudioButtonListener(final AudioButtonListener listener) {
 | 
			
		||||
    audioButton.setListener(listener);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								src/org/thoughtcrime/securesms/events/WebRtcViewModel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/org/thoughtcrime/securesms/events/WebRtcViewModel.java
									
									
									
									
									
										Normal 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 + "]";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user