summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Ping Hu <yph@google.com>2014-03-06 18:52:55 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-06 18:52:55 +0000
commit1a085db22d269721b862567c4153ebd93b2340a5 (patch)
tree68f4afae218845e7bcc3675e4bd082b090150cc8
parent36fa2e58cd03a2f2bda55a9fcd8780f153d0c611 (diff)
parent9a2230380dc95e4b6dd66b14a43d8007dc5f784e (diff)
downloadExchange-1a085db22d269721b862567c4153ebd93b2340a5.tar.gz
Merge "Switch to using EasSyncBase for mail downsync." into ub-mail-klp-mr2
-rw-r--r--src/com/android/exchange/eas/EasOperation.java32
-rw-r--r--src/com/android/exchange/eas/EasSyncBase.java10
-rw-r--r--src/com/android/exchange/eas/EasSyncCollectionTypeBase.java3
-rw-r--r--src/com/android/exchange/service/EmailSyncAdapterService.java111
4 files changed, 86 insertions, 70 deletions
diff --git a/src/com/android/exchange/eas/EasOperation.java b/src/com/android/exchange/eas/EasOperation.java
index e53363ab..a03543d7 100644
--- a/src/com/android/exchange/eas/EasOperation.java
+++ b/src/com/android/exchange/eas/EasOperation.java
@@ -130,8 +130,8 @@ public abstract class EasOperation {
public static final int RESULT_CLIENT_CERTIFICATE_REQUIRED = -8;
/** Error code indicating we don't have a protocol version in common with the server. */
public static final int RESULT_PROTOCOL_VERSION_UNSUPPORTED = -9;
- /** Error code indicating the account could not be loaded from the provider. */
- public static final int RESULT_ACCOUNT_ID_INVALID = -10;
+ /** Error code indicating a hard error when initializing the operation. */
+ public static final int RESULT_INITIALIZATION_FAILURE = -10;
/** Error code indicating a hard data layer error. */
public static final int RESULT_HARD_DATA_FAILURE = -11;
/** Error code indicating some other failure. */
@@ -266,11 +266,9 @@ public abstract class EasOperation {
public int performOperation() {
// Make sure the account is loaded if it hasn't already been.
if (!init(false)) {
- // TODO: Fix this comment and error code, init() can now fail for reasons other than
- // failing to load the account.
- LogUtils.i(LOG_TAG, "Failed to load account %d before sending request for operation %s",
+ LogUtils.i(LOG_TAG, "Failed to initialize %d before sending request for operation %s",
getAccountId(), getCommand());
- return RESULT_ACCOUNT_ID_INVALID;
+ return RESULT_INITIALIZATION_FAILURE;
}
// We handle server redirects by looping, but we need to protect against too much looping.
@@ -721,31 +719,39 @@ public abstract class EasOperation {
amAccount.toString(), extras.toString());
}
- public static void writeResultToSyncResult(final int result, final SyncResult syncResult) {
+ /**
+ * Interpret a result code from an {@link EasOperation} and, if it's an error, write it to
+ * the appropriate field in {@link SyncResult}.
+ * @param result
+ * @param syncResult
+ * @return Whether an error code was written to syncResult.
+ */
+ public static boolean writeResultToSyncResult(final int result, final SyncResult syncResult) {
switch (result) {
case RESULT_TOO_MANY_REDIRECTS:
syncResult.tooManyRetries = true;
- break;
+ return true;
case RESULT_REQUEST_FAILURE:
syncResult.stats.numIoExceptions = 1;
- break;
+ return true;
case RESULT_FORBIDDEN:
case RESULT_PROVISIONING_ERROR:
case RESULT_AUTHENTICATION_ERROR:
case RESULT_CLIENT_CERTIFICATE_REQUIRED:
syncResult.stats.numAuthExceptions = 1;
- break;
+ return true;
case RESULT_PROTOCOL_VERSION_UNSUPPORTED:
// Only used in validate, so there's never a syncResult to write to here.
break;
- case RESULT_ACCOUNT_ID_INVALID:
+ case RESULT_INITIALIZATION_FAILURE:
case RESULT_HARD_DATA_FAILURE:
syncResult.databaseError = true;
- break;
+ return true;
case RESULT_OTHER_FAILURE:
// TODO: Is this correct?
syncResult.stats.numIoExceptions = 1;
- break;
+ return true;
}
+ return false;
}
}
diff --git a/src/com/android/exchange/eas/EasSyncBase.java b/src/com/android/exchange/eas/EasSyncBase.java
index dfa5e9b3..ede73b5f 100644
--- a/src/com/android/exchange/eas/EasSyncBase.java
+++ b/src/com/android/exchange/eas/EasSyncBase.java
@@ -30,7 +30,7 @@ public class EasSyncBase extends EasOperation {
public static final int RESULT_DONE = 0;
public static final int RESULT_MORE_AVAILABLE = 1;
- private final boolean mInitialSync;
+ private boolean mInitialSync;
private final Mailbox mMailbox;
private EasSyncCollectionTypeBase mCollectionTypeHandler;
@@ -39,8 +39,6 @@ public class EasSyncBase extends EasOperation {
// TODO: Convert to accountId when ready to convert to EasService.
public EasSyncBase(final Context context, final Account account, final Mailbox mailbox) {
super(context, account);
- // TODO: This works for email, but not necessarily for other types.
- mInitialSync = EmailContent.isInitialSyncKey(getSyncKey());
mMailbox = mailbox;
}
@@ -82,7 +80,7 @@ public class EasSyncBase extends EasOperation {
final String syncKey = getSyncKey();
LogUtils.d(TAG, "Syncing account %d mailbox %d (class %s) with syncKey %s", mAccount.mId,
mMailbox.mId, className, syncKey);
-
+ mInitialSync = EmailContent.isInitialSyncKey(syncKey);
final Serializer s = new Serializer();
s.start(Tags.SYNC_SYNC);
s.start(Tags.SYNC_COLLECTIONS);
@@ -120,7 +118,7 @@ public class EasSyncBase extends EasOperation {
public int performOperation() {
int result = RESULT_MORE_AVAILABLE;
mNumWindows = 1;
- String key = getSyncKey();
+ final String key = getSyncKey();
while (result == RESULT_MORE_AVAILABLE) {
result = super.performOperation();
// TODO: Clear pending request queue.
@@ -156,7 +154,7 @@ public class EasSyncBase extends EasOperation {
case Mailbox.TYPE_MAIL:
case Mailbox.TYPE_INBOX:
case Mailbox.TYPE_DRAFTS:
-// case Mailbox.TYPE_SENT:
+ case Mailbox.TYPE_SENT:
// case Mailbox.TYPE_TRASH:
case Mailbox.TYPE_JUNK: {
return new EasSyncMail();
diff --git a/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java b/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
index 6ff15083..d8e578c0 100644
--- a/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
+++ b/src/com/android/exchange/eas/EasSyncCollectionTypeBase.java
@@ -15,9 +15,6 @@ import java.io.InputStream;
* These details include:
* - Forming the request options. Contacts, Calendar, and Mail set this up differently.
* - Getting the appropriate parser for this collection type.
- * These classes should be stateless, i.e. the distinct subtypes and instances are used simply
- * to have polymorphic behavior for these functions. If member variables are ever added to any
- * of these classes, {@link EasSyncBase} MUST change how it creates these objects.
*/
public abstract class EasSyncCollectionTypeBase {
diff --git a/src/com/android/exchange/service/EmailSyncAdapterService.java b/src/com/android/exchange/service/EmailSyncAdapterService.java
index b59822f6..05e7a01e 100644
--- a/src/com/android/exchange/service/EmailSyncAdapterService.java
+++ b/src/com/android/exchange/service/EmailSyncAdapterService.java
@@ -71,6 +71,7 @@ import com.android.exchange.eas.EasOutboxSync;
import com.android.exchange.eas.EasPing;
import com.android.exchange.eas.EasSearch;
import com.android.exchange.eas.EasSync;
+import com.android.exchange.eas.EasSyncBase;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;
@@ -720,7 +721,6 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
// Do the bookkeeping for starting a sync, including stopping a ping if necessary.
mSyncHandlerMap.startSync(account.mId);
- boolean lastSyncHadError = false;
try {
// Perform a FolderSync if necessary.
@@ -760,32 +760,29 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
}
if (mailboxIds != null) {
- long numIoExceptions = 0;
- long numAuthExceptions = 0;
// Sync the mailbox that was explicitly requested.
for (final long mailboxId : mailboxIds) {
- final boolean success = syncMailbox(context, cr, acct, account, mailboxId,
+ final int result = syncMailbox(context, cr, acct, account, mailboxId,
extras, syncResult, null, true);
- if (!success) {
- lastSyncHadError = true;
- }
+ EasSyncBase.writeResultToSyncResult(result, syncResult);
if (hasCallbackMethod) {
- final int result;
+ final int uiResult;
if (syncResult.hasError()) {
- if (syncResult.stats.numIoExceptions > numIoExceptions) {
- result = UIProvider.LastSyncResult.CONNECTION_ERROR;
- numIoExceptions = syncResult.stats.numIoExceptions;
- } else if (syncResult.stats.numAuthExceptions> numAuthExceptions) {
- result = UIProvider.LastSyncResult.AUTH_ERROR;
- numAuthExceptions= syncResult.stats.numAuthExceptions;
+ if (syncResult.stats.numIoExceptions > 0) {
+ uiResult = UIProvider.LastSyncResult.CONNECTION_ERROR;
+ } else if (syncResult.stats.numAuthExceptions > 0) {
+ uiResult = UIProvider.LastSyncResult.AUTH_ERROR;
} else {
- result = UIProvider.LastSyncResult.INTERNAL_ERROR;
+ uiResult = UIProvider.LastSyncResult.INTERNAL_ERROR;
}
} else {
- result = UIProvider.LastSyncResult.SUCCESS;
+ uiResult = UIProvider.LastSyncResult.SUCCESS;
}
EmailServiceStatus.syncMailboxStatus(
- cr, extras, mailboxId,EmailServiceStatus.SUCCESS, 0, result);
+ cr, extras, mailboxId,EmailServiceStatus.SUCCESS, 0, uiResult);
+ }
+ if (syncResult.hasError()) {
+ break;
}
}
} else if (!accountOnly && !pushOnly) {
@@ -802,10 +799,11 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
try {
final HashSet<String> authsToSync = getAuthsToSync(acct);
while (c.moveToNext()) {
- boolean success = syncMailbox(context, cr, acct, account,
+ final int result = syncMailbox(context, cr, acct, account,
c.getLong(0), extras, syncResult, authsToSync, false);
- if (!success) {
- lastSyncHadError = true;
+ EasSyncBase.writeResultToSyncResult(result, syncResult);
+ if (syncResult.hasError()) {
+ break;
}
}
} finally {
@@ -815,11 +813,13 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
}
} finally {
// Clean up the bookkeeping, including restarting ping if necessary.
- mSyncHandlerMap.syncComplete(lastSyncHadError, account);
+ mSyncHandlerMap.syncComplete(syncResult.hasError(), account);
+
+ // If any operations had an auth error, notify the user.
+ if (syncResult.stats.numAuthExceptions > 0) {
+ showAuthNotification(account.mId, account.mEmailAddress);
+ }
- // TODO: It may make sense to have common error handling here. Two possibilities:
- // 1) performSync return value can signal some useful info.
- // 2) syncResult can contain useful info.
LogUtils.d(TAG, "onPerformSync: finished");
}
}
@@ -841,24 +841,24 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
mailbox.update(context, cv);
}
- private boolean syncMailbox(final Context context, final ContentResolver cr,
+ private int syncMailbox(final Context context, final ContentResolver cr,
final android.accounts.Account acct, final Account account, final long mailboxId,
final Bundle extras, final SyncResult syncResult, final HashSet<String> authsToSync,
final boolean isMailboxSync) {
final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
if (mailbox == null) {
- return false;
+ return EasSyncBase.RESULT_HARD_DATA_FAILURE;
}
if (mailbox.mAccountKey != account.mId) {
LogUtils.e(TAG, "Mailbox does not match account: %s, %s", acct.toString(),
extras.toString());
- return false;
+ return EasSyncBase.RESULT_HARD_DATA_FAILURE;
}
if (authsToSync != null && !authsToSync.contains(Mailbox.getAuthority(mailbox.mType))) {
// We are asking for an account sync, but this mailbox type is not configured for
// sync. Do NOT treat this as a sync error for ping backoff purposes.
- return true;
+ return EasSyncBase.RESULT_DONE;
}
if (mailbox.mType == Mailbox.TYPE_DRAFTS) {
@@ -869,36 +869,51 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
// that we won't sync even if the user attempts to force a sync from the UI.
// Do NOT treat as a sync error for ping backoff purposes.
LogUtils.d(TAG, "Skipping sync of DRAFTS folder");
- return true;
+ return EasSyncBase.RESULT_DONE;
}
- final boolean success;
+
// 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);
- if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
- int result = syncOutbox(context, cr, account, mailbox);
- // TODO: in some cases we might want to abort the sync completely.
- success = true;
- } else if(mailbox.isSyncable()) {
- final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context, cr,
- acct, account, mailbox, extras, syncResult);
- if (syncHandler != null) {
- success = syncHandler.performSync(syncResult);
- } else {
- success = false;
+ try {
+ if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
+ return syncOutbox(context, cr, account, mailbox);
}
- } else {
- success = false;
- }
- updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);
- if (syncResult.stats.numAuthExceptions > 0) {
- showAuthNotification(account.mId, account.mEmailAddress);
+ 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) {
+ final EasSyncBase operation = new EasSyncBase(context, account, mailbox);
+ return operation.performOperation();
+ } else {
+ // TODO: This branch goes away after all conversions are done.
+ final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context,
+ cr, acct, account, mailbox, extras, syncResult);
+ if (syncHandler != null) {
+ if (!syncHandler.performSync(syncResult)) {
+ // This is ass-backwards, but it's a hack until this code goes away.
+ if (syncResult.stats.numIoExceptions > 0) {
+ return EasSyncBase.RESULT_REQUEST_FAILURE;
+ }
+ if (syncResult.stats.numAuthExceptions > 0) {
+ return EasSyncBase.RESULT_AUTHENTICATION_ERROR;
+ }
+ if (syncResult.stats.numParseExceptions > 0) {
+ return EasSyncBase.RESULT_OTHER_FAILURE;
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);
}
- return success;
+
+ return EasSyncBase.RESULT_DONE;
}
}