make retract jingle messages work
This commit is contained in:
parent
e2f1cec2e5
commit
7909a72d43
|
@ -244,4 +244,13 @@ public class MessageGenerator extends AbstractGenerator {
|
|||
packet.addChild("request", "urn:xmpp:receipts");
|
||||
return packet;
|
||||
}
|
||||
|
||||
public MessagePacket sessionRetract(final JingleConnectionManager.RtpSessionProposal proposal) {
|
||||
final MessagePacket packet = new MessagePacket();
|
||||
packet.setTo(proposal.with);
|
||||
final Element propose = packet.addChild("retract", Namespace.JINGLE_MESSAGE);
|
||||
propose.setAttribute("id", proposal.sessionId);
|
||||
propose.addChild("description", Namespace.JINGLE_APPS_RTP);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ public class NotificationService {
|
|||
builder.addAction(new NotificationCompat.Action.Builder(
|
||||
R.drawable.ic_call_white_24dp,
|
||||
mXmppConnectionService.getString(R.string.answer_call),
|
||||
createPendingRtpSession(id, RtpSessionActivity.ACTION_ACCEPT, 103))
|
||||
createPendingRtpSession(id, RtpSessionActivity.ACTION_ACCEPT_CALL, 103))
|
||||
.build());
|
||||
final Notification notification = builder.build();
|
||||
notification.flags = notification.flags | Notification.FLAG_INSISTENT;
|
||||
|
|
|
@ -3977,9 +3977,9 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
public void notifyJingleRtpConnectionUpdate(final Account account, final Jid with, final RtpEndUserState state) {
|
||||
public void notifyJingleRtpConnectionUpdate(final Account account, final Jid with, final String sessionId, final RtpEndUserState state) {
|
||||
for(OnJingleRtpConnectionUpdate listener : threadSafeList(this.onJingleRtpConnectionUpdate)) {
|
||||
listener.onJingleRtpConnectionUpdate(account, with, state);
|
||||
listener.onJingleRtpConnectionUpdate(account, with, sessionId, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4661,7 +4661,7 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
|
||||
public interface OnJingleRtpConnectionUpdate {
|
||||
void onJingleRtpConnectionUpdate(final Account account, final Jid with, final RtpEndUserState state);
|
||||
void onJingleRtpConnectionUpdate(final Account account, final Jid with, final String sessionId, final RtpEndUserState state);
|
||||
}
|
||||
|
||||
public interface OnAccountUpdate {
|
||||
|
|
|
@ -1243,7 +1243,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
|
||||
private void triggerRtpSession() {
|
||||
final Contact contact = conversation.getContact();
|
||||
activity.xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(conversation.getAccount(), contact);
|
||||
final Intent intent = new Intent(activity, RtpSessionActivity.class);
|
||||
intent.setAction(RtpSessionActivity.ACTION_MAKE_VOICE_CALL);
|
||||
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, contact.getAccount().getJid().toEscapedString());
|
||||
intent.putExtra(RtpSessionActivity.EXTRA_WITH, contact.getJid().asBareJid().toEscapedString());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void handleAttachmentSelection(MenuItem item) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.view.View;
|
|||
import android.view.WindowManager;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
|
@ -20,12 +21,16 @@ import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
|||
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
|
||||
import rocks.xmpp.addr.Jid;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate {
|
||||
|
||||
public static final String EXTRA_WITH = "with";
|
||||
public static final String EXTRA_SESSION_ID = "session_id";
|
||||
|
||||
public static final String ACTION_ACCEPT = "accept";
|
||||
public static final String ACTION_ACCEPT_CALL = "action_accept_call";
|
||||
public static final String ACTION_MAKE_VOICE_CALL = "action_make_voice_call";
|
||||
public static final String ACTION_MAKE_VIDEO_CALL = "action_make_video_call";
|
||||
|
||||
private WeakReference<JingleRtpConnection> rtpConnectionReference;
|
||||
|
||||
|
@ -53,7 +58,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
}
|
||||
|
||||
private void endCall(View view) {
|
||||
requireRtpConnection().endCall();
|
||||
if (this.rtpConnectionReference == null) {
|
||||
final Intent intent = getIntent();
|
||||
final Account account = extractAccount(intent);
|
||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
||||
xmppConnectionService.getJingleConnectionManager().retractSessionProposal(account, with.asBareJid());
|
||||
finish();
|
||||
} else {
|
||||
requireRtpConnection().endCall();
|
||||
}
|
||||
}
|
||||
|
||||
private void rejectCall(View view) {
|
||||
|
@ -73,8 +86,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
@Override
|
||||
public void onNewIntent(final Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if (ACTION_ACCEPT.equals(intent.getAction())) {
|
||||
Log.d(Config.LOGTAG,"accepting through onNewIntent()");
|
||||
if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
|
||||
Log.d(Config.LOGTAG, "accepting through onNewIntent()");
|
||||
requireRtpConnection().acceptCall();
|
||||
}
|
||||
}
|
||||
|
@ -83,28 +96,50 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
void onBackendConnected() {
|
||||
final Intent intent = getIntent();
|
||||
final Account account = extractAccount(intent);
|
||||
final String with = intent.getStringExtra(EXTRA_WITH);
|
||||
final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
|
||||
final String sessionId = intent.getStringExtra(EXTRA_SESSION_ID);
|
||||
if (with != null && sessionId != null) {
|
||||
final WeakReference<JingleRtpConnection> reference = xmppConnectionService.getJingleConnectionManager()
|
||||
.findJingleRtpConnection(account, Jid.ofEscaped(with), sessionId);
|
||||
if (reference == null || reference.get() == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
this.rtpConnectionReference = reference;
|
||||
binding.with.setText(getWith().getDisplayName());
|
||||
final RtpEndUserState currentState = requireRtpConnection().getEndUserState();
|
||||
final String action = intent.getAction();
|
||||
updateStateDisplay(currentState);
|
||||
updateButtonConfiguration(currentState);
|
||||
if (ACTION_ACCEPT.equals(action)) {
|
||||
Log.d(Config.LOGTAG,"intent action was accept");
|
||||
if (sessionId != null) {
|
||||
initializeActivityWithRunningRapSession(account, with, sessionId);
|
||||
if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
|
||||
Log.d(Config.LOGTAG, "intent action was accept");
|
||||
requireRtpConnection().acceptCall();
|
||||
}
|
||||
} else if (asList(ACTION_MAKE_VIDEO_CALL, ACTION_MAKE_VOICE_CALL).contains(intent.getAction())) {
|
||||
xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with);
|
||||
binding.with.setText(account.getRoster().getContact(with).getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
|
||||
final WeakReference<JingleRtpConnection> reference = xmppConnectionService.getJingleConnectionManager()
|
||||
.findJingleRtpConnection(account, with, sessionId);
|
||||
if (reference == null || reference.get() == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
this.rtpConnectionReference = reference;
|
||||
final RtpEndUserState currentState = requireRtpConnection().getEndUserState();
|
||||
if (currentState == RtpEndUserState.ENDED) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
binding.with.setText(getWith().getDisplayName());
|
||||
updateStateDisplay(currentState);
|
||||
updateButtonConfiguration(currentState);
|
||||
}
|
||||
|
||||
private void reInitializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
|
||||
runOnUiThread(() -> {
|
||||
initializeActivityWithRunningRapSession(account, with, sessionId);
|
||||
});
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
|
||||
intent.putExtra(EXTRA_WITH, with.toEscapedString());
|
||||
intent.putExtra(EXTRA_SESSION_ID, sessionId);
|
||||
setIntent(intent);
|
||||
}
|
||||
|
||||
private void updateStateDisplay(final RtpEndUserState state) {
|
||||
switch (state) {
|
||||
case INCOMING_CALL:
|
||||
|
@ -122,6 +157,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
case ENDING_CALL:
|
||||
binding.status.setText(R.string.rtp_state_ending_call);
|
||||
break;
|
||||
case FINDING_DEVICE:
|
||||
binding.status.setText(R.string.rtp_state_finding_device);
|
||||
break;
|
||||
case RINGING:
|
||||
binding.status.setText(R.string.rtp_state_ringing);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,9 +196,19 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onJingleRtpConnectionUpdate(Account account, Jid with, RtpEndUserState state) {
|
||||
public void onJingleRtpConnectionUpdate(Account account, Jid with, final String sessionId, RtpEndUserState state) {
|
||||
Log.d(Config.LOGTAG,"onJingleRtpConnectionUpdate("+state+")");
|
||||
if (with.isBareJid()) {
|
||||
updateRtpSessionProposalState(with, state);
|
||||
return;
|
||||
}
|
||||
if (this.rtpConnectionReference == null) {
|
||||
//this happens when going from proposed session to actual session
|
||||
reInitializeActivityWithRunningRapSession(account, with, sessionId);
|
||||
return;
|
||||
}
|
||||
final AbstractJingleConnection.Id id = requireRtpConnection().getId();
|
||||
if (account == id.account && id.with.equals(with)) {
|
||||
if (account == id.account && id.with.equals(with) && id.sessionId.equals(sessionId)) {
|
||||
if (state == RtpEndUserState.ENDED) {
|
||||
finish();
|
||||
return;
|
||||
|
@ -170,6 +220,19 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
|||
} else {
|
||||
Log.d(Config.LOGTAG, "received update for other rtp session");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRtpSessionProposalState(Jid with, RtpEndUserState state) {
|
||||
final Intent intent = getIntent();
|
||||
final String intentExtraWith = intent == null ? null : intent.getStringExtra(EXTRA_WITH);
|
||||
if (intentExtraWith == null) {
|
||||
return;
|
||||
}
|
||||
if (Jid.ofEscaped(intentExtraWith).asBareJid().equals(with)) {
|
||||
runOnUiThread(() -> {
|
||||
updateStateDisplay(state);
|
||||
updateButtonConfiguration(state);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,12 +188,52 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void proposeJingleRtpSession(final Account account, final Contact contact) {
|
||||
final RtpSessionProposal proposal = RtpSessionProposal.of(account, contact.getJid().asBareJid());
|
||||
public void retractSessionProposal(final Account account, final Jid with) {
|
||||
synchronized (this.rtpSessionProposals) {
|
||||
RtpSessionProposal matchingProposal = null;
|
||||
for (RtpSessionProposal proposal : this.rtpSessionProposals.keySet()) {
|
||||
if (proposal.account == account && with.asBareJid().equals(proposal.with)) {
|
||||
matchingProposal = proposal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matchingProposal != null) {
|
||||
this.rtpSessionProposals.remove(matchingProposal);
|
||||
final MessagePacket messagePacket = mXmppConnectionService.getMessageGenerator().sessionRetract(matchingProposal);
|
||||
Log.d(Config.LOGTAG, messagePacket.toString());
|
||||
mXmppConnectionService.sendMessagePacket(account, messagePacket);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void proposeJingleRtpSession(final Account account, final Jid with) {
|
||||
synchronized (this.rtpSessionProposals) {
|
||||
for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) {
|
||||
RtpSessionProposal proposal = entry.getKey();
|
||||
if (proposal.account == account && with.asBareJid().equals(proposal.with)) {
|
||||
final DeviceDiscoveryState preexistingState = entry.getValue();
|
||||
if (preexistingState != null && preexistingState != DeviceDiscoveryState.FAILED) {
|
||||
mXmppConnectionService.notifyJingleRtpConnectionUpdate(
|
||||
account,
|
||||
with,
|
||||
proposal.sessionId,
|
||||
preexistingState.toEndUserState()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
final RtpSessionProposal proposal = RtpSessionProposal.of(account, with.asBareJid());
|
||||
this.rtpSessionProposals.put(proposal, DeviceDiscoveryState.SEARCHING);
|
||||
mXmppConnectionService.notifyJingleRtpConnectionUpdate(
|
||||
account,
|
||||
proposal.with,
|
||||
proposal.sessionId,
|
||||
RtpEndUserState.FINDING_DEVICE
|
||||
);
|
||||
final MessagePacket messagePacket = mXmppConnectionService.getMessageGenerator().sessionProposal(proposal);
|
||||
Log.d(Config.LOGTAG,messagePacket.toString());
|
||||
Log.d(Config.LOGTAG, messagePacket.toString());
|
||||
mXmppConnectionService.sendMessagePacket(account, messagePacket);
|
||||
}
|
||||
}
|
||||
|
@ -255,24 +295,25 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
|||
}
|
||||
|
||||
public void updateProposedSessionDiscovered(Account account, Jid from, String sessionId, final DeviceDiscoveryState target) {
|
||||
final RtpSessionProposal sessionProposal = new RtpSessionProposal(account,from.asBareJid(),sessionId);
|
||||
final RtpSessionProposal sessionProposal = new RtpSessionProposal(account, from.asBareJid(), sessionId);
|
||||
synchronized (this.rtpSessionProposals) {
|
||||
final DeviceDiscoveryState currentState = rtpSessionProposals.get(sessionProposal);
|
||||
if (currentState == null) {
|
||||
Log.d(Config.LOGTAG,"unable to find session proposal for session id "+sessionId);
|
||||
Log.d(Config.LOGTAG, "unable to find session proposal for session id " + sessionId);
|
||||
return;
|
||||
}
|
||||
if (currentState == DeviceDiscoveryState.DISCOVERED) {
|
||||
Log.d(Config.LOGTAG,"session proposal already at discovered. not going to fall back");
|
||||
Log.d(Config.LOGTAG, "session proposal already at discovered. not going to fall back");
|
||||
return;
|
||||
}
|
||||
this.rtpSessionProposals.put(sessionProposal, target);
|
||||
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": flagging session "+sessionId+" as "+target);
|
||||
mXmppConnectionService.notifyJingleRtpConnectionUpdate(account, sessionProposal.with, sessionProposal.sessionId, target.toEndUserState());
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": flagging session " + sessionId + " as " + target);
|
||||
}
|
||||
}
|
||||
|
||||
public void rejectRtpSession(final String sessionId) {
|
||||
for(final AbstractJingleConnection connection : this.connections.values()) {
|
||||
for (final AbstractJingleConnection connection : this.connections.values()) {
|
||||
if (connection.getId().sessionId.equals(sessionId)) {
|
||||
if (connection instanceof JingleRtpConnection) {
|
||||
((JingleRtpConnection) connection).rejectCall();
|
||||
|
@ -313,6 +354,17 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
|||
}
|
||||
|
||||
public enum DeviceDiscoveryState {
|
||||
SEARCHING, DISCOVERED, FAILED
|
||||
SEARCHING, DISCOVERED, FAILED;
|
||||
|
||||
public RtpEndUserState toEndUserState() {
|
||||
switch (this) {
|
||||
case SEARCHING:
|
||||
return RtpEndUserState.FINDING_DEVICE;
|
||||
case DISCOVERED:
|
||||
return RtpEndUserState.RINGING;
|
||||
default:
|
||||
return RtpEndUserState.CONNECTIVITY_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -17,7 +16,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.ui.RtpSessionActivity;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
|
||||
|
@ -34,7 +32,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
|||
static {
|
||||
final ImmutableMap.Builder<State, Collection<State>> transitionBuilder = new ImmutableMap.Builder<>();
|
||||
transitionBuilder.put(State.NULL, ImmutableList.of(State.PROPOSED, State.SESSION_INITIALIZED));
|
||||
transitionBuilder.put(State.PROPOSED, ImmutableList.of(State.ACCEPTED, State.PROCEED, State.REJECTED));
|
||||
transitionBuilder.put(State.PROPOSED, ImmutableList.of(State.ACCEPTED, State.PROCEED, State.REJECTED, State.RETRACTED));
|
||||
transitionBuilder.put(State.PROCEED, ImmutableList.of(State.SESSION_INITIALIZED));
|
||||
transitionBuilder.put(State.SESSION_INITIALIZED, ImmutableList.of(State.SESSION_ACCEPTED));
|
||||
VALID_TRANSITIONS = transitionBuilder.build();
|
||||
|
@ -234,6 +232,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
|||
break;
|
||||
case "proceed":
|
||||
receiveProceed(from, message);
|
||||
break;
|
||||
case "retract":
|
||||
receiveRetract(from, message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -272,6 +274,21 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
|||
}
|
||||
}
|
||||
|
||||
private void receiveRetract(final Jid from, final Element retract) {
|
||||
if (from.equals(id.with)) {
|
||||
if (transition(State.RETRACTED)) {
|
||||
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": session with " + id.with + " has been retracted");
|
||||
//TODO create missed call notification/message
|
||||
jingleConnectionManager.finishConnection(this);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "ignoring retract because already in " + this.state);
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received retract from " + from + ". expected retract from" + id.with + ". ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSessionInitiate() {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": prepare session-initiate");
|
||||
setupWebRTC();
|
||||
|
@ -472,6 +489,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
|||
}
|
||||
|
||||
private void updateEndUserState() {
|
||||
xmppConnectionService.notifyJingleRtpConnectionUpdate(id.account, id.with, getEndUserState());
|
||||
xmppConnectionService.notifyJingleRtpConnectionUpdate(id.account, id.with, id.sessionId, getEndUserState());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -894,6 +894,8 @@
|
|||
<string name="rtp_state_ending_call">Ending call</string>
|
||||
<string name="answer_call">Answer</string>
|
||||
<string name="dismiss_call">Dismiss</string>
|
||||
<string name="rtp_state_finding_device">Locating devices</string>
|
||||
<string name="rtp_state_ringing">Ringing</string>
|
||||
<plurals name="view_users">
|
||||
<item quantity="one">View %1$d Participant</item>
|
||||
<item quantity="other">View %1$d Participants</item>
|
||||
|
|
Loading…
Reference in a new issue