remember last rtp capability

This commit is contained in:
Daniel Gultsch 2021-01-21 16:47:30 +01:00
parent e087b594ff
commit e711b3d294
6 changed files with 75 additions and 17 deletions

View file

@ -18,6 +18,7 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; 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.JidHelper;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element; 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.pep.Avatar;
import eu.siacs.conversations.xmpp.Jid; 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_PRESENCE = "last_presence";
public static final String LAST_TIME = "last_time"; public static final String LAST_TIME = "last_time";
public static final String GROUPS = "groups"; public static final String GROUPS = "groups";
public static final String RTP_CAPABILITY = "rtpCapability";
private String accountUuid; private String accountUuid;
private String systemName; private String systemName;
private String serverName; private String serverName;
@ -64,11 +67,12 @@ public class Contact implements ListItem, Blockable {
private boolean mActive = false; private boolean mActive = false;
private long mLastseen = 0; private long mLastseen = 0;
private String mLastPresence = null; private String mLastPresence = null;
private RtpCapability.Capability rtpCapability;
public Contact(final String account, final String systemName, final String serverName, final String presenceName, public Contact(final String account, final String systemName, final String serverName, final String presenceName,
final Jid jid, final int subscription, final String photoUri, final Jid jid, final int subscription, final String photoUri,
final Uri systemAccount, final String keys, final String avatar, final long lastseen, 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.accountUuid = account;
this.systemName = systemName; this.systemName = systemName;
this.serverName = serverName; this.serverName = serverName;
@ -96,6 +100,7 @@ public class Contact implements ListItem, Blockable {
} }
this.mLastseen = lastseen; this.mLastseen = lastseen;
this.mLastPresence = presence; this.mLastPresence = presence;
this.rtpCapability = rtpCapability;
} }
public Contact(final Jid jid) { public Contact(final Jid jid) {
@ -129,7 +134,8 @@ public class Contact implements ListItem, Blockable {
cursor.getString(cursor.getColumnIndex(AVATAR)), cursor.getString(cursor.getColumnIndex(AVATAR)),
cursor.getLong(cursor.getColumnIndex(LAST_TIME)), cursor.getLong(cursor.getColumnIndex(LAST_TIME)),
cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)), 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() { public String getDisplayName() {
@ -234,6 +240,7 @@ public class Contact implements ListItem, Blockable {
values.put(LAST_PRESENCE, mLastPresence); values.put(LAST_PRESENCE, mLastPresence);
values.put(LAST_TIME, mLastseen); values.put(LAST_TIME, mLastseen);
values.put(GROUPS, groups.toString()); values.put(GROUPS, groups.toString());
values.put(RTP_CAPABILITY, rtpCapability == null ? null : rtpCapability.toString());
return values; return values;
} }
} }
@ -573,7 +580,18 @@ public class Contact implements ListItem, Blockable {
return (avatar != null && avatar.getFilename() != null) || presenceName != null; 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 TO = 0;
public static final int FROM = 1; public static final int FROM = 1;
public static final int ASKING = 2; public static final int ASKING = 2;

View file

@ -7,7 +7,7 @@ import java.util.Locale;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
public class Presence implements Comparable { public class Presence implements Comparable<Presence> {
public enum Status { public enum Status {
CHAT, ONLINE, AWAY, XA, DND, OFFLINE; 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); 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); return this.status.compareTo(((Presence)other).status);
} }

View file

@ -136,6 +136,9 @@ public class Presences {
public boolean anySupport(final String namespace) { public boolean anySupport(final String namespace) {
synchronized (this.presences) { synchronized (this.presences) {
if (this.presences.size() == 0) {
return true;
}
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)) {

View file

@ -63,9 +63,9 @@ import eu.siacs.conversations.xmpp.Jid;
public class DatabaseBackend extends SQLiteOpenHelper { public class DatabaseBackend extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "history"; 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 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.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
+ Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT," + Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT,"
+ Contact.PRESENCE_NAME + " TEXT," + Contact.PRESENCE_NAME + " TEXT,"
@ -73,12 +73,13 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER," + Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER,"
+ Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, " + Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, "
+ Contact.LAST_PRESENCE + " TEXT, " + Contact.LAST_TIME + " NUMBER, " + Contact.LAST_PRESENCE + " TEXT, " + Contact.LAST_TIME + " NUMBER, "
+ Contact.RTP_CAPABILITY + " TEXT,"
+ Contact.GROUPS + " TEXT, FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES " + Contact.GROUPS + " TEXT, FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ Account.TABLENAME + "(" + Account.UUID + Account.TABLENAME + "(" + Account.UUID
+ ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", " + ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", "
+ Contact.JID + ") ON CONFLICT REPLACE);"; + 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.TABLENAME + "("
+ ServiceDiscoveryResult.HASH + " TEXT, " + ServiceDiscoveryResult.HASH + " TEXT, "
+ ServiceDiscoveryResult.VER + " TEXT, " + ServiceDiscoveryResult.VER + " TEXT, "
@ -86,7 +87,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ "UNIQUE(" + ServiceDiscoveryResult.HASH + ", " + "UNIQUE(" + ServiceDiscoveryResult.HASH + ", "
+ ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);"; + 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.TABELNAME + "("
+ PresenceTemplate.UUID + " TEXT, " + PresenceTemplate.UUID + " TEXT, "
+ PresenceTemplate.LAST_USED + " NUMBER," + PresenceTemplate.LAST_USED + " NUMBER,"
@ -94,7 +95,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ PresenceTemplate.STATUS + " TEXT," + PresenceTemplate.STATUS + " TEXT,"
+ "UNIQUE(" + PresenceTemplate.MESSAGE + "," + PresenceTemplate.STATUS + ") ON CONFLICT REPLACE);"; + "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.PREKEY_TABLENAME + "("
+ SQLiteAxolotlStore.ACCOUNT + " TEXT, " + SQLiteAxolotlStore.ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore.ID + " INTEGER, " + SQLiteAxolotlStore.ID + " INTEGER, "
@ -559,6 +560,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
if (oldVersion < 47 && newVersion >= 47) { if (oldVersion < 47 && newVersion >= 47) {
db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " + Contact.PRESENCE_NAME + " TEXT"); 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) { private void canonicalizeJids(SQLiteDatabase db) {

View file

@ -358,10 +358,10 @@ public class XmppConnectionService extends Service {
syncDirtyContacts(account); syncDirtyContacts(account);
} }
}; };
private AtomicLong mLastExpiryRun = new AtomicLong(0); private final AtomicLong mLastExpiryRun = new AtomicLong(0);
private SecureRandom mRandom; private SecureRandom mRandom;
private LruCache<Pair<String, String>, ServiceDiscoveryResult> discoCache = new LruCache<>(20); private final LruCache<Pair<String, String>, ServiceDiscoveryResult> discoCache = new LruCache<>(20);
private OnStatusChanged statusListener = new OnStatusChanged() { private final OnStatusChanged statusListener = new OnStatusChanged() {
@Override @Override
public void onStatusChanged(final Account account) { public void onStatusChanged(final Account account) {
@ -4552,6 +4552,10 @@ public class XmppConnectionService extends Service {
final ServiceDiscoveryResult disco = getCachedServiceDiscoveryResult(key); final ServiceDiscoveryResult disco = getCachedServiceDiscoveryResult(key);
if (disco != null) { if (disco != null) {
presence.setServiceDiscoveryResult(disco); presence.setServiceDiscoveryResult(disco);
final Contact contact = account.getRoster().getContact(jid);
if (contact.refreshRtpCapability()) {
syncRoster(account);
}
} else { } else {
if (account.inProgressDiscoFetches.contains(key)) { if (account.inProgressDiscoFetches.contains(key)) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": skipping duplicate disco request for " + key.second + " to " + jid); 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) { private void injectServiceDiscoveryResult(Roster roster, String hash, String ver, ServiceDiscoveryResult disco) {
boolean rosterNeedsSync = false;
for (final Contact contact : roster.getContacts()) { for (final Contact contact : roster.getContacts()) {
boolean serviceDiscoverySet = false;
for (final Presence presence : contact.getPresences().getPresences()) { for (final Presence presence : contact.getPresences().getPresences()) {
if (hash.equals(presence.getHash()) && ver.equals(presence.getVer())) { if (hash.equals(presence.getHash()) && ver.equals(presence.getVer())) {
presence.setServiceDiscoveryResult(disco); presence.setServiceDiscoveryResult(disco);
serviceDiscoverySet = true;
} }
} }
if (serviceDiscoverySet) {
rosterNeedsSync |= contact.refreshRtpCapability();
}
}
if (rosterNeedsSync) {
syncRoster(roster.getAccount());
} }
} }

View file

@ -1,5 +1,7 @@
package eu.siacs.conversations.xmpp.jingle; package eu.siacs.conversations.xmpp.jingle;
import com.google.common.base.Strings;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -20,7 +22,7 @@ public class RtpCapability {
Namespace.JINGLE_APPS_RTP, Namespace.JINGLE_APPS_RTP,
Namespace.JINGLE_APPS_DTLS Namespace.JINGLE_APPS_DTLS
); );
private static List<String> VIDEO_REQUIREMENTS = Arrays.asList( private static final List<String> VIDEO_REQUIREMENTS = Arrays.asList(
Namespace.JINGLE_FEATURE_AUDIO, Namespace.JINGLE_FEATURE_AUDIO,
Namespace.JINGLE_FEATURE_VIDEO Namespace.JINGLE_FEATURE_VIDEO
); );
@ -42,7 +44,7 @@ public class RtpCapability {
public static String[] filterPresences(final Contact contact, Capability required) { public static String[] filterPresences(final Contact contact, Capability required) {
final Presences presences = contact.getPresences(); final Presences presences = contact.getPresences();
final ArrayList<String> resources = new ArrayList<>(); final ArrayList<String> resources = new ArrayList<>();
for(final Map.Entry<String,Presence> presence : presences.getPresencesMap().entrySet()) { for (final Map.Entry<String, Presence> presence : presences.getPresencesMap().entrySet()) {
final Capability capability = check(presence.getValue()); final Capability capability = check(presence.getValue());
if (capability == Capability.NONE) { if (capability == Capability.NONE) {
continue; continue;
@ -55,9 +57,16 @@ public class RtpCapability {
} }
public static Capability check(final Contact contact) { 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(); final Presences presences = contact.getPresences();
if (presences.size() == 0 && allowFallback) {
return contact.getRtpCapability();
}
Capability result = Capability.NONE; Capability result = Capability.NONE;
for(Presence presence : presences.getPresences()) { for (final Presence presence : presences.getPresences()) {
Capability capability = check(presence); Capability capability = check(presence);
if (capability == Capability.VIDEO) { if (capability == Capability.VIDEO) {
result = capability; result = capability;
@ -69,7 +78,18 @@ public class RtpCapability {
} }
public enum Capability { 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;
}
}
} }
} }