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 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
|
//Notification settings
|
||||||
|
|
|
@ -4,10 +4,12 @@ import android.Manifest;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -65,4 +67,13 @@ public class PhoneNumberContact extends AbstractPhoneContact {
|
||||||
}
|
}
|
||||||
return contacts;
|
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.crypto.sasl.Plain;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
|
import eu.siacs.conversations.entities.Entry;
|
||||||
import eu.siacs.conversations.utils.AccountUtils;
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||||
|
@ -286,7 +287,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PhoneNumberContact phoneNumberContact = findByUri(contacts, uri);
|
PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(contacts, uri);
|
||||||
final boolean needsCacheClean;
|
final boolean needsCacheClean;
|
||||||
if (phoneNumberContact != null) {
|
if (phoneNumberContact != null) {
|
||||||
needsCacheClean = contact.setPhoneContact(phoneNumberContact);
|
needsCacheClean = contact.setPhoneContact(phoneNumberContact);
|
||||||
|
@ -320,13 +321,17 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
}
|
}
|
||||||
IqPacket query = new IqPacket(IqPacket.TYPE.GET);
|
IqPacket query = new IqPacket(IqPacket.TYPE.GET);
|
||||||
query.setTo(syncServer);
|
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);
|
mLastSyncAttempt = Attempt.create(hash);
|
||||||
service.sendIqPacket(account, query, (a, response) -> {
|
service.sendIqPacket(account, query, (a, response) -> {
|
||||||
if (response.getType() == IqPacket.TYPE.RESULT) {
|
if (response.getType() == IqPacket.TYPE.RESULT) {
|
||||||
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
|
||||||
final Element phoneBook = response.findChild("phone-book", Namespace.SYNCHRONIZATION);
|
final Element phoneBook = response.findChild("phone-book", Namespace.SYNCHRONIZATION);
|
||||||
if (phoneBook != null) {
|
if (phoneBook != null) {
|
||||||
|
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
||||||
for(Entry entry : Entry.ofPhoneBook(phoneBook)) {
|
for(Entry entry : Entry.ofPhoneBook(phoneBook)) {
|
||||||
PhoneNumberContact phoneContact = contacts.get(entry.getNumber());
|
PhoneNumberContact phoneContact = contacts.get(entry.getNumber());
|
||||||
if (phoneContact == null) {
|
if (phoneContact == null) {
|
||||||
|
@ -341,13 +346,15 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
withSystemAccounts.remove(contact);
|
withSystemAccounts.remove(contact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (Contact contact : withSystemAccounts) {
|
for (Contact contact : withSystemAccounts) {
|
||||||
final boolean needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
|
final boolean needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
|
||||||
if (needsCacheClean) {
|
if (needsCacheClean) {
|
||||||
service.getAvatarService().clear(contact);
|
service.getAvatarService().clear(contact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": phone number contact list remains unchanged");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
service.syncRoster(account);
|
service.syncRoster(account);
|
||||||
service.updateRosterUi();
|
service.updateRosterUi();
|
||||||
|
@ -355,14 +362,6 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
return true;
|
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 static class Attempt {
|
||||||
private final long timestamp;
|
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 {
|
public interface OnVerificationRequested {
|
||||||
void onVerificationRequestFailed(int code);
|
void onVerificationRequestFailed(int code);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue