From e711b3d294ce28050b851bf45034121e7c6b5558 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 21 Jan 2021 16:47:30 +0100 Subject: [PATCH] remember last rtp capability --- .../siacs/conversations/entities/Contact.java | 24 ++++++++++++++-- .../conversations/entities/Presence.java | 4 +-- .../conversations/entities/Presences.java | 3 ++ .../persistance/DatabaseBackend.java | 14 ++++++---- .../services/XmppConnectionService.java | 19 +++++++++++-- .../xmpp/jingle/RtpCapability.java | 28 ++++++++++++++++--- 6 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 5ca5754599127cf127a084f69ba3d47210b4a439..7f169c5d541547b6a133337e5cfb36b625926204 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -18,6 +18,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Objects; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -27,6 +28,7 @@ import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.utils.JidHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jingle.RtpCapability; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.Jid; @@ -46,6 +48,7 @@ public class Contact implements ListItem, Blockable { public static final String LAST_PRESENCE = "last_presence"; public static final String LAST_TIME = "last_time"; public static final String GROUPS = "groups"; + public static final String RTP_CAPABILITY = "rtpCapability"; private String accountUuid; private String systemName; private String serverName; @@ -64,11 +67,12 @@ public class Contact implements ListItem, Blockable { private boolean mActive = false; private long mLastseen = 0; private String mLastPresence = null; + private RtpCapability.Capability rtpCapability; public Contact(final String account, final String systemName, final String serverName, final String presenceName, final Jid jid, final int subscription, final String photoUri, final Uri systemAccount, final String keys, final String avatar, final long lastseen, - final String presence, final String groups) { + final String presence, final String groups, final RtpCapability.Capability rtpCapability) { this.accountUuid = account; this.systemName = systemName; this.serverName = serverName; @@ -96,6 +100,7 @@ public class Contact implements ListItem, Blockable { } this.mLastseen = lastseen; this.mLastPresence = presence; + this.rtpCapability = rtpCapability; } public Contact(final Jid jid) { @@ -129,7 +134,8 @@ public class Contact implements ListItem, Blockable { cursor.getString(cursor.getColumnIndex(AVATAR)), cursor.getLong(cursor.getColumnIndex(LAST_TIME)), cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)), - cursor.getString(cursor.getColumnIndex(GROUPS))); + cursor.getString(cursor.getColumnIndex(GROUPS)), + RtpCapability.Capability.of(cursor.getString(cursor.getColumnIndex(RTP_CAPABILITY)))); } public String getDisplayName() { @@ -234,6 +240,7 @@ public class Contact implements ListItem, Blockable { values.put(LAST_PRESENCE, mLastPresence); values.put(LAST_TIME, mLastseen); values.put(GROUPS, groups.toString()); + values.put(RTP_CAPABILITY, rtpCapability == null ? null : rtpCapability.toString()); return values; } } @@ -573,7 +580,18 @@ public class Contact implements ListItem, Blockable { return (avatar != null && avatar.getFilename() != null) || presenceName != null; } - public final class Options { + public boolean refreshRtpCapability() { + final RtpCapability.Capability previous = this.rtpCapability; + this.rtpCapability = RtpCapability.check(this, false); + return !Objects.equals(previous, this.rtpCapability); + } + + public RtpCapability.Capability getRtpCapability() { + + return this.rtpCapability; + } + + public static final class Options { public static final int TO = 0; public static final int FROM = 1; public static final int ASKING = 2; diff --git a/src/main/java/eu/siacs/conversations/entities/Presence.java b/src/main/java/eu/siacs/conversations/entities/Presence.java index 741ec03e0bbef2349fbec7178516116a31c8d25c..9dce29d394774390a88320a15e2061ffad26ad05 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presence.java +++ b/src/main/java/eu/siacs/conversations/entities/Presence.java @@ -7,7 +7,7 @@ import java.util.Locale; import eu.siacs.conversations.xml.Element; -public class Presence implements Comparable { +public class Presence implements Comparable { public enum Status { CHAT, ONLINE, AWAY, XA, DND, OFFLINE; @@ -64,7 +64,7 @@ public class Presence implements Comparable { return new Presence(Status.fromShowString(show), ver, hash, node, message); } - public int compareTo(@NonNull Object other) { + public int compareTo(@NonNull Presence other) { return this.status.compareTo(((Presence)other).status); } diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index feca9883915c64cc4758755fd847a0e057caca9d..04d378cc2602e9fd47b1da60d9a9fdf3433114c6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -136,6 +136,9 @@ public class Presences { public boolean anySupport(final String namespace) { synchronized (this.presences) { + if (this.presences.size() == 0) { + return true; + } for (Presence presence : this.presences.values()) { ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult(); if (disco != null && disco.getFeatures().contains(namespace)) { diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 789b07c42b479d57b629b564566a3ff050f5cdad..4d11cfa1a0218649dd3ba83bc3a533929a056201 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -63,9 +63,9 @@ import eu.siacs.conversations.xmpp.Jid; public class DatabaseBackend extends SQLiteOpenHelper { private static final String DATABASE_NAME = "history"; - private static final int DATABASE_VERSION = 47; + private static final int DATABASE_VERSION = 48; private static DatabaseBackend instance = null; - private static String CREATE_CONTATCS_STATEMENT = "create table " + private static final String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " + Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT," + Contact.PRESENCE_NAME + " TEXT," @@ -73,12 +73,13 @@ public class DatabaseBackend extends SQLiteOpenHelper { + Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER," + Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, " + Contact.LAST_PRESENCE + " TEXT, " + Contact.LAST_TIME + " NUMBER, " + + Contact.RTP_CAPABILITY + " TEXT," + Contact.GROUPS + " TEXT, FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", " + Contact.JID + ") ON CONFLICT REPLACE);"; - private static String CREATE_DISCOVERY_RESULTS_STATEMENT = "create table " + private static final String CREATE_DISCOVERY_RESULTS_STATEMENT = "create table " + ServiceDiscoveryResult.TABLENAME + "(" + ServiceDiscoveryResult.HASH + " TEXT, " + ServiceDiscoveryResult.VER + " TEXT, " @@ -86,7 +87,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + "UNIQUE(" + ServiceDiscoveryResult.HASH + ", " + ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);"; - private static String CREATE_PRESENCE_TEMPLATES_STATEMENT = "CREATE TABLE " + private static final String CREATE_PRESENCE_TEMPLATES_STATEMENT = "CREATE TABLE " + PresenceTemplate.TABELNAME + "(" + PresenceTemplate.UUID + " TEXT, " + PresenceTemplate.LAST_USED + " NUMBER," @@ -94,7 +95,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + PresenceTemplate.STATUS + " TEXT," + "UNIQUE(" + PresenceTemplate.MESSAGE + "," + PresenceTemplate.STATUS + ") ON CONFLICT REPLACE);"; - private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE " + private static final String CREATE_PREKEYS_STATEMENT = "CREATE TABLE " + SQLiteAxolotlStore.PREKEY_TABLENAME + "(" + SQLiteAxolotlStore.ACCOUNT + " TEXT, " + SQLiteAxolotlStore.ID + " INTEGER, " @@ -559,6 +560,9 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (oldVersion < 47 && newVersion >= 47) { db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " + Contact.PRESENCE_NAME + " TEXT"); } + if (oldVersion < 48 && newVersion >= 48) { + db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " + Contact.RTP_CAPABILITY + " TEXT"); + } } private void canonicalizeJids(SQLiteDatabase db) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 6cce735ddbec552d9decd82a529a793de53f66f7..23e156f67bf6d1c118622f8be705e78c38bb7bad 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -358,10 +358,10 @@ public class XmppConnectionService extends Service { syncDirtyContacts(account); } }; - private AtomicLong mLastExpiryRun = new AtomicLong(0); + private final AtomicLong mLastExpiryRun = new AtomicLong(0); private SecureRandom mRandom; - private LruCache, ServiceDiscoveryResult> discoCache = new LruCache<>(20); - private OnStatusChanged statusListener = new OnStatusChanged() { + private final LruCache, ServiceDiscoveryResult> discoCache = new LruCache<>(20); + private final OnStatusChanged statusListener = new OnStatusChanged() { @Override public void onStatusChanged(final Account account) { @@ -4552,6 +4552,10 @@ public class XmppConnectionService extends Service { final ServiceDiscoveryResult disco = getCachedServiceDiscoveryResult(key); if (disco != null) { presence.setServiceDiscoveryResult(disco); + final Contact contact = account.getRoster().getContact(jid); + if (contact.refreshRtpCapability()) { + syncRoster(account); + } } else { if (account.inProgressDiscoFetches.contains(key)) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": skipping duplicate disco request for " + key.second + " to " + jid); @@ -4585,12 +4589,21 @@ public class XmppConnectionService extends Service { } private void injectServiceDiscoveryResult(Roster roster, String hash, String ver, ServiceDiscoveryResult disco) { + boolean rosterNeedsSync = false; for (final Contact contact : roster.getContacts()) { + boolean serviceDiscoverySet = false; for (final Presence presence : contact.getPresences().getPresences()) { if (hash.equals(presence.getHash()) && ver.equals(presence.getVer())) { presence.setServiceDiscoveryResult(disco); + serviceDiscoverySet = true; } } + if (serviceDiscoverySet) { + rosterNeedsSync |= contact.refreshRtpCapability(); + } + } + if (rosterNeedsSync) { + syncRoster(roster.getAccount()); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java index 7fad0459a2b3d377d59c7055594b0b66b0349503..fb7a604804215a4b6f2557efac33505a950eab38 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.xmpp.jingle; +import com.google.common.base.Strings; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -20,7 +22,7 @@ public class RtpCapability { Namespace.JINGLE_APPS_RTP, Namespace.JINGLE_APPS_DTLS ); - private static List VIDEO_REQUIREMENTS = Arrays.asList( + private static final List VIDEO_REQUIREMENTS = Arrays.asList( Namespace.JINGLE_FEATURE_AUDIO, Namespace.JINGLE_FEATURE_VIDEO ); @@ -42,7 +44,7 @@ public class RtpCapability { public static String[] filterPresences(final Contact contact, Capability required) { final Presences presences = contact.getPresences(); final ArrayList resources = new ArrayList<>(); - for(final Map.Entry presence : presences.getPresencesMap().entrySet()) { + for (final Map.Entry presence : presences.getPresencesMap().entrySet()) { final Capability capability = check(presence.getValue()); if (capability == Capability.NONE) { continue; @@ -55,9 +57,16 @@ public class RtpCapability { } public static Capability check(final Contact contact) { + return check(contact, true); + } + + public static Capability check(final Contact contact, final boolean allowFallback) { final Presences presences = contact.getPresences(); + if (presences.size() == 0 && allowFallback) { + return contact.getRtpCapability(); + } Capability result = Capability.NONE; - for(Presence presence : presences.getPresences()) { + for (final Presence presence : presences.getPresences()) { Capability capability = check(presence); if (capability == Capability.VIDEO) { result = capability; @@ -69,7 +78,18 @@ public class RtpCapability { } public enum Capability { - NONE, AUDIO, VIDEO + NONE, AUDIO, VIDEO; + + public static Capability of(String value) { + if (Strings.isNullOrEmpty(value)) { + return NONE; + } + try { + return valueOf(value); + } catch (IllegalArgumentException e) { + return NONE; + } + } } }