From 17ef530547de707b59d903225bcaaaa4f78654bc Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 31 Mar 2019 09:09:32 +0200 Subject: [PATCH] Cache lookup URIs --- .../java/eu/faircode/email/ContactInfo.java | 48 +++++++++++++++---- app/src/main/java/eu/faircode/email/Core.java | 11 +---- .../java/eu/faircode/email/DaoMessage.java | 8 ++++ .../java/eu/faircode/email/EntityRule.java | 2 +- .../eu/faircode/email/FragmentCompose.java | 4 +- .../eu/faircode/email/TupleMessageLookup.java | 9 ++++ .../java/eu/faircode/email/WorkerCleanup.java | 28 +++++++++++ 7 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/TupleMessageLookup.java diff --git a/app/src/main/java/eu/faircode/email/ContactInfo.java b/app/src/main/java/eu/faircode/email/ContactInfo.java index c48570fbab..6e40046c0e 100644 --- a/app/src/main/java/eu/faircode/email/ContactInfo.java +++ b/app/src/main/java/eu/faircode/email/ContactInfo.java @@ -27,9 +27,11 @@ public class ContactInfo { private Uri lookupUri; private long time; + private static Map emailLookupInfo = new HashMap<>(); private static Map emailContactInfo = new HashMap<>(); - private static final long CACHE_DURATION = 60 * 1000L; + private static final long CACHE_LOOKUP_DURATION = 120 * 60 * 1000L; + private static final long CACHE_CONTACT_DURATION = 60 * 1000L; private ContactInfo() { } @@ -60,10 +62,13 @@ public class ContactInfo { } private boolean isExpired() { - return (new Date().getTime() - time > CACHE_DURATION); + return (new Date().getTime() - time > CACHE_CONTACT_DURATION); } static void clearCache() { + synchronized (emailLookupInfo) { + emailLookupInfo.clear(); + } synchronized (emailContactInfo) { emailContactInfo.clear(); } @@ -146,13 +151,20 @@ public class ContactInfo { return info; } - static Uri getLookupUri(Context context, Address[] addresses) { + static Uri getLookupUri(Context context, Address[] addresses, boolean useCache) { + if (!Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) + return null; + if (addresses == null || addresses.length == 0) return null; InternetAddress address = (InternetAddress) addresses[0]; - if (!Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) - return null; + if (useCache) + synchronized (emailLookupInfo) { + LookupInfo info = emailLookupInfo.get(address.getAddress()); + if (info != null && !info.isExpired()) + return info.uri; + } try { ContentResolver resolver = context.getContentResolver(); @@ -166,19 +178,39 @@ public class ContactInfo { address.getAddress() }, null)) { + Uri uri = null; if (cursor != null && cursor.moveToNext()) { int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); long contactId = cursor.getLong(colContactId); String lookupKey = cursor.getString(colLookupKey); - return ContactsContract.Contacts.getLookupUri(contactId, lookupKey); - } else - return null; + + uri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); + } + + LookupInfo info = new LookupInfo(); + info.uri = uri; + info.time = new Date().getTime(); + + synchronized (emailLookupInfo) { + emailLookupInfo.put(address.getAddress(), info); + } + + return info.uri; } } catch (Throwable ex) { Log.e(ex); return null; } } + + private static class LookupInfo { + private Uri uri; + private long time; + + private boolean isExpired() { + return (new Date().getTime() - time > CACHE_LOOKUP_DURATION); + } + } } diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index c6bed8b349..8c2f003813 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -1169,7 +1169,7 @@ class Core { message.ui_browsed = browsed; message.sender = MessageHelper.getSortKey(message.from); - Uri lookupUri = ContactInfo.getLookupUri(context, message.from); + Uri lookupUri = ContactInfo.getLookupUri(context, message.from, true); message.avatar = (lookupUri == null ? null : lookupUri.toString()); Address sender = helper.getSender(); // header @@ -1263,13 +1263,6 @@ class Core { Log.i(folder.name + " updated id=" + message.id + " uid=" + message.uid + " unbrowse"); } - Uri lookupUri = ContactInfo.getLookupUri(context, message.from); - if ((message.avatar == null) != (lookupUri == null)) { - update = true; - message.avatar = (lookupUri == null ? null : lookupUri.toString()); - Log.i(folder.name + " updated id=" + message.id + " lookup=" + lookupUri); - } - if (update) try { db.beginTransaction(); @@ -1351,7 +1344,7 @@ class Core { for (Address recipient : recipients) { String email = ((InternetAddress) recipient).getAddress(); String name = ((InternetAddress) recipient).getPersonal(); - Uri avatar = ContactInfo.getLookupUri(context, new Address[]{recipient}); + Uri avatar = ContactInfo.getLookupUri(context, new Address[]{recipient}, true); EntityContact contact = db.contact().getContact(folder.account, type, email); if (contact == null) { contact = new EntityContact(); diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index 8dfe9c1cdf..d5757ee680 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -261,6 +261,11 @@ public interface DaoMessage { @Query("SELECT * FROM message WHERE NOT ui_snoozed IS NULL") List getSnoozed(); + @Query("SELECT id, `from`, avatar FROM message" + + " WHERE folder = :folder" + + " AND received >= :before") + List getAvatars(long folder, long before); + @Insert long insertMessage(EntityMessage message); @@ -303,6 +308,9 @@ public interface DaoMessage { @Query("UPDATE message SET sent = :sent WHERE id = :id") int setMessageSent(long id, Long sent); + @Query("UPDATE message SET avatar = :avatar WHERE id = :id") + int setMessageAvatar(long id, String avatar); + @Query("UPDATE message SET error = :error WHERE id = :id") int setMessageError(long id, String error); diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index 19d9562ce6..c3a5109f2e 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -260,7 +260,7 @@ public class EntityRule { reply.received = new Date().getTime(); reply.sender = MessageHelper.getSortKey(reply.from); - Uri lookupUri = ContactInfo.getLookupUri(context, reply.from); + Uri lookupUri = ContactInfo.getLookupUri(context, reply.from, true); reply.avatar = (lookupUri == null ? null : lookupUri.toString()); reply.id = db.message().insertMessage(reply); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index a61c214c6e..f04be63b80 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -1814,7 +1814,7 @@ public class FragmentCompose extends FragmentBase { } draft.sender = MessageHelper.getSortKey(draft.from); - Uri lookupUri = ContactInfo.getLookupUri(context, draft.from); + Uri lookupUri = ContactInfo.getLookupUri(context, draft.from, true); draft.avatar = (lookupUri == null ? null : lookupUri.toString()); draft.received = new Date().getTime(); @@ -2171,7 +2171,7 @@ public class FragmentCompose extends FragmentBase { draft.received = new Date().getTime(); draft.sender = MessageHelper.getSortKey(draft.from); - Uri lookupUri = ContactInfo.getLookupUri(context, draft.from); + Uri lookupUri = ContactInfo.getLookupUri(context, draft.from, true); draft.avatar = (lookupUri == null ? null : lookupUri.toString()); db.message().updateMessage(draft); diff --git a/app/src/main/java/eu/faircode/email/TupleMessageLookup.java b/app/src/main/java/eu/faircode/email/TupleMessageLookup.java new file mode 100644 index 0000000000..223c775838 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/TupleMessageLookup.java @@ -0,0 +1,9 @@ +package eu.faircode.email; + +import javax.mail.Address; + +public class TupleMessageLookup { + public long id; + public Address[] from; + public String avatar; +} diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java index bd33729b82..af9c40e4c0 100644 --- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java +++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java @@ -1,6 +1,7 @@ package eu.faircode.email; import android.content.Context; +import android.net.Uri; import android.os.Build; import java.io.File; @@ -9,6 +10,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; import androidx.annotation.NonNull; @@ -121,6 +123,32 @@ public class WorkerCleanup extends Worker { int logs = db.log().deleteLogs(now - KEEP_LOG_DURATION); Log.i("Deleted logs=" + logs); + Log.i("Update lookup URIs"); + List folders = db.folder().getSynchronizingFolders(); + for (EntityFolder folder : folders) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, -folder.sync_days); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + long sync_time = cal.getTimeInMillis(); + if (sync_time < 0) + sync_time = 0; + Log.i("Update lookup URIs " + folder.name + " before " + new Date(sync_time)); + + List avatars = db.message().getAvatars(folder.id, sync_time); + for (TupleMessageLookup message : avatars) { + Uri uri = (message.avatar == null ? null : Uri.parse(message.avatar)); + Uri lookup = ContactInfo.getLookupUri(context, message.from, false); + if (!Objects.equals(uri, lookup)) { + Log.i("Updating email=" + MessageHelper.formatAddresses(message.from) + " uri=" + lookup); + db.message().setMessageAvatar(message.id, lookup == null ? null : lookup.toString()); + } + } + } + Log.i("Updated lookup URIs"); + db.setTransactionSuccessful(); } catch (Throwable ex) { Log.e(ex);