added hash for status quo to make sync reply more performant
This commit is contained in:
parent
1bcbd257c3
commit
a1a625bb2d
|
@ -48,7 +48,7 @@ public final class Config {
|
|||
|
||||
public static final boolean ALLOW_NON_TLS_CONNECTIONS = false; //very dangerous. you should have a good reason to set this to true
|
||||
|
||||
public static final long CONTACT_SYNC_RETRY_INTERVAL = 1000L * 60 * 5;
|
||||
public static final long CONTACT_SYNC_RETRY_INTERVAL = 1000L * 60 * 1;
|
||||
|
||||
|
||||
//Notification settings
|
||||
|
|
|
@ -4,10 +4,12 @@ import android.Manifest;
|
|||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.ContactsContract;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -65,4 +67,13 @@ public class PhoneNumberContact extends AbstractPhoneContact {
|
|||
}
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public static PhoneNumberContact findByUri(Collection<PhoneNumberContact> haystack, Uri needle) {
|
||||
for(PhoneNumberContact contact : haystack) {
|
||||
if (needle.equals(contact.getLookupUri())) {
|
||||
return contact;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package eu.siacs.conversations.entities;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.android.PhoneNumberContact;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import rocks.xmpp.addr.Jid;
|
||||
|
||||
public class Entry implements Comparable<Entry> {
|
||||
private final List<Jid> jids;
|
||||
private final String number;
|
||||
|
||||
private Entry(String number, List<Jid> jids) {
|
||||
this.number = number;
|
||||
this.jids = jids;
|
||||
}
|
||||
|
||||
public static Entry of(Element element) {
|
||||
final String number = element.getAttribute("number");
|
||||
final List<Jid> jids = new ArrayList<>();
|
||||
for (Element jidElement : element.getChildren()) {
|
||||
String content = jidElement.getContent();
|
||||
if (content != null) {
|
||||
jids.add(Jid.of(content));
|
||||
}
|
||||
}
|
||||
return new Entry(number, jids);
|
||||
}
|
||||
|
||||
public static List<Entry> ofPhoneBook(Element phoneBook) {
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
for (Element entry : phoneBook.getChildren()) {
|
||||
if ("entry".equals(entry.getName())) {
|
||||
entries.add(of(entry));
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
public static String statusQuo(final Collection<PhoneNumberContact> phoneNumberContacts, Collection<Contact> systemContacts) {
|
||||
return statusQuo(ofPhoneNumberContactsAndContacts(phoneNumberContacts, systemContacts));
|
||||
}
|
||||
|
||||
private static String statusQuo(final List<Entry> entries) {
|
||||
Collections.sort(entries);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(Entry entry : entries) {
|
||||
if (builder.length() != 0) {
|
||||
builder.append('\u001d');
|
||||
}
|
||||
builder.append(entry.getNumber());
|
||||
List<Jid> jids = entry.getJids();
|
||||
Collections.sort(jids);
|
||||
for(Jid jid : jids) {
|
||||
builder.append('\u001e');
|
||||
builder.append(jid.asBareJid().toEscapedString());
|
||||
}
|
||||
}
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return "";
|
||||
}
|
||||
Log.d(Config.LOGTAG,"status quo string: "+builder.toString());
|
||||
byte[] sha1 = md.digest(builder.toString().getBytes());
|
||||
return new String(Base64.encode(sha1, Base64.DEFAULT)).trim();
|
||||
}
|
||||
|
||||
private static List<Entry> ofPhoneNumberContactsAndContacts(final Collection<PhoneNumberContact> phoneNumberContacts, Collection<Contact> systemContacts) {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
for(Contact contact : systemContacts) {
|
||||
PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount());
|
||||
if (phoneNumberContact != null && phoneNumberContact.getPhoneNumber() != null) {
|
||||
Entry entry = findOrCreateByPhoneNumber(entries, phoneNumberContact.getPhoneNumber());
|
||||
entry.jids.add(contact.getJid().asBareJid());
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
private static Entry findOrCreateByPhoneNumber(final List<Entry> entries, String number) {
|
||||
for(Entry entry : entries) {
|
||||
if (entry.number.equals(number)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
Entry entry = new Entry(number, new ArrayList<>());
|
||||
entries.add(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public List<Jid> getJids() {
|
||||
return jids;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Entry o) {
|
||||
return number.compareTo(o.number);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import eu.siacs.conversations.android.PhoneNumberContact;
|
|||
import eu.siacs.conversations.crypto.sasl.Plain;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.Entry;
|
||||
import eu.siacs.conversations.utils.AccountUtils;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||
|
@ -286,7 +287,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
|||
if (uri == null) {
|
||||
continue;
|
||||
}
|
||||
PhoneNumberContact phoneNumberContact = findByUri(contacts, uri);
|
||||
PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(contacts, uri);
|
||||
final boolean needsCacheClean;
|
||||
if (phoneNumberContact != null) {
|
||||
needsCacheClean = contact.setPhoneContact(phoneNumberContact);
|
||||
|
@ -320,13 +321,17 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
|||
}
|
||||
IqPacket query = new IqPacket(IqPacket.TYPE.GET);
|
||||
query.setTo(syncServer);
|
||||
query.addChild(new Element("phone-book", Namespace.SYNCHRONIZATION).setChildren(entries));
|
||||
Element book = new Element("phone-book", Namespace.SYNCHRONIZATION).setChildren(entries);
|
||||
String statusQuo = Entry.statusQuo(contacts.values(), account.getRoster().getWithSystemAccounts(PhoneNumberContact.class));
|
||||
Log.d(Config.LOGTAG,"status quo="+statusQuo);
|
||||
book.setAttribute("ver",statusQuo);
|
||||
query.addChild(book);
|
||||
mLastSyncAttempt = Attempt.create(hash);
|
||||
service.sendIqPacket(account, query, (a, response) -> {
|
||||
if (response.getType() == IqPacket.TYPE.RESULT) {
|
||||
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
||||
final Element phoneBook = response.findChild("phone-book", Namespace.SYNCHRONIZATION);
|
||||
if (phoneBook != null) {
|
||||
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
||||
for(Entry entry : Entry.ofPhoneBook(phoneBook)) {
|
||||
PhoneNumberContact phoneContact = contacts.get(entry.getNumber());
|
||||
if (phoneContact == null) {
|
||||
|
@ -341,13 +346,15 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
|||
withSystemAccounts.remove(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Contact contact : withSystemAccounts) {
|
||||
final boolean needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
|
||||
if (needsCacheClean) {
|
||||
service.getAvatarService().clear(contact);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": phone number contact list remains unchanged");
|
||||
}
|
||||
}
|
||||
service.syncRoster(account);
|
||||
service.updateRosterUi();
|
||||
|
@ -355,14 +362,6 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
|||
return true;
|
||||
}
|
||||
|
||||
private static PhoneNumberContact findByUri(Collection<PhoneNumberContact> haystack, Uri needle) {
|
||||
for(PhoneNumberContact contact : haystack) {
|
||||
if (needle.equals(contact.getLookupUri())) {
|
||||
return contact;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class Attempt {
|
||||
private final long timestamp;
|
||||
|
@ -382,46 +381,6 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
|||
}
|
||||
}
|
||||
|
||||
public static class Entry {
|
||||
private final List<Jid> jids;
|
||||
private final String number;
|
||||
|
||||
private Entry(String number, List<Jid> jids) {
|
||||
this.number = number;
|
||||
this.jids = jids;
|
||||
}
|
||||
|
||||
public static Entry of(Element element) {
|
||||
final String number = element.getAttribute("number");
|
||||
final List<Jid> jids = new ArrayList<>();
|
||||
for (Element jidElement : element.getChildren()) {
|
||||
String content = jidElement.getContent();
|
||||
if (content != null) {
|
||||
jids.add(Jid.of(content));
|
||||
}
|
||||
}
|
||||
return new Entry(number, jids);
|
||||
}
|
||||
|
||||
public static List<Entry> ofPhoneBook(Element phoneBook) {
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
for (Element entry : phoneBook.getChildren()) {
|
||||
if ("entry".equals(entry.getName())) {
|
||||
entries.add(of(entry));
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
public List<Jid> getJids() {
|
||||
return jids;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnVerificationRequested {
|
||||
void onVerificationRequestFailed(int code);
|
||||
|
||||
|
|
Loading…
Reference in New Issue