summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Hibdon <mhibdon@google.com>2013-08-12 18:44:56 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2013-08-12 18:44:56 -0700
commitb2947f4702b6443661dd4b8ef635bef6eaddfa01 (patch)
tree8ecadf9f3b7bd8fd52e3859ba3a6ab6754f2a732
parentdf5332e1748e68943f7730aa9018bb038b3869f1 (diff)
parent66ac290b353302256e85d319c0ce623277dfdad3 (diff)
downloadandroid_packages_apps_Email-b2947f4702b6443661dd4b8ef635bef6eaddfa01.tar.gz
android_packages_apps_Email-b2947f4702b6443661dd4b8ef635bef6eaddfa01.tar.bz2
android_packages_apps_Email-b2947f4702b6443661dd4b8ef635bef6eaddfa01.zip
am 66ac290b: Fix a bug causing duplicate messages to be added
* commit '66ac290b353302256e85d319c0ce623277dfdad3': Fix a bug causing duplicate messages to be added
-rw-r--r--src/com/android/email/service/ImapService.java70
1 files changed, 42 insertions, 28 deletions
diff --git a/src/com/android/email/service/ImapService.java b/src/com/android/email/service/ImapService.java
index 4d0b6c349..2cd4383fc 100644
--- a/src/com/android/email/service/ImapService.java
+++ b/src/com/android/email/service/ImapService.java
@@ -68,6 +68,8 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
public class ImapService extends Service {
// TODO get these from configurations or settings.
@@ -195,11 +197,12 @@ public class ImapService extends Service {
private static final int COLUMN_FLAG_LOADED = 3;
private static final int COLUMN_SERVER_ID = 4;
private static final int COLUMN_FLAGS = 7;
+ private static final int COLUMN_TIMESTAMP = 8;
private static final String[] PROJECTION = new String[] {
EmailContent.RECORD_ID,
MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE, MessageColumns.FLAG_LOADED,
SyncColumns.SERVER_ID, MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
- MessageColumns.FLAGS
+ MessageColumns.FLAGS, MessageColumns.TIMESTAMP
};
final long mId;
@@ -208,6 +211,7 @@ public class ImapService extends Service {
final int mFlagLoaded;
final String mServerId;
final int mFlags;
+ final long mTimestamp;
public LocalMessageInfo(Cursor c) {
mId = c.getLong(COLUMN_ID);
@@ -216,6 +220,7 @@ public class ImapService extends Service {
mFlagLoaded = c.getInt(COLUMN_FLAG_LOADED);
mServerId = c.getString(COLUMN_SERVER_ID);
mFlags = c.getInt(COLUMN_FLAGS);
+ mTimestamp = c.getLong(COLUMN_TIMESTAMP);
// Note: mailbox key and account key not needed - they are projected for the SELECT
}
}
@@ -498,12 +503,20 @@ public class ImapService extends Service {
// 8. Get the all of the local messages within the sync window, and create
// an index of the uids.
- // It's important that we only get local messages that are inside our sync window.
- // In a later step, we will delete any messages that are in localMessageMap but
- // are not in our remote message list.
+ // The IMAP query for messages ignores time, and only looks at the date part of the endDate.
+ // So if we query for messages since Aug 11 at 3:00 PM, we can get messages from any time
+ // on Aug 11. Our IMAP query results can include messages up to 24 hours older than endDate,
+ // or up to 25 hours older at a daylight savings transition.
+ // It is important that we have the Id of any local message that could potentially be
+ // returned by the IMAP query, or we will create duplicate copies of the same messages.
+ // So we will increase our local query range by this much.
+ // Note that this complicates deletion: It's not okay to delete anything that is in the
+ // localMessageMap but not in the remote result, because we know that we may be getting
+ // Ids of local messages that are outside the IMAP query window.
Cursor localUidCursor = null;
HashMap<String, LocalMessageInfo> localMessageMap = new HashMap<String, LocalMessageInfo>();
try {
+ final long queryEndDate = endDate - DateUtils.DAY_IN_MILLIS - DateUtils.HOUR_IN_MILLIS;
localUidCursor = resolver.query(
EmailContent.Message.CONTENT_URI,
LocalMessageInfo.PROJECTION,
@@ -513,7 +526,7 @@ public class ImapService extends Service {
new String[] {
String.valueOf(account.mId),
String.valueOf(mailbox.mId),
- String.valueOf(endDate) },
+ String.valueOf(queryEndDate) },
null);
while (localUidCursor.moveToNext()) {
LocalMessageInfo info = new LocalMessageInfo(localUidCursor);
@@ -626,29 +639,30 @@ public class ImapService extends Service {
}
// 13. Remove messages that are in the local store and in the current sync window,
- // but no longer on the remote store.
- final HashSet<String> localUidsToDelete = new HashSet<String>(localMessageMap.keySet());
- localUidsToDelete.removeAll(remoteUidMap.keySet());
-
- for (String uidToDelete : localUidsToDelete) {
- LocalMessageInfo infoToDelete = localMessageMap.get(uidToDelete);
-
- // Delete associated data (attachment files)
- // Attachment & Body records are auto-deleted when we delete the Message record
- AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId, infoToDelete.mId);
-
- // Delete the message itself
- Uri uriToDelete = ContentUris.withAppendedId(
- EmailContent.Message.CONTENT_URI, infoToDelete.mId);
- resolver.delete(uriToDelete, null, null);
-
- // Delete extra rows (e.g. synced or deleted)
- Uri syncRowToDelete = ContentUris.withAppendedId(
- EmailContent.Message.UPDATED_CONTENT_URI, infoToDelete.mId);
- resolver.delete(syncRowToDelete, null, null);
- Uri deletERowToDelete = ContentUris.withAppendedId(
- EmailContent.Message.UPDATED_CONTENT_URI, infoToDelete.mId);
- resolver.delete(deletERowToDelete, null, null);
+ // but no longer on the remote store. Note that localMessageMap can contain messages
+ // that are not actually in our sync window. We need to check the timestamp to ensure
+ // that it is before deleting.
+ for (final LocalMessageInfo info : localMessageMap.values()) {
+ // If this message is inside our sync window, and we cannot find it in our list
+ // of remote messages, then we know it's been deleted from the server.
+ if (info.mTimestamp >= endDate && !remoteUidMap.containsKey(info.mServerId)) {
+ // Delete associated data (attachment files)
+ // Attachment & Body records are auto-deleted when we delete the Message record
+ AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId, info.mId);
+
+ // Delete the message itself
+ Uri uriToDelete = ContentUris.withAppendedId(
+ EmailContent.Message.CONTENT_URI, info.mId);
+ resolver.delete(uriToDelete, null, null);
+
+ // Delete extra rows (e.g. synced or deleted)
+ Uri syncRowToDelete = ContentUris.withAppendedId(
+ EmailContent.Message.UPDATED_CONTENT_URI, info.mId);
+ resolver.delete(syncRowToDelete, null, null);
+ Uri deletERowToDelete = ContentUris.withAppendedId(
+ EmailContent.Message.UPDATED_CONTENT_URI, info.mId);
+ resolver.delete(deletERowToDelete, null, null);
+ }
}
loadUnsyncedMessages(context, account, remoteFolder, unsyncedMessages, mailbox);