ask for resource and use jingle direct init when JMI is not available. fixes #3751
This commit is contained in:
		
							parent
							
								
									8edfc61346
								
							
						
					
					
						commit
						637c208f55
					
				@ -11,12 +11,34 @@ import java.util.Map;
 | 
				
			|||||||
public class Presences {
 | 
					public class Presences {
 | 
				
			||||||
    private final Hashtable<String, Presence> presences = new Hashtable<>();
 | 
					    private final Hashtable<String, Presence> presences = new Hashtable<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static String nameWithoutVersion(String name) {
 | 
				
			||||||
 | 
					        String[] parts = name.split(" ");
 | 
				
			||||||
 | 
					        if (parts.length > 1 && Character.isDigit(parts[parts.length - 1].charAt(0))) {
 | 
				
			||||||
 | 
					            StringBuilder output = new StringBuilder();
 | 
				
			||||||
 | 
					            for (int i = 0; i < parts.length - 1; ++i) {
 | 
				
			||||||
 | 
					                if (output.length() != 0) {
 | 
				
			||||||
 | 
					                    output.append(' ');
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                output.append(parts[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return output.toString();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return name;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<Presence> getPresences() {
 | 
					    public List<Presence> getPresences() {
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
            return new ArrayList<>(this.presences.values());
 | 
					            return new ArrayList<>(this.presences.values());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Map<String, Presence> getPresencesMap() {
 | 
				
			||||||
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
 | 
					            return new HashMap<>(this.presences);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Presence get(String resource) {
 | 
					    public Presence get(String resource) {
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
            return this.presences.get(resource);
 | 
					            return this.presences.get(resource);
 | 
				
			||||||
@ -44,10 +66,10 @@ public class Presences {
 | 
				
			|||||||
    public Presence.Status getShownStatus() {
 | 
					    public Presence.Status getShownStatus() {
 | 
				
			||||||
        Presence.Status status = Presence.Status.OFFLINE;
 | 
					        Presence.Status status = Presence.Status.OFFLINE;
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
			for(Presence p : presences.values()) {
 | 
					            for (Presence p : presences.values()) {
 | 
				
			||||||
                if (p.getStatus() == Presence.Status.DND) {
 | 
					                if (p.getStatus() == Presence.Status.DND) {
 | 
				
			||||||
                    return p.getStatus();
 | 
					                    return p.getStatus();
 | 
				
			||||||
				} else if (p.getStatus().compareTo(status) < 0){
 | 
					                } else if (p.getStatus().compareTo(status) < 0) {
 | 
				
			||||||
                    status = p.getStatus();
 | 
					                    status = p.getStatus();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -72,7 +94,7 @@ public class Presences {
 | 
				
			|||||||
    public List<PresenceTemplate> asTemplates() {
 | 
					    public List<PresenceTemplate> asTemplates() {
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
            ArrayList<PresenceTemplate> templates = new ArrayList<>(presences.size());
 | 
					            ArrayList<PresenceTemplate> templates = new ArrayList<>(presences.size());
 | 
				
			||||||
			for(Presence p : presences.values()) {
 | 
					            for (Presence p : presences.values()) {
 | 
				
			||||||
                if (p.getMessage() != null && !p.getMessage().trim().isEmpty()) {
 | 
					                if (p.getMessage() != null && !p.getMessage().trim().isEmpty()) {
 | 
				
			||||||
                    templates.add(new PresenceTemplate(p.getStatus(), p.getMessage()));
 | 
					                    templates.add(new PresenceTemplate(p.getStatus(), p.getMessage()));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -90,7 +112,7 @@ public class Presences {
 | 
				
			|||||||
    public List<String> getStatusMessages() {
 | 
					    public List<String> getStatusMessages() {
 | 
				
			||||||
        ArrayList<String> messages = new ArrayList<>();
 | 
					        ArrayList<String> messages = new ArrayList<>();
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
			for(Presence presence : this.presences.values()) {
 | 
					            for (Presence presence : this.presences.values()) {
 | 
				
			||||||
                String message = presence.getMessage() == null ? null : presence.getMessage().trim();
 | 
					                String message = presence.getMessage() == null ? null : presence.getMessage().trim();
 | 
				
			||||||
                if (message != null && !message.isEmpty() && !messages.contains(message)) {
 | 
					                if (message != null && !message.isEmpty() && !messages.contains(message)) {
 | 
				
			||||||
                    messages.add(message);
 | 
					                    messages.add(message);
 | 
				
			||||||
@ -102,7 +124,7 @@ public class Presences {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public boolean allOrNonSupport(String namespace) {
 | 
					    public boolean allOrNonSupport(String namespace) {
 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
			for(Presence presence : this.presences.values()) {
 | 
					            for (Presence presence : this.presences.values()) {
 | 
				
			||||||
                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
 | 
					                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
 | 
				
			||||||
                if (disco == null || !disco.getFeatures().contains(namespace)) {
 | 
					                if (disco == null || !disco.getFeatures().contains(namespace)) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
@ -112,11 +134,23 @@ public class Presences {
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public Pair<Map<String, String>,Map<String,String>> toTypeAndNameMap() {
 | 
					    public boolean anySupport(final String namespace) {
 | 
				
			||||||
		Map<String,String> typeMap = new HashMap<>();
 | 
					 | 
				
			||||||
		Map<String,String> nameMap = new HashMap<>();
 | 
					 | 
				
			||||||
        synchronized (this.presences) {
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
			for(Map.Entry<String,Presence> presenceEntry : this.presences.entrySet()) {
 | 
					            for (Presence presence : this.presences.values()) {
 | 
				
			||||||
 | 
					                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
 | 
				
			||||||
 | 
					                if (disco != null && disco.getFeatures().contains(namespace)) {
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Pair<Map<String, String>, Map<String, String>> toTypeAndNameMap() {
 | 
				
			||||||
 | 
					        Map<String, String> typeMap = new HashMap<>();
 | 
				
			||||||
 | 
					        Map<String, String> nameMap = new HashMap<>();
 | 
				
			||||||
 | 
					        synchronized (this.presences) {
 | 
				
			||||||
 | 
					            for (Map.Entry<String, Presence> presenceEntry : this.presences.entrySet()) {
 | 
				
			||||||
                String resource = presenceEntry.getKey();
 | 
					                String resource = presenceEntry.getKey();
 | 
				
			||||||
                Presence presence = presenceEntry.getValue();
 | 
					                Presence presence = presenceEntry.getValue();
 | 
				
			||||||
                ServiceDiscoveryResult serviceDiscoveryResult = presence == null ? null : presence.getServiceDiscoveryResult();
 | 
					                ServiceDiscoveryResult serviceDiscoveryResult = presence == null ? null : presence.getServiceDiscoveryResult();
 | 
				
			||||||
@ -125,7 +159,7 @@ public class Presences {
 | 
				
			|||||||
                    String type = identity.getType();
 | 
					                    String type = identity.getType();
 | 
				
			||||||
                    String name = identity.getName();
 | 
					                    String name = identity.getName();
 | 
				
			||||||
                    if (type != null) {
 | 
					                    if (type != null) {
 | 
				
			||||||
						typeMap.put(resource,type);
 | 
					                        typeMap.put(resource, type);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (name != null) {
 | 
					                    if (name != null) {
 | 
				
			||||||
                        nameMap.put(resource, nameWithoutVersion(name));
 | 
					                        nameMap.put(resource, nameWithoutVersion(name));
 | 
				
			||||||
@ -133,22 +167,6 @@ public class Presences {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
		return new Pair<>(typeMap,nameMap);
 | 
					        return new Pair<>(typeMap, nameMap);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private static String nameWithoutVersion(String name) {
 | 
					 | 
				
			||||||
		String[] parts = name.split(" ");
 | 
					 | 
				
			||||||
		if (parts.length > 1 && Character.isDigit(parts[parts.length -1].charAt(0))) {
 | 
					 | 
				
			||||||
			StringBuilder output = new StringBuilder();
 | 
					 | 
				
			||||||
			for(int i = 0; i < parts.length -1; ++i) {
 | 
					 | 
				
			||||||
				if (output.length() != 0) {
 | 
					 | 
				
			||||||
					output.append(' ');
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				output.append(parts[i]);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return output.toString();
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return name;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -116,6 +116,7 @@ import eu.siacs.conversations.utils.QuickLoader;
 | 
				
			|||||||
import eu.siacs.conversations.utils.StylingHelper;
 | 
					import eu.siacs.conversations.utils.StylingHelper;
 | 
				
			||||||
import eu.siacs.conversations.utils.TimeFrameUtils;
 | 
					import eu.siacs.conversations.utils.TimeFrameUtils;
 | 
				
			||||||
import eu.siacs.conversations.utils.UIHelper;
 | 
					import eu.siacs.conversations.utils.UIHelper;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xml.Namespace;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.XmppConnection;
 | 
					import eu.siacs.conversations.xmpp.XmppConnection;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
 | 
					import eu.siacs.conversations.xmpp.chatstate.ChatState;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 | 
					import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 | 
				
			||||||
@ -1342,11 +1343,28 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 | 
				
			|||||||
            Toast.makeText(getActivity(), R.string.only_one_call_at_a_time, Toast.LENGTH_LONG).show();
 | 
					            Toast.makeText(getActivity(), R.string.only_one_call_at_a_time, Toast.LENGTH_LONG).show();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Contact contact = conversation.getContact();
 | 
					        final Contact contact = conversation.getContact();
 | 
				
			||||||
 | 
					        if (contact.getPresences().anySupport(Namespace.JINGLE_MESSAGE)) {
 | 
				
			||||||
 | 
					            triggerRtpSession(contact.getAccount(),contact.getJid().asBareJid(),action);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            final RtpCapability.Capability capability;
 | 
				
			||||||
 | 
					            if (action.equals(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL)) {
 | 
				
			||||||
 | 
					                capability = RtpCapability.Capability.VIDEO;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                capability = RtpCapability.Capability.AUDIO;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            PresenceSelector.selectFullJidForDirectRtpConnection(activity, contact, capability, fullJid -> {
 | 
				
			||||||
 | 
					                triggerRtpSession(contact.getAccount(), fullJid, action);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void triggerRtpSession(final Account account, final Jid with, final String action) {
 | 
				
			||||||
        final Intent intent = new Intent(activity, RtpSessionActivity.class);
 | 
					        final Intent intent = new Intent(activity, RtpSessionActivity.class);
 | 
				
			||||||
        intent.setAction(action);
 | 
					        intent.setAction(action);
 | 
				
			||||||
        intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, contact.getAccount().getJid().toEscapedString());
 | 
					        intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
 | 
				
			||||||
        intent.putExtra(RtpSessionActivity.EXTRA_WITH, contact.getJid().asBareJid().toEscapedString());
 | 
					        intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
 | 
				
			||||||
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
					        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
				
			||||||
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
 | 
					        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
 | 
				
			||||||
        startActivity(intent);
 | 
					        startActivity(intent);
 | 
				
			||||||
 | 
				
			|||||||
@ -51,6 +51,7 @@ import eu.siacs.conversations.ui.util.AvatarWorkerTask;
 | 
				
			|||||||
import eu.siacs.conversations.ui.util.MainThreadExecutor;
 | 
					import eu.siacs.conversations.ui.util.MainThreadExecutor;
 | 
				
			||||||
import eu.siacs.conversations.utils.PermissionUtils;
 | 
					import eu.siacs.conversations.utils.PermissionUtils;
 | 
				
			||||||
import eu.siacs.conversations.utils.TimeFrameUtils;
 | 
					import eu.siacs.conversations.utils.TimeFrameUtils;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xml.Namespace;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 | 
					import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
 | 
					import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.Media;
 | 
					import eu.siacs.conversations.xmpp.jingle.Media;
 | 
				
			||||||
@ -306,7 +307,13 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
 | 
					    private void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
 | 
				
			||||||
        checkMicrophoneAvailability();
 | 
					        checkMicrophoneAvailability();
 | 
				
			||||||
 | 
					        if (with.isBareJid()) {
 | 
				
			||||||
            xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with, media);
 | 
					            xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with, media);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            final String sessionId = xmppConnectionService.getJingleConnectionManager().initializeRtpSession(account, with, media);
 | 
				
			||||||
 | 
					            initializeActivityWithRunningRtpSession(account, with, sessionId);
 | 
				
			||||||
 | 
					            resetIntent(account, with, sessionId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        putScreenInCallMode(media);
 | 
					        putScreenInCallMode(media);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -444,8 +451,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void reInitializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
 | 
					    private void reInitializeActivityWithRunningRtpSession(final Account account, Jid with, String sessionId) {
 | 
				
			||||||
        runOnUiThread(() -> initializeActivityWithRunningRtpSession(account, with, sessionId));
 | 
					        runOnUiThread(() -> initializeActivityWithRunningRtpSession(account, with, sessionId));
 | 
				
			||||||
 | 
					        resetIntent(account, with, sessionId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void resetIntent(final Account account, final Jid with, final String sessionId) {
 | 
				
			||||||
        final Intent intent = new Intent(Intent.ACTION_VIEW);
 | 
					        final Intent intent = new Intent(Intent.ACTION_VIEW);
 | 
				
			||||||
        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
 | 
					        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
 | 
				
			||||||
        intent.putExtra(EXTRA_WITH, with.toEscapedString());
 | 
					        intent.putExtra(EXTRA_WITH, with.toEscapedString());
 | 
				
			||||||
@ -838,7 +849,6 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void retry(View view) {
 | 
					    private void retry(View view) {
 | 
				
			||||||
        Log.d(Config.LOGTAG, "attempting retry");
 | 
					 | 
				
			||||||
        final Intent intent = getIntent();
 | 
					        final Intent intent = getIntent();
 | 
				
			||||||
        final Account account = extractAccount(intent);
 | 
					        final Account account = extractAccount(intent);
 | 
				
			||||||
        final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
 | 
					        final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
 | 
				
			||||||
@ -846,6 +856,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
        final String action = intent.getAction();
 | 
					        final String action = intent.getAction();
 | 
				
			||||||
        final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
 | 
					        final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
 | 
				
			||||||
        this.rtpConnectionReference = null;
 | 
					        this.rtpConnectionReference = null;
 | 
				
			||||||
 | 
					        Log.d(Config.LOGTAG, "attempting retry with " + with.toEscapedString());
 | 
				
			||||||
        proposeJingleRtpSession(account, with, media);
 | 
					        proposeJingleRtpSession(account, with, media);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -899,7 +910,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //this happens when going from proposed session to actual session
 | 
					            //this happens when going from proposed session to actual session
 | 
				
			||||||
            reInitializeActivityWithRunningRapSession(account, with, sessionId);
 | 
					            reInitializeActivityWithRunningRtpSession(account, with, sessionId);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        final AbstractJingleConnection.Id id = requireRtpConnection().getId();
 | 
					        final AbstractJingleConnection.Id id = requireRtpConnection().getId();
 | 
				
			||||||
@ -976,8 +987,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void resetIntent(final Account account, Jid with, final RtpEndUserState state, final Set<Media> media) {
 | 
					    private void resetIntent(final Account account, Jid with, final RtpEndUserState state, final Set<Media> media) {
 | 
				
			||||||
        final Intent intent = new Intent(Intent.ACTION_VIEW);
 | 
					        final Intent intent = new Intent(Intent.ACTION_VIEW);
 | 
				
			||||||
        intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString());
 | 
					 | 
				
			||||||
        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
 | 
					        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
 | 
				
			||||||
 | 
					        if (account.getRoster().getContact(with).getPresences().anySupport(Namespace.JINGLE_MESSAGE)) {
 | 
				
			||||||
 | 
					            intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString());
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            intent.putExtra(EXTRA_WITH, with.toEscapedString());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        intent.putExtra(EXTRA_LAST_REPORTED_STATE, state.toString());
 | 
					        intent.putExtra(EXTRA_LAST_REPORTED_STATE, state.toString());
 | 
				
			||||||
        intent.putExtra(EXTRA_LAST_ACTION, media.contains(Media.VIDEO) ? ACTION_MAKE_VIDEO_CALL : ACTION_MAKE_VOICE_CALL);
 | 
					        intent.putExtra(EXTRA_LAST_ACTION, media.contains(Media.VIDEO) ? ACTION_MAKE_VIDEO_CALL : ACTION_MAKE_VOICE_CALL);
 | 
				
			||||||
        setIntent(intent);
 | 
					        setIntent(intent);
 | 
				
			||||||
 | 
				
			|||||||
@ -44,15 +44,32 @@ import eu.siacs.conversations.entities.Conversation;
 | 
				
			|||||||
import eu.siacs.conversations.entities.Presences;
 | 
					import eu.siacs.conversations.entities.Presences;
 | 
				
			||||||
import eu.siacs.conversations.utils.CryptoHelper;
 | 
					import eu.siacs.conversations.utils.CryptoHelper;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.Jid;
 | 
					import eu.siacs.conversations.xmpp.Jid;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.RtpCapability;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class PresenceSelector {
 | 
					public class PresenceSelector {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void showPresenceSelectionDialog(Activity activity, final Conversation conversation, final OnPresenceSelected listener) {
 | 
					    public static void showPresenceSelectionDialog(Activity activity, final Conversation conversation, final OnPresenceSelected listener) {
 | 
				
			||||||
        final Contact contact = conversation.getContact();
 | 
					        final Contact contact = conversation.getContact();
 | 
				
			||||||
 | 
					        final String[] resourceArray = contact.getPresences().toResourceArray();
 | 
				
			||||||
 | 
					        showPresenceSelectionDialog(activity, contact, resourceArray, fullJid -> {
 | 
				
			||||||
 | 
					            conversation.setNextCounterpart(fullJid);
 | 
				
			||||||
 | 
					            listener.onPresenceSelected();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void selectFullJidForDirectRtpConnection(final Activity activity, final Contact contact, final RtpCapability.Capability required, final OnFullJidSelected onFullJidSelected) {
 | 
				
			||||||
 | 
					        final String[] resources = RtpCapability.filterPresences(contact, required);
 | 
				
			||||||
 | 
					        if (resources.length == 1) {
 | 
				
			||||||
 | 
					            onFullJidSelected.onFullJidSelected(contact.getJid().withResource(resources[0]));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            showPresenceSelectionDialog(activity, contact, resources, onFullJidSelected);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static void showPresenceSelectionDialog(final Activity activity, final Contact contact, final String[] resourceArray, final OnFullJidSelected onFullJidSelected) {
 | 
				
			||||||
        final Presences presences = contact.getPresences();
 | 
					        final Presences presences = contact.getPresences();
 | 
				
			||||||
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
 | 
					        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
 | 
				
			||||||
        builder.setTitle(activity.getString(R.string.choose_presence));
 | 
					        builder.setTitle(activity.getString(R.string.choose_presence));
 | 
				
			||||||
		final String[] resourceArray = presences.toResourceArray();
 | 
					 | 
				
			||||||
        Pair<Map<String, String>, Map<String, String>> typeAndName = presences.toTypeAndNameMap();
 | 
					        Pair<Map<String, String>, Map<String, String>> typeAndName = presences.toTypeAndNameMap();
 | 
				
			||||||
        final Map<String, String> resourceTypeMap = typeAndName.first;
 | 
					        final Map<String, String> resourceTypeMap = typeAndName.first;
 | 
				
			||||||
        final Map<String, String> resourceNameMap = typeAndName.second;
 | 
					        final Map<String, String> resourceNameMap = typeAndName.second;
 | 
				
			||||||
@ -86,15 +103,12 @@ public class PresenceSelector {
 | 
				
			|||||||
                selectedResource.get(),
 | 
					                selectedResource.get(),
 | 
				
			||||||
                (dialog, which) -> selectedResource.set(which));
 | 
					                (dialog, which) -> selectedResource.set(which));
 | 
				
			||||||
        builder.setNegativeButton(R.string.cancel, null);
 | 
					        builder.setNegativeButton(R.string.cancel, null);
 | 
				
			||||||
		builder.setPositiveButton(R.string.ok, (dialog, which) -> {
 | 
					        builder.setPositiveButton(
 | 
				
			||||||
			try {
 | 
					                R.string.ok,
 | 
				
			||||||
				Jid next = Jid.of(contact.getJid().getLocal(), contact.getJid().getDomain(), resourceArray[selectedResource.get()]);
 | 
					                (dialog, which) -> onFullJidSelected.onFullJidSelected(
 | 
				
			||||||
				conversation.setNextCounterpart(next);
 | 
					                        Jid.of(contact.getJid().getLocal(), contact.getJid().getDomain(), resourceArray[selectedResource.get()])
 | 
				
			||||||
			} catch (IllegalArgumentException e) {
 | 
					                )
 | 
				
			||||||
				conversation.setNextCounterpart(null);
 | 
					        );
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			listener.onPresenceSelected();
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
        builder.create().show();
 | 
					        builder.create().show();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -132,4 +146,8 @@ public class PresenceSelector {
 | 
				
			|||||||
    public interface OnPresenceSelected {
 | 
					    public interface OnPresenceSelected {
 | 
				
			||||||
        void onPresenceSelected();
 | 
					        void onPresenceSelected();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public interface OnFullJidSelected {
 | 
				
			||||||
 | 
					        void onFullJidSelected(Jid jid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -62,6 +62,10 @@ public abstract class AbstractJingleConnection {
 | 
				
			|||||||
            return new Id(account, with, sessionId);
 | 
					            return new Id(account, with, sessionId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static Id of(Account account, Jid with) {
 | 
				
			||||||
 | 
					            return new Id(account, with, JingleConnectionManager.nextRandomId());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static Id of(Message message) {
 | 
					        public static Id of(Message message) {
 | 
				
			||||||
            return new Id(
 | 
					            return new Id(
 | 
				
			||||||
                    message.getConversation().getAccount(),
 | 
					                    message.getConversation().getAccount(),
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ import com.google.common.cache.CacheBuilder;
 | 
				
			|||||||
import com.google.common.collect.Collections2;
 | 
					import com.google.common.collect.Collections2;
 | 
				
			||||||
import com.google.common.collect.ComparisonChain;
 | 
					import com.google.common.collect.ComparisonChain;
 | 
				
			||||||
import com.google.common.collect.ImmutableSet;
 | 
					import com.google.common.collect.ImmutableSet;
 | 
				
			||||||
 | 
					import com.google.j2objc.annotations.Weak;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.ref.WeakReference;
 | 
					import java.lang.ref.WeakReference;
 | 
				
			||||||
import java.security.SecureRandom;
 | 
					import java.security.SecureRandom;
 | 
				
			||||||
@ -523,6 +524,15 @@ public class JingleConnectionManager extends AbstractConnectionManager {
 | 
				
			|||||||
        mXmppConnectionService.sendMessagePacket(account, messagePacket);
 | 
					        mXmppConnectionService.sendMessagePacket(account, messagePacket);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String initializeRtpSession(final Account account, final Jid with, final Set<Media> media) {
 | 
				
			||||||
 | 
					        final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, with);
 | 
				
			||||||
 | 
					        final JingleRtpConnection rtpConnection = new JingleRtpConnection(this, id, account.getJid());
 | 
				
			||||||
 | 
					        rtpConnection.setProposedMedia(media);
 | 
				
			||||||
 | 
					        this.connections.put(id, rtpConnection);
 | 
				
			||||||
 | 
					        rtpConnection.sendSessionInitiate();
 | 
				
			||||||
 | 
					        return id.sessionId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
 | 
					    public void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
 | 
				
			||||||
        synchronized (this.rtpSessionProposals) {
 | 
					        synchronized (this.rtpSessionProposals) {
 | 
				
			||||||
            for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) {
 | 
					            for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) {
 | 
				
			||||||
 | 
				
			|||||||
@ -640,6 +640,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void sendSessionInitiate() {
 | 
				
			||||||
 | 
					        sendSessionInitiate(this.proposedMedia, State.SESSION_INITIALIZED);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void sendSessionInitiate(final Set<Media> media, final State targetState) {
 | 
					    private void sendSessionInitiate(final Set<Media> media, final State targetState) {
 | 
				
			||||||
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": prepare session-initiate");
 | 
					        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": prepare session-initiate");
 | 
				
			||||||
        discoverIceServers(iceServers -> sendSessionInitiate(media, targetState, iceServers));
 | 
					        discoverIceServers(iceServers -> sendSessionInitiate(media, targetState, iceServers));
 | 
				
			||||||
@ -781,6 +785,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public RtpEndUserState getEndUserState() {
 | 
					    public RtpEndUserState getEndUserState() {
 | 
				
			||||||
        switch (this.state) {
 | 
					        switch (this.state) {
 | 
				
			||||||
 | 
					            case NULL:
 | 
				
			||||||
            case PROPOSED:
 | 
					            case PROPOSED:
 | 
				
			||||||
            case SESSION_INITIALIZED:
 | 
					            case SESSION_INITIALIZED:
 | 
				
			||||||
                if (isInitiator()) {
 | 
					                if (isInitiator()) {
 | 
				
			||||||
@ -836,10 +841,19 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
 | 
				
			|||||||
    public Set<Media> getMedia() {
 | 
					    public Set<Media> getMedia() {
 | 
				
			||||||
        final State current = getState();
 | 
					        final State current = getState();
 | 
				
			||||||
        if (current == State.NULL) {
 | 
					        if (current == State.NULL) {
 | 
				
			||||||
 | 
					            if (isInitiator()) {
 | 
				
			||||||
 | 
					                return Preconditions.checkNotNull(
 | 
				
			||||||
 | 
					                        this.proposedMedia,
 | 
				
			||||||
 | 
					                        "RTP connection has not been initialized properly"
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            throw new IllegalStateException("RTP connection has not been initialized yet");
 | 
					            throw new IllegalStateException("RTP connection has not been initialized yet");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (Arrays.asList(State.PROPOSED, State.PROCEED).contains(current)) {
 | 
					        if (Arrays.asList(State.PROPOSED, State.PROCEED).contains(current)) {
 | 
				
			||||||
            return Preconditions.checkNotNull(this.proposedMedia, "RTP connection has not been initialized properly");
 | 
					            return Preconditions.checkNotNull(
 | 
				
			||||||
 | 
					                    this.proposedMedia,
 | 
				
			||||||
 | 
					                    "RTP connection has not been initialized properly"
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        final RtpContentMap initiatorContentMap = initiatorRtpContentMap;
 | 
					        final RtpContentMap initiatorContentMap = initiatorRtpContentMap;
 | 
				
			||||||
        if (initiatorContentMap != null) {
 | 
					        if (initiatorContentMap != null) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,10 @@
 | 
				
			|||||||
package eu.siacs.conversations.xmpp.jingle;
 | 
					package eu.siacs.conversations.xmpp.jingle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Arrays;
 | 
					import java.util.Arrays;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import eu.siacs.conversations.entities.Contact;
 | 
					import eu.siacs.conversations.entities.Contact;
 | 
				
			||||||
import eu.siacs.conversations.entities.Presence;
 | 
					import eu.siacs.conversations.entities.Presence;
 | 
				
			||||||
@ -37,6 +39,21 @@ public class RtpCapability {
 | 
				
			|||||||
        return Capability.NONE;
 | 
					        return Capability.NONE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String[] filterPresences(final Contact contact, Capability required) {
 | 
				
			||||||
 | 
					        final Presences presences = contact.getPresences();
 | 
				
			||||||
 | 
					        final ArrayList<String> resources = new ArrayList<>();
 | 
				
			||||||
 | 
					        for(final Map.Entry<String,Presence> presence : presences.getPresencesMap().entrySet()) {
 | 
				
			||||||
 | 
					            final Capability capability = check(presence.getValue());
 | 
				
			||||||
 | 
					            if (capability == Capability.NONE) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (required == Capability.AUDIO || capability == required) {
 | 
				
			||||||
 | 
					                resources.add(presence.getKey());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return resources.toArray(new String[0]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Capability check(final Contact contact) {
 | 
					    public static Capability check(final Contact contact) {
 | 
				
			||||||
        final Presences presences = contact.getPresences();
 | 
					        final Presences presences = contact.getPresences();
 | 
				
			||||||
        Capability result = Capability.NONE;
 | 
					        Capability result = Capability.NONE;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user