RtpSessionActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.content.Intent;
  4import android.databinding.DataBindingUtil;
  5import android.os.Bundle;
  6import android.util.Log;
  7import android.view.View;
  8import android.view.WindowManager;
  9
 10import java.lang.ref.WeakReference;
 11import java.util.Arrays;
 12
 13import eu.siacs.conversations.Config;
 14import eu.siacs.conversations.R;
 15import eu.siacs.conversations.databinding.ActivityRtpSessionBinding;
 16import eu.siacs.conversations.entities.Account;
 17import eu.siacs.conversations.entities.Contact;
 18import eu.siacs.conversations.services.XmppConnectionService;
 19import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 20import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
 21import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
 22import rocks.xmpp.addr.Jid;
 23
 24import static java.util.Arrays.asList;
 25
 26public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate {
 27
 28    public static final String EXTRA_WITH = "with";
 29    public static final String EXTRA_SESSION_ID = "session_id";
 30
 31    public static final String ACTION_ACCEPT_CALL = "action_accept_call";
 32    public static final String ACTION_MAKE_VOICE_CALL = "action_make_voice_call";
 33    public static final String ACTION_MAKE_VIDEO_CALL = "action_make_video_call";
 34
 35    private WeakReference<JingleRtpConnection> rtpConnectionReference;
 36
 37    private ActivityRtpSessionBinding binding;
 38
 39    @Override
 40    public void onCreate(Bundle savedInstanceState) {
 41        super.onCreate(savedInstanceState);
 42        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
 43                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
 44                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
 45                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
 46        ;
 47        Log.d(Config.LOGTAG, "RtpSessionActivity.onCreate()");
 48        this.binding = DataBindingUtil.setContentView(this, R.layout.activity_rtp_session);
 49        this.binding.rejectCall.setOnClickListener(this::rejectCall);
 50        this.binding.endCall.setOnClickListener(this::endCall);
 51        this.binding.acceptCall.setOnClickListener(this::acceptCall);
 52    }
 53
 54    @Override
 55    public void onStart() {
 56        super.onStart();
 57        Log.d(Config.LOGTAG, "RtpSessionActivity.onStart()");
 58    }
 59
 60    private void endCall(View view) {
 61        if (this.rtpConnectionReference == null) {
 62            final Intent intent = getIntent();
 63            final Account account = extractAccount(intent);
 64            final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
 65            xmppConnectionService.getJingleConnectionManager().retractSessionProposal(account, with.asBareJid());
 66            finish();
 67        } else {
 68            requireRtpConnection().endCall();
 69        }
 70    }
 71
 72    private void rejectCall(View view) {
 73        requireRtpConnection().rejectCall();
 74        finish();
 75    }
 76
 77    private void acceptCall(View view) {
 78        requireRtpConnection().acceptCall();
 79    }
 80
 81    @Override
 82    protected void refreshUiReal() {
 83
 84    }
 85
 86    @Override
 87    public void onNewIntent(final Intent intent) {
 88        super.onNewIntent(intent);
 89        if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
 90            Log.d(Config.LOGTAG, "accepting through onNewIntent()");
 91            requireRtpConnection().acceptCall();
 92        }
 93    }
 94
 95    @Override
 96    void onBackendConnected() {
 97        final Intent intent = getIntent();
 98        final Account account = extractAccount(intent);
 99        final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
100        final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
101        if (sessionId != null) {
102            initializeActivityWithRunningRapSession(account, with, sessionId);
103            if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
104                Log.d(Config.LOGTAG, "intent action was accept");
105                requireRtpConnection().acceptCall();
106            }
107        } else if (asList(ACTION_MAKE_VIDEO_CALL, ACTION_MAKE_VOICE_CALL).contains(intent.getAction())) {
108            xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with);
109            binding.with.setText(account.getRoster().getContact(with).getDisplayName());
110        }
111    }
112
113
114    private void initializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
115        final WeakReference<JingleRtpConnection> reference = xmppConnectionService.getJingleConnectionManager()
116                .findJingleRtpConnection(account, with, sessionId);
117        if (reference == null || reference.get() == null) {
118            finish();
119            return;
120        }
121        this.rtpConnectionReference = reference;
122        final RtpEndUserState currentState = requireRtpConnection().getEndUserState();
123        if (currentState == RtpEndUserState.ENDED) {
124            finish();
125            return;
126        }
127        binding.with.setText(getWith().getDisplayName());
128        updateStateDisplay(currentState);
129        updateButtonConfiguration(currentState);
130    }
131
132    private void reInitializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
133        runOnUiThread(() -> {
134            initializeActivityWithRunningRapSession(account, with, sessionId);
135        });
136        final Intent intent = new Intent(Intent.ACTION_VIEW);
137        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
138        intent.putExtra(EXTRA_WITH, with.toEscapedString());
139        intent.putExtra(EXTRA_SESSION_ID, sessionId);
140        setIntent(intent);
141    }
142
143    private void updateStateDisplay(final RtpEndUserState state) {
144        switch (state) {
145            case INCOMING_CALL:
146                binding.status.setText(R.string.rtp_state_incoming_call);
147                break;
148            case CONNECTING:
149                binding.status.setText(R.string.rtp_state_connecting);
150                break;
151            case CONNECTED:
152                binding.status.setText(R.string.rtp_state_connected);
153                break;
154            case ACCEPTING_CALL:
155                binding.status.setText(R.string.rtp_state_accepting_call);
156                break;
157            case ENDING_CALL:
158                binding.status.setText(R.string.rtp_state_ending_call);
159                break;
160            case FINDING_DEVICE:
161                binding.status.setText(R.string.rtp_state_finding_device);
162                break;
163            case RINGING:
164                binding.status.setText(R.string.rtp_state_ringing);
165        }
166    }
167
168    private void updateButtonConfiguration(final RtpEndUserState state) {
169        if (state == RtpEndUserState.INCOMING_CALL) {
170            this.binding.rejectCall.show();
171            this.binding.endCall.hide();
172            this.binding.acceptCall.show();
173        } else if (state == RtpEndUserState.ENDING_CALL) {
174            this.binding.rejectCall.hide();
175            this.binding.endCall.hide();
176            this.binding.acceptCall.hide();
177        } else {
178            this.binding.rejectCall.hide();
179            this.binding.endCall.show();
180            this.binding.acceptCall.hide();
181        }
182    }
183
184    private Contact getWith() {
185        final AbstractJingleConnection.Id id = requireRtpConnection().getId();
186        final Account account = id.account;
187        return account.getRoster().getContact(id.with);
188    }
189
190    private JingleRtpConnection requireRtpConnection() {
191        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
192        if (connection == null) {
193            throw new IllegalStateException("No RTP connection found");
194        }
195        return connection;
196    }
197
198    @Override
199    public void onJingleRtpConnectionUpdate(Account account, Jid with, final String sessionId, RtpEndUserState state) {
200        Log.d(Config.LOGTAG,"onJingleRtpConnectionUpdate("+state+")");
201        if (with.isBareJid()) {
202            updateRtpSessionProposalState(with, state);
203            return;
204        }
205        if (this.rtpConnectionReference == null) {
206            //this happens when going from proposed session to actual session
207            reInitializeActivityWithRunningRapSession(account, with, sessionId);
208            return;
209        }
210        final AbstractJingleConnection.Id id = requireRtpConnection().getId();
211        if (account == id.account && id.with.equals(with) && id.sessionId.equals(sessionId)) {
212            if (state == RtpEndUserState.ENDED) {
213                finish();
214                return;
215            }
216            runOnUiThread(() -> {
217                updateStateDisplay(state);
218                updateButtonConfiguration(state);
219            });
220        } else {
221            Log.d(Config.LOGTAG, "received update for other rtp session");
222        }
223    }
224
225    private void updateRtpSessionProposalState(Jid with, RtpEndUserState state) {
226        final Intent intent = getIntent();
227        final String intentExtraWith = intent == null ? null : intent.getStringExtra(EXTRA_WITH);
228        if (intentExtraWith == null) {
229            return;
230        }
231        if (Jid.ofEscaped(intentExtraWith).asBareJid().equals(with)) {
232            runOnUiThread(() -> {
233                updateStateDisplay(state);
234                updateButtonConfiguration(state);
235            });
236        }
237    }
238}