summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Ping Hu <yph@google.com>2014-03-07 19:17:02 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-07 19:17:02 +0000
commitf382d4ffbde7e16eea4cc3aebca220e6cad81735 (patch)
treeb3e7ac8fa80fe99c43f1491c74ccc83ba4f7e768
parent2909f4d00bf188f0d0c76ff8e61a306f862193fd (diff)
parent52c9dfbbed3860d9b7dfc60fae466f620464151c (diff)
downloadExchange-f382d4ffbde7e16eea4cc3aebca220e6cad81735.tar.gz
Merge "Switch contacts sync to an EasSyncBase." into ub-mail-klp-mr2
-rw-r--r--src/com/android/exchange/adapter/ContactsSyncParser.java4
-rw-r--r--src/com/android/exchange/adapter/FolderSyncParser.java4
-rw-r--r--src/com/android/exchange/eas/EasSyncBase.java18
-rw-r--r--src/com/android/exchange/eas/EasSyncCollectionTypeBase.java49
-rw-r--r--src/com/android/exchange/eas/EasSyncContacts.java (renamed from src/com/android/exchange/service/EasContactsSyncHandler.java)127
-rw-r--r--src/com/android/exchange/eas/EasSyncMail.java7
-rw-r--r--src/com/android/exchange/service/EasMailboxSyncHandler.java196
-rw-r--r--src/com/android/exchange/service/EasSyncHandler.java10
-rw-r--r--src/com/android/exchange/service/EmailSyncAdapterService.java26
9 files changed, 147 insertions, 294 deletions
diff --git a/src/com/android/exchange/adapter/ContactsSyncParser.java b/src/com/android/exchange/adapter/ContactsSyncParser.java
index c5b6068e..3504bd94 100644
--- a/src/com/android/exchange/adapter/ContactsSyncParser.java
+++ b/src/com/android/exchange/adapter/ContactsSyncParser.java
@@ -40,7 +40,7 @@ import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
-import com.android.exchange.service.EasContactsSyncHandler;
+import com.android.exchange.eas.EasSyncContacts;
import com.android.exchange.service.EasSyncHandler;
import com.android.exchange.utility.CalendarUtilities;
import com.android.mail.utils.LogUtils;
@@ -1308,7 +1308,7 @@ public class ContactsSyncParser extends AbstractSyncParser {
@Override
protected void wipe() {
LogUtils.w(TAG, "Wiping contacts for account %d", mAccount.mId);
- EasContactsSyncHandler.wipeAccountFromContentProvider(mContext,
+ EasSyncContacts.wipeAccountFromContentProvider(mContext,
mAccount.mEmailAddress);
}
}
diff --git a/src/com/android/exchange/adapter/FolderSyncParser.java b/src/com/android/exchange/adapter/FolderSyncParser.java
index 4805cdc3..de06658c 100644
--- a/src/com/android/exchange/adapter/FolderSyncParser.java
+++ b/src/com/android/exchange/adapter/FolderSyncParser.java
@@ -40,8 +40,8 @@ import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.exchange.CommandStatusException;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.Eas;
+import com.android.exchange.eas.EasSyncContacts;
import com.android.exchange.service.EasCalendarSyncHandler;
-import com.android.exchange.service.EasContactsSyncHandler;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;
@@ -761,7 +761,7 @@ public class FolderSyncParser extends AbstractSyncParser {
protected void wipe() {
EasCalendarSyncHandler.wipeAccountFromContentProvider(mContext,
mAccount.mEmailAddress);
- EasContactsSyncHandler.wipeAccountFromContentProvider(mContext,
+ EasSyncContacts.wipeAccountFromContentProvider(mContext,
mAccount.mEmailAddress);
// Save away any mailbox sync information that is NOT default
diff --git a/src/com/android/exchange/eas/EasSyncBase.java b/src/com/android/exchange/eas/EasSyncBase.java
index ede73b5f..871000ed 100644
--- a/src/com/android/exchange/eas/EasSyncBase.java
+++ b/src/com/android/exchange/eas/EasSyncBase.java
@@ -1,8 +1,10 @@
package com.android.exchange.eas;
import android.content.Context;
+import android.net.TrafficStats;
import android.text.format.DateUtils;
+import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Mailbox;
@@ -70,6 +72,9 @@ public class EasSyncBase extends EasOperation {
if (mCollectionTypeHandler == null) {
return false;
}
+ // Set up traffic stats bookkeeping.
+ final int trafficFlags = TrafficFlags.getSyncFlags(mContext, mAccount);
+ TrafficStats.setThreadStatsTag(trafficFlags | mCollectionTypeHandler.getTrafficFlag());
}
return result;
}
@@ -121,6 +126,9 @@ public class EasSyncBase extends EasOperation {
final String key = getSyncKey();
while (result == RESULT_MORE_AVAILABLE) {
result = super.performOperation();
+ if (result == RESULT_MORE_AVAILABLE || result == RESULT_DONE) {
+ mCollectionTypeHandler.cleanup(mContext, mAccount);
+ }
// TODO: Clear pending request queue.
final String newKey = getSyncKey();
if (result == RESULT_MORE_AVAILABLE && key.equals(newKey)) {
@@ -155,16 +163,14 @@ public class EasSyncBase extends EasOperation {
case Mailbox.TYPE_INBOX:
case Mailbox.TYPE_DRAFTS:
case Mailbox.TYPE_SENT:
-// case Mailbox.TYPE_TRASH:
- case Mailbox.TYPE_JUNK: {
+ case Mailbox.TYPE_TRASH:
+ //case Mailbox.TYPE_JUNK:
return new EasSyncMail();
- }
case Mailbox.TYPE_CALENDAR:
- // TODO: fill this in when we have EasSyncContacts;
+ // TODO: fill this in when we have EasSyncCalendar;
return null;
case Mailbox.TYPE_CONTACTS:
- // TODO: fill this in when we have EasSyncContacts;
- return null;
+ return new EasSyncContacts(mAccount.mEmailAddress);
default:
LogUtils.e(LOG_TAG, "unexpected collectiontype %d", type);
return null;
diff --git a/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java b/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
index d8e578c0..555e5353 100644
--- a/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
+++ b/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
@@ -4,8 +4,10 @@ import android.content.Context;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
+import com.android.exchange.Eas;
import com.android.exchange.adapter.AbstractSyncParser;
import com.android.exchange.adapter.Serializer;
+import com.android.exchange.adapter.Tags;
import java.io.IOException;
import java.io.InputStream;
@@ -21,6 +23,13 @@ public abstract class EasSyncCollectionTypeBase {
public static final int MAX_WINDOW_SIZE = 512;
/**
+ * Get the flag for traffic bookkeeping for this sync type.
+ * @return The appropriate value from {@link com.android.emailcommon.TrafficFlags} for this
+ * sync.
+ */
+ public abstract int getTrafficFlag();
+
+ /**
* Write the contents of a Collection node in an EAS sync request appropriate for our mailbox.
* See http://msdn.microsoft.com/en-us/library/gg650891(v=exchg.80).aspx for documentation on
* the contents of this sync request element.
@@ -49,4 +58,44 @@ public abstract class EasSyncCollectionTypeBase {
*/
public abstract AbstractSyncParser getParser(final Context context, final Account account,
final Mailbox mailbox, final InputStream is) throws IOException;
+
+ /**
+ * After every successful sync iteration, this function gets called to cleanup any state to
+ * match the sync result (e.g., to clean up an external ContentProvider for PIM data).
+ * @param context
+ * @param account
+ */
+ public void cleanup(final Context context, final Account account) {}
+
+ /**
+ * Shared non-initial sync options for PIM (contacts & calendar) objects.
+ *
+ * @param s The {@link com.android.exchange.adapter.Serializer} for this sync request.
+ * @param filter The lookback to use, or null if no lookback is desired.
+ * @param protocolVersion The EAS protocol version for this request, as a double.
+ * @param windowSize
+ * @throws IOException
+ */
+ protected static void setPimSyncOptions(final Serializer s, final String filter,
+ final double protocolVersion, int windowSize) throws IOException {
+ s.tag(Tags.SYNC_DELETES_AS_MOVES);
+ s.tag(Tags.SYNC_GET_CHANGES);
+ s.data(Tags.SYNC_WINDOW_SIZE, String.valueOf(windowSize));
+ s.start(Tags.SYNC_OPTIONS);
+ // Set the filter (lookback), if provided
+ if (filter != null) {
+ s.data(Tags.SYNC_FILTER_TYPE, filter);
+ }
+ // Set the truncation amount and body type
+ if (protocolVersion >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
+ s.start(Tags.BASE_BODY_PREFERENCE);
+ // Plain text
+ s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT);
+ s.data(Tags.BASE_TRUNCATION_SIZE, Eas.EAS12_TRUNCATION_SIZE);
+ s.end();
+ } else {
+ s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
+ }
+ s.end();
+ }
}
diff --git a/src/com/android/exchange/service/EasContactsSyncHandler.java b/src/com/android/exchange/eas/EasSyncContacts.java
index 8757b927..3a6ffc05 100644
--- a/src/com/android/exchange/service/EasContactsSyncHandler.java
+++ b/src/com/android/exchange/eas/EasSyncContacts.java
@@ -1,4 +1,4 @@
-package com.android.exchange.service;
+package com.android.exchange.eas;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
@@ -7,10 +7,8 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.content.EntityIterator;
-import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -54,9 +52,11 @@ import java.util.TimeZone;
* Contact state is in the contacts provider, not in our DB (and therefore not in e.g. mMailbox).
* The Mailbox in the Email DB is only useful for serverId and syncInterval.
*/
-public class EasContactsSyncHandler extends EasSyncHandler {
+public class EasSyncContacts extends EasSyncCollectionTypeBase {
private static final String TAG = Eas.LOG_TAG;
+ public static final int PIM_WINDOW_SIZE_CONTACTS = 10;
+
private static final String MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS =
ContactsContract.Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "' AND " +
GroupMembership.GROUP_ROW_ID + "=?";
@@ -152,34 +152,44 @@ public class EasContactsSyncHandler extends EasSyncHandler {
public static final String ACCOUNT_NAME = "data8";
}
- public EasContactsSyncHandler(final Context context, final ContentResolver contentResolver,
- final android.accounts.Account accountManagerAccount, final Account account,
- final Mailbox mailbox, final Bundle syncExtras, final SyncResult syncResult) {
- super(context, contentResolver, account, mailbox, syncExtras, syncResult);
- mAccountManagerAccount = accountManagerAccount;
+ public EasSyncContacts(final String emailAddress) {
+ mAccountManagerAccount = new android.accounts.Account(emailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
}
@Override
- protected int getTrafficFlag() {
+ public int getTrafficFlag() {
return TrafficFlags.DATA_CONTACTS;
}
@Override
- protected String getFolderClassName() {
- return "Contacts";
+ public void setSyncOptions(final Context context, final Serializer s,
+ final double protocolVersion, final Account account, final Mailbox mailbox,
+ final boolean isInitialSync, final int numWindows) throws IOException {
+ if (isInitialSync) {
+ setInitialSyncOptions(s);
+ return;
+ }
+
+ final int windowSize = numWindows * PIM_WINDOW_SIZE_CONTACTS;
+ if (windowSize > MAX_WINDOW_SIZE + PIM_WINDOW_SIZE_CONTACTS) {
+ throw new IOException("Max window size reached and still no data");
+ }
+ setPimSyncOptions(s, null, protocolVersion,
+ windowSize < MAX_WINDOW_SIZE ? windowSize : MAX_WINDOW_SIZE);
+
+ setUpsyncCommands(s, context.getContentResolver(), account, mailbox, protocolVersion);
}
@Override
- protected AbstractSyncParser getParser(final InputStream is) throws IOException {
- // Store the parser because we'll want to ask it about whether groups are used later.
- // TODO: It'd be nice to find a cleaner way to get this result back from the parser.
- mParser = new ContactsSyncParser(mContext, mContentResolver, is,
- mMailbox, mAccount, mAccountManagerAccount);
+ public AbstractSyncParser getParser(final Context context, final Account account,
+ final Mailbox mailbox, final InputStream is) throws IOException {
+ mParser = new ContactsSyncParser(context, context.getContentResolver(), is, mailbox,
+ account, mAccountManagerAccount);
return mParser;
}
- @Override
- protected void setInitialSyncOptions(final Serializer s) throws IOException {
+ private void setInitialSyncOptions(final Serializer s) throws IOException {
// These are the tags we support for upload; whenever we add/remove support
// (in addData), we need to update this list
s.start(Tags.SYNC_SUPPORTED);
@@ -243,15 +253,6 @@ public class EasContactsSyncHandler extends EasSyncHandler {
s.end(); // SYNC_SUPPORTED
}
- @Override
- protected void setNonInitialSyncOptions(final Serializer s, int numWindows) throws IOException {
- final int windowSize = numWindows * PIM_WINDOW_SIZE_CONTACTS;
- if (windowSize > MAX_WINDOW_SIZE + PIM_WINDOW_SIZE_CONTACTS) {
- throw new IOException("Max window size reached and still no data");
- }
- setPimSyncOptions(s, null, windowSize < MAX_WINDOW_SIZE ? windowSize : MAX_WINDOW_SIZE);
- }
-
/**
* Add account info and the "caller is syncadapter" param to a URI.
* @param uri The {@link Uri} to add to.
@@ -281,10 +282,9 @@ public class EasContactsSyncHandler extends EasSyncHandler {
/**
* Mark contacts in dirty groups as dirty.
*/
- private void dirtyContactsWithinDirtyGroups() {
- final String emailAddress = mAccount.mEmailAddress;
- final Cursor c = mContentResolver.query(
- uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
+ private void dirtyContactsWithinDirtyGroups(final ContentResolver cr, final Account account) {
+ final String emailAddress = account.mEmailAddress;
+ final Cursor c = cr.query( uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
GROUPS_ID_PROJECTION, Groups.DIRTY + "=1", null, null);
if (c == null) {
return;
@@ -300,19 +300,17 @@ public class EasContactsSyncHandler extends EasSyncHandler {
final long id = c.getLong(0);
updateValues.put(GroupMembership.GROUP_ROW_ID, id);
updateArgs[0] = Long.toString(id);
- mContentResolver.update(ContactsContract.Data.CONTENT_URI, updateValues,
+ cr.update(ContactsContract.Data.CONTENT_URI, updateValues,
MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS, updateArgs);
}
// Really delete groups that are marked deleted
- mContentResolver.delete(uriWithAccountAndIsSyncAdapter(
- Groups.CONTENT_URI, emailAddress),
+ cr.delete(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
Groups.DELETED + "=1", null);
// Clear the dirty flag for all of our groups
updateValues.clear();
updateValues.put(Groups.DIRTY, 0);
- mContentResolver.update(uriWithAccountAndIsSyncAdapter(
- Groups.CONTENT_URI, emailAddress), updateValues, null,
- null);
+ cr.update(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
+ updateValues, null, null);
}
} finally {
c.close();
@@ -638,9 +636,11 @@ public class EasContactsSyncHandler extends EasSyncHandler {
* Add a note to the upsync.
* @param s The {@link Serializer} for this sync request.
* @param cv The {@link ContentValues} with the data for this note.
+ * @param protocolVersion
* @throws IOException
*/
- private void sendNote(final Serializer s, final ContentValues cv) throws IOException {
+ private void sendNote(final Serializer s, final ContentValues cv, final double protocolVersion)
+ throws IOException {
// Even when there is no local note, we must explicitly upsync an empty note,
// which is the only way to force the server to delete any pre-existing note.
String note = "";
@@ -649,7 +649,7 @@ public class EasContactsSyncHandler extends EasSyncHandler {
note = cv.getAsString(Note.NOTE).replaceAll("\n", "\r\n");
}
// Format of upsync data depends on protocol version
- if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
+ if (protocolVersion >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
s.start(Tags.BASE_BODY);
s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT).data(Tags.BASE_DATA, note);
s.end();
@@ -681,10 +681,11 @@ public class EasContactsSyncHandler extends EasSyncHandler {
* @param cv The {@link ContentValues} with the data for this email address.
* @param count The number of email addresses that have already been added.
* @param displayName The display name for this contact.
+ * @param protocolVersion
* @throws IOException
*/
private void sendEmail(final Serializer s, final ContentValues cv, final int count,
- final String displayName) throws IOException {
+ final String displayName, final double protocolVersion) throws IOException {
// Get both parts of the email address (a newly created one in the UI won't have a name)
final String addr = cv.getAsString(Email.DATA);
String name = cv.getAsString(Email.DISPLAY_NAME);
@@ -700,7 +701,7 @@ public class EasContactsSyncHandler extends EasSyncHandler {
final String value;
// Only send the raw email address for EAS 2.5 (Hotmail, in particular, chokes on
// an RFC822 address)
- if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
+ if (protocolVersion < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
value = addr;
} else {
value = '\"' + name + "\" <" + addr + '>';
@@ -711,19 +712,19 @@ public class EasContactsSyncHandler extends EasSyncHandler {
}
}
- @Override
- protected void setUpsyncCommands(final Serializer s) throws IOException {
+ private void setUpsyncCommands(final Serializer s, final ContentResolver cr,
+ final Account account, final Mailbox mailbox, final double protocolVersion)
+ throws IOException {
// Find any groups of ours that are dirty and dirty those groups' members
- dirtyContactsWithinDirtyGroups();
+ dirtyContactsWithinDirtyGroups(cr, account);
// First, let's find Contacts that have changed.
final Uri uri = uriWithAccountAndIsSyncAdapter(
- ContactsContract.RawContactsEntity.CONTENT_URI, mAccount.mEmailAddress);
+ ContactsContract.RawContactsEntity.CONTENT_URI, account.mEmailAddress);
// Get them all atomically
final EntityIterator ei = ContactsContract.RawContacts.newEntityIterator(
- mContentResolver.query(uri, null, ContactsContract.RawContacts.DIRTY + "=1", null,
- null));
+ cr.query(uri, null, ContactsContract.RawContacts.DIRTY + "=1", null, null));
final ContentValues cidValues = new ContentValues();
try {
boolean first = true;
@@ -744,12 +745,12 @@ public class EasContactsSyncHandler extends EasSyncHandler {
if (serverId == null) {
// This is a new contact; create a clientId
final String clientId =
- "new_" + mMailbox.mId + '_' + System.currentTimeMillis();
+ "new_" + mailbox.mId + '_' + System.currentTimeMillis();
LogUtils.d(TAG, "Creating new contact with clientId: %s", clientId);
s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId);
// And save it in the raw contact
cidValues.put(ContactsContract.RawContacts.SYNC1, clientId);
- mContentResolver.update(ContentUris.withAppendedId(rawContactUri,
+ cr.update(ContentUris.withAppendedId(rawContactUri,
entityValues.getAsLong(ContactsContract.RawContacts._ID)),
cidValues, null, null);
} else {
@@ -811,7 +812,7 @@ public class EasContactsSyncHandler extends EasSyncHandler {
// We must gather these, and send them together (below)
groupIds.add(cv.getAsInteger(GroupMembership.GROUP_ROW_ID));
} else if (mimeType.equals(Note.CONTENT_ITEM_TYPE)) {
- sendNote(s, cv);
+ sendNote(s, cv, protocolVersion);
} else if (mimeType.equals(Photo.CONTENT_ITEM_TYPE)) {
sendPhoto(s, cv);
} else {
@@ -822,7 +823,7 @@ public class EasContactsSyncHandler extends EasSyncHandler {
// We do the email rows last, because we need to make sure we've found the
// displayName (if one exists); this would be in a StructuredName rnow
for (final ContentValues cv: emailValues) {
- sendEmail(s, cv, emailCount++, displayName);
+ sendEmail(s, cv, emailCount++, displayName, protocolVersion);
}
// Now, we'll send up groups, if any
@@ -830,9 +831,8 @@ public class EasContactsSyncHandler extends EasSyncHandler {
boolean groupFirst = true;
for (final int id: groupIds) {
// Since we get id's from the provider, we need to find their names
- final Cursor c = mContentResolver.query(ContentUris.withAppendedId(
- Groups.CONTENT_URI, id),
- GROUP_TITLE_PROJECTION, null, null, null);
+ final Cursor c = cr.query(ContentUris.withAppendedId(Groups.CONTENT_URI,
+ id), GROUP_TITLE_PROJECTION, null, null, null);
try {
// Presumably, this should always succeed, but ...
if (c.moveToFirst()) {
@@ -863,10 +863,8 @@ public class EasContactsSyncHandler extends EasSyncHandler {
}
@Override
- protected void cleanup(final int syncResult) {
- if (syncResult == SYNC_RESULT_FAILED) {
- return;
- }
+ public void cleanup(final Context context, final Account account) {
+ final ContentResolver cr = context.getContentResolver();
// Mark the changed contacts dirty = 0
// Permanently delete the user deletions
@@ -885,16 +883,15 @@ public class EasContactsSyncHandler extends EasSyncHandler {
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build())
.build());
}
- ops.execute(mContext);
+ ops.execute(context);
if (mParser != null && mParser.isGroupsUsed()) {
// Make sure the title column is set for all of our groups
// And that all of our groups are visible
// TODO Perhaps the visible part should only happen when the group is created, but
// this is fine for now.
final Uri groupsUri = uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI,
- mAccount.mEmailAddress);
- final Cursor c = mContentResolver.query(groupsUri,
- new String[] {Groups.SOURCE_ID, Groups.TITLE},
+ account.mEmailAddress);
+ final Cursor c = cr.query(groupsUri, new String[] {Groups.SOURCE_ID, Groups.TITLE},
Groups.TITLE + " IS NULL", null, null);
final ContentValues values = new ContentValues();
values.put(Groups.GROUP_VISIBLE, 1);
@@ -902,8 +899,8 @@ public class EasContactsSyncHandler extends EasSyncHandler {
while (c.moveToNext()) {
final String sourceId = c.getString(0);
values.put(Groups.TITLE, sourceId);
- mContentResolver.update(uriWithAccountAndIsSyncAdapter(groupsUri,
- mAccount.mEmailAddress), values, Groups.SOURCE_ID + "=?",
+ cr.update(uriWithAccountAndIsSyncAdapter(groupsUri,
+ account.mEmailAddress), values, Groups.SOURCE_ID + "=?",
new String[] {sourceId});
}
} finally {
diff --git a/src/com/android/exchange/eas/EasSyncMail.java b/src/com/android/exchange/eas/EasSyncMail.java
index eec5bdf3..f5e0e153 100644
--- a/src/com/android/exchange/eas/EasSyncMail.java
+++ b/src/com/android/exchange/eas/EasSyncMail.java
@@ -3,6 +3,7 @@ package com.android.exchange.eas;
import android.content.Context;
import android.database.Cursor;
+import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
@@ -32,6 +33,12 @@ public class EasSyncMail extends EasSyncCollectionTypeBase {
private static final int EMAIL_WINDOW_SIZE = 10;
+
+ @Override
+ public int getTrafficFlag() {
+ return TrafficFlags.DATA_EMAIL;
+ }
+
@Override
public void setSyncOptions(final Context context, final Serializer s,
final double protocolVersion, final Account account, final Mailbox mailbox,
diff --git a/src/com/android/exchange/service/EasMailboxSyncHandler.java b/src/com/android/exchange/service/EasMailboxSyncHandler.java
deleted file mode 100644
index 03846741..00000000
--- a/src/com/android/exchange/service/EasMailboxSyncHandler.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package com.android.exchange.service;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SyncResult;
-import android.database.Cursor;
-import android.os.Bundle;
-
-import com.android.emailcommon.TrafficFlags;
-import com.android.emailcommon.provider.Account;
-import com.android.emailcommon.provider.EmailContent.Message;
-import com.android.emailcommon.provider.EmailContent.MessageColumns;
-import com.android.emailcommon.provider.EmailContent.SyncColumns;
-import com.android.emailcommon.provider.Mailbox;
-import com.android.emailcommon.service.SyncWindow;
-import com.android.exchange.Eas;
-import com.android.exchange.adapter.AbstractSyncParser;
-import com.android.exchange.adapter.EmailSyncParser;
-import com.android.exchange.adapter.Serializer;
-import com.android.exchange.adapter.Tags;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-
-/**
- * Performs an Exchange mailbox sync for "normal" mailboxes.
- */
-public class EasMailboxSyncHandler extends EasSyncHandler {
- /**
- * The projection used for building the fetch request list.
- */
- private static final String[] FETCH_REQUEST_PROJECTION = { SyncColumns.SERVER_ID };
- private static final int FETCH_REQUEST_SERVER_ID = 0;
-
- private static final int EMAIL_WINDOW_SIZE = 10;
-
- /**
- * List of server ids for messages to fetch from the server.
- */
- private final ArrayList<String> mMessagesToFetch = new ArrayList<String>();
-
- public EasMailboxSyncHandler(final Context context, final ContentResolver contentResolver,
- final Account account, final Mailbox mailbox, final Bundle syncExtras,
- final SyncResult syncResult) {
- super(context, contentResolver, account, mailbox, syncExtras, syncResult);
- }
-
- private String getEmailFilter() {
- final int syncLookback = mMailbox.mSyncLookback == SyncWindow.SYNC_WINDOW_ACCOUNT
- ? mAccount.mSyncLookback : mMailbox.mSyncLookback;
- switch (syncLookback) {
- case SyncWindow.SYNC_WINDOW_1_DAY:
- return Eas.FILTER_1_DAY;
- case SyncWindow.SYNC_WINDOW_3_DAYS:
- return Eas.FILTER_3_DAYS;
- case SyncWindow.SYNC_WINDOW_1_WEEK:
- return Eas.FILTER_1_WEEK;
- case SyncWindow.SYNC_WINDOW_2_WEEKS:
- return Eas.FILTER_2_WEEKS;
- case SyncWindow.SYNC_WINDOW_1_MONTH:
- return Eas.FILTER_1_MONTH;
- case SyncWindow.SYNC_WINDOW_ALL:
- return Eas.FILTER_ALL;
- default:
- // Auto window is deprecated and will also use the default.
- return Eas.FILTER_1_WEEK;
- }
- }
-
- /**
- * Find partially loaded messages and add their server ids to {@link #mMessagesToFetch}.
- */
- private void addToFetchRequestList() {
- final Cursor c = mContentResolver.query(Message.CONTENT_URI, FETCH_REQUEST_PROJECTION,
- MessageColumns.FLAG_LOADED + "=" + Message.FLAG_LOADED_PARTIAL + " AND " +
- MessageColumns.MAILBOX_KEY + "=?", new String[] {Long.toString(mMailbox.mId)},
- null);
- if (c != null) {
- try {
- while (c.moveToNext()) {
- mMessagesToFetch.add(c.getString(FETCH_REQUEST_SERVER_ID));
- }
- } finally {
- c.close();
- }
- }
- }
-
- @Override
- protected int getTrafficFlag() {
- return TrafficFlags.DATA_EMAIL;
- }
-
- @Override
- protected String getFolderClassName() {
- return "Email";
- }
-
- @Override
- protected AbstractSyncParser getParser(final InputStream is) throws IOException {
- return new EmailSyncParser(mContext, mContentResolver, is, mMailbox, mAccount);
- }
-
- @Override
- protected void setInitialSyncOptions(final Serializer s) {
- // No-op.
- }
-
- @Override
- protected void setNonInitialSyncOptions(final Serializer s, int numWindows) throws IOException {
- // Check for messages that aren't fully loaded.
- addToFetchRequestList();
- // The "empty" case is typical; we send a request for changes, and also specify a sync
- // window, body preference type (HTML for EAS 12.0 and later; MIME for EAS 2.5), and
- // truncation
- // If there are fetch requests, we only want the fetches (i.e. no changes from the server)
- // so we turn MIME support off. Note that we are always using EAS 2.5 if there are fetch
- // requests
- if (mMessagesToFetch.isEmpty()) {
- // Permanently delete if in trash mailbox
- // In Exchange 2003, deletes-as-moves tag = true; no tag = false
- // In Exchange 2007 and up, deletes-as-moves tag is "0" (false) or "1" (true)
- final boolean isTrashMailbox = mMailbox.mType == Mailbox.TYPE_TRASH;
- if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
- if (!isTrashMailbox) {
- s.tag(Tags.SYNC_DELETES_AS_MOVES);
- }
- } else {
- s.data(Tags.SYNC_DELETES_AS_MOVES, isTrashMailbox ? "0" : "1");
- }
- s.tag(Tags.SYNC_GET_CHANGES);
-
- final int windowSize = numWindows * EMAIL_WINDOW_SIZE;
- if (windowSize > MAX_WINDOW_SIZE + EMAIL_WINDOW_SIZE) {
- throw new IOException("Max window size reached and still no data");
- }
- s.data(Tags.SYNC_WINDOW_SIZE,
- String.valueOf(windowSize < MAX_WINDOW_SIZE ? windowSize : MAX_WINDOW_SIZE));
- s.start(Tags.SYNC_OPTIONS);
- // Set the lookback appropriately (EAS calls this a "filter")
- s.data(Tags.SYNC_FILTER_TYPE, getEmailFilter());
- // Set the truncation amount for all classes
- if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
- s.start(Tags.BASE_BODY_PREFERENCE);
- // HTML for email
- s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_HTML);
- s.data(Tags.BASE_TRUNCATION_SIZE, Eas.EAS12_TRUNCATION_SIZE);
- s.end();
- } else {
- // Use MIME data for EAS 2.5
- s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_MIME);
- s.data(Tags.SYNC_MIME_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
- }
- s.end();
- } else {
- // If we have any messages that are not fully loaded, ask for plain text rather than
- // MIME, to guarantee we'll get usable text body. This also means we should NOT ask for
- // new messages -- we only want data for the message explicitly fetched.
- s.start(Tags.SYNC_OPTIONS);
- s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_TEXT);
- s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
- s.end();
- }
- }
-
- /**
- * Add FETCH commands for messages that need a body (i.e. we didn't find it during our earlier
- * sync; this happens only in EAS 2.5 where the body couldn't be found after parsing the
- * message's MIME data).
- * @param s The {@link Serializer} for this sync request.
- * @throws IOException
- */
- private void addFetchCommands(final Serializer s) throws IOException {
- if (!mMessagesToFetch.isEmpty()) {
- s.start(Tags.SYNC_COMMANDS);
- for (final String serverId : mMessagesToFetch) {
- s.start(Tags.SYNC_FETCH).data(Tags.SYNC_SERVER_ID, serverId).end();
- }
- s.end();
- }
- }
-
- @Override
- protected void setUpsyncCommands(final Serializer s) throws IOException {
- addFetchCommands(s);
- }
-
- @Override
- protected void cleanup(final int syncResult) {
- if (syncResult == SYNC_RESULT_MORE_AVAILABLE) {
- // Prepare our member variables for another sync request.
- mMessagesToFetch.clear();
- }
- }
-}
diff --git a/src/com/android/exchange/service/EasSyncHandler.java b/src/com/android/exchange/service/EasSyncHandler.java
index 6614399c..148da49a 100644
--- a/src/com/android/exchange/service/EasSyncHandler.java
+++ b/src/com/android/exchange/service/EasSyncHandler.java
@@ -126,19 +126,9 @@ public abstract class EasSyncHandler extends EasServerConnection {
final Bundle syncExtras, final SyncResult syncResult) {
if (account != null && mailbox != null) {
switch (mailbox.mType) {
- case Mailbox.TYPE_INBOX:
- case Mailbox.TYPE_MAIL:
- case Mailbox.TYPE_DRAFTS:
- case Mailbox.TYPE_SENT:
- case Mailbox.TYPE_TRASH:
- return new EasMailboxSyncHandler(context, contentResolver, account, mailbox,
- syncExtras, syncResult);
case Mailbox.TYPE_CALENDAR:
return new EasCalendarSyncHandler(context, contentResolver,
accountManagerAccount, account, mailbox, syncExtras, syncResult);
- case Mailbox.TYPE_CONTACTS:
- return new EasContactsSyncHandler(context, contentResolver,
- accountManagerAccount, account, mailbox, syncExtras, syncResult);
}
}
// Unknown mailbox type.
diff --git a/src/com/android/exchange/service/EmailSyncAdapterService.java b/src/com/android/exchange/service/EmailSyncAdapterService.java
index 05e7a01e..6a2ed421 100644
--- a/src/com/android/exchange/service/EmailSyncAdapterService.java
+++ b/src/com/android/exchange/service/EmailSyncAdapterService.java
@@ -63,6 +63,7 @@ import com.android.exchange.Eas;
import com.android.exchange.R.drawable;
import com.android.exchange.R.string;
import com.android.exchange.adapter.PingParser;
+import com.android.exchange.eas.EasSyncContacts;
import com.android.exchange.eas.EasFolderSync;
import com.android.exchange.eas.EasLoadAttachment;
import com.android.exchange.eas.EasMoveItems;
@@ -461,7 +462,7 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
LogUtils.d(TAG, "IEmailService.deleteAccountPIMData");
if (emailAddress != null) {
final Context context = EmailSyncAdapterService.this;
- EasContactsSyncHandler.wipeAccountFromContentProvider(context, emailAddress);
+ EasSyncContacts.wipeAccountFromContentProvider(context, emailAddress);
EasCalendarSyncHandler.wipeAccountFromContentProvider(context, emailAddress);
}
// TODO: Run account reconciler?
@@ -875,18 +876,17 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
// Non-mailbox syncs are whole account syncs initiated by the AccountManager and are
// treated as background syncs.
// TODO: Push will be treated as "user" syncs, and probably should be background.
- final ContentValues cv = new ContentValues(2);
- updateMailbox(context, mailbox, cv, isMailboxSync ?
- EmailContent.SYNC_STATUS_USER : EmailContent.SYNC_STATUS_BACKGROUND);
- try {
- if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
- return syncOutbox(context, cr, account, mailbox);
- }
+ if (mailbox.mType == Mailbox.TYPE_OUTBOX || mailbox.isSyncable()) {
+ final ContentValues cv = new ContentValues(2);
+ updateMailbox(context, mailbox, cv, isMailboxSync ?
+ EmailContent.SYNC_STATUS_USER : EmailContent.SYNC_STATUS_BACKGROUND);
+ try {
+ if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
+ return syncOutbox(context, cr, account, mailbox);
+ }
- if(mailbox.isSyncable()) {
// TODO: This conditional logic is temporary until EasSyncHandler is obsolete.
- if (mailbox.mType == Mailbox.TYPE_INBOX || mailbox.mType == Mailbox.TYPE_MAIL ||
- mailbox.mType == Mailbox.TYPE_SENT) {
+ if (mailbox.mType != Mailbox.TYPE_CALENDAR) {
final EasSyncBase operation = new EasSyncBase(context, account, mailbox);
return operation.performOperation();
} else {
@@ -908,9 +908,9 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
}
}
}
+ } finally {
+ updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);
}
- } finally {
- updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);
}
return EasSyncBase.RESULT_DONE;