Merge "Code refactoring, prep for contacts/calendar." into jb-ub-mail-ur10
diff --git a/src/com/android/exchange/service/EasAccountValidator.java b/src/com/android/exchange/service/EasAccountValidator.java
index e867ded..63ce9b9 100644
--- a/src/com/android/exchange/service/EasAccountValidator.java
+++ b/src/com/android/exchange/service/EasAccountValidator.java
@@ -61,8 +61,6 @@
Eas.SUPPORTED_PROTOCOL_EX2007, Eas.SUPPORTED_PROTOCOL_EX2007_SP1,
Eas.SUPPORTED_PROTOCOL_EX2010, Eas.SUPPORTED_PROTOCOL_EX2010_SP1);
- /** mAccount.mProtocolVersion, as a double. If the version is unknown, this will be 0.0. */
- private double mProtocolVersionDouble;
/** The number of times we've been redirected so far. */
private int mRedirectCount;
@@ -81,11 +79,6 @@
public EasAccountValidator(final Context context, final Account account,
final HostAuth hostAuth) {
super(context, account, hostAuth);
- if (account.mProtocolVersion != null) {
- mProtocolVersionDouble = Eas.getProtocolVersionDouble(account.mProtocolVersion);
- } else {
- mProtocolVersionDouble = 0.0d;
- }
mRedirectCount = 0;
}
@@ -115,19 +108,19 @@
if (newProtocolVersion == null) {
LogUtils.w(TAG, "No supported EAS versions: %s", supportedVersions);
// TODO: if mAccount.isSaved(), we should delete the account.
- mProtocolVersionDouble = 0.0d;
return false;
- } else {
- mProtocolVersionDouble = Eas.getProtocolVersionDouble(newProtocolVersion);
}
// Update our account with the new protocol version.
final boolean protocolChanged = !newProtocolVersion.equals(mAccount.mProtocolVersion);
- mAccount.mProtocolVersion = newProtocolVersion;
+ if (protocolChanged) {
+ mAccount.mProtocolVersion = newProtocolVersion;
+ uncacheProtocolVersion();
+ }
// Fixup search flags, if they're not set.
final boolean flagsChanged;
- if (mProtocolVersionDouble >= 12.0) {
+ if (getProtocolVersion() >= 12.0) {
int oldFlags = mAccount.mFlags;
mAccount.mFlags |= Account.FLAGS_SUPPORTS_GLOBAL_SEARCH + Account.FLAGS_SUPPORTS_SEARCH;
flagsChanged = (oldFlags != mAccount.mFlags);
@@ -279,7 +272,7 @@
}
private String getPolicyType() {
- return (mProtocolVersionDouble >=
+ return (getProtocolVersion() >=
Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) ? EAS_12_POLICY_TYPE : EAS_2_POLICY_TYPE;
}
@@ -364,7 +357,7 @@
private ProvisionParser canProvision() throws IOException {
final Serializer s = new Serializer();
s.start(Tags.PROVISION_PROVISION);
- if (mProtocolVersionDouble >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
+ if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
// Send settings information in 14.1 and greater
s.start(Tags.SETTINGS_DEVICE_INFORMATION).start(Tags.SETTINGS_SET);
s.data(Tags.SETTINGS_MODEL, Build.MODEL);
@@ -390,7 +383,7 @@
// The PolicySet in the ProvisionParser will have the requirements for all KNOWN
// policies. If others are required, hasSupportablePolicySet will be false
if (pp.hasSupportablePolicySet() &&
- mProtocolVersionDouble == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
+ getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
// In EAS 14.0, we need the final security key in order to use the settings
// command
final String policyKey = acknowledgeProvision(pp.getSecuritySyncKey(),
@@ -468,7 +461,7 @@
// to the server and get the final policy key
// NOTE: For EAS 14.0, we already have the acknowledgment in the ProvisionParser
String securitySyncKey;
- if (mProtocolVersionDouble == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
+ if (getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
securitySyncKey = pp.getSecuritySyncKey();
} else {
securitySyncKey = acknowledgeProvision(pp.getSecuritySyncKey(),
@@ -560,7 +553,7 @@
resultCode = MessagingException.SECURITY_POLICIES_REQUIRED;
bundle.putParcelable(EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET,
pp.getPolicy());
- if (mProtocolVersionDouble == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
+ if (getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
mAccount.mSecuritySyncKey = pp.getSecuritySyncKey();
if (!sendSettings()) {
LogUtils.i(TAG, "Denied access: %s",
diff --git a/src/com/android/exchange/service/EasMailboxSyncHandler.java b/src/com/android/exchange/service/EasMailboxSyncHandler.java
index f3eab9e..aaf3454 100644
--- a/src/com/android/exchange/service/EasMailboxSyncHandler.java
+++ b/src/com/android/exchange/service/EasMailboxSyncHandler.java
@@ -71,10 +71,8 @@
s.start(Tags.SYNC_COLLECTIONS);
s.start(Tags.SYNC_COLLECTION);
- final Double protocolVersionDouble =
- Eas.getProtocolVersionDouble(getProtocolVersion());
// The "Class" element is removed in EAS 12.1 and later versions
- if (protocolVersionDouble < Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE) {
+ if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE) {
s.data(Tags.SYNC_CLASS, "Email");
}
s.data(Tags.SYNC_SYNC_KEY, mMailbox.mSyncKey);
@@ -93,7 +91,7 @@
// Therefore, we don't send any options with the initial sync.
// Set the truncation amount, body preference, lookback, etc.
if (!initialSync) {
- sendSyncOptions(protocolVersionDouble, s, !fetchRequestList.isEmpty());
+ sendSyncOptions(getProtocolVersion(), s, !fetchRequestList.isEmpty());
// TODO: Fix.
//EmailSyncAdapter.upsync(resolver, mailbox, s);
}
diff --git a/src/com/android/exchange/service/EasOutboxSyncHandler.java b/src/com/android/exchange/service/EasOutboxSyncHandler.java
index 5595231..b2f8cff 100644
--- a/src/com/android/exchange/service/EasOutboxSyncHandler.java
+++ b/src/com/android/exchange/service/EasOutboxSyncHandler.java
@@ -1,13 +1,10 @@
package com.android.exchange.service;
-import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
-import android.content.SyncResult;
import android.database.Cursor;
import android.net.TrafficStats;
import android.net.Uri;
-import android.os.Bundle;
import android.text.format.DateUtils;
import com.android.emailcommon.TrafficFlags;
@@ -20,8 +17,8 @@
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.HostAuth;
import com.android.emailcommon.provider.Mailbox;
-import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.Eas;
@@ -48,7 +45,7 @@
/**
* Performs an Exchange Outbox sync, i.e. sends all mail from the Outbox.
*/
-public class EasOutboxSyncHandler extends EasSyncHandler {
+public class EasOutboxSyncHandler extends EasServerConnection {
// Value for a message's server id when sending fails.
public static final int SEND_FAILED = 1;
@@ -64,24 +61,23 @@
// failure would probably generate an Exception before timing out anyway
public static final long SEND_MAIL_TIMEOUT = 15 * DateUtils.MINUTE_IN_MILLIS;
+ private final Mailbox mMailbox;
private final File mCacheDir;
- public EasOutboxSyncHandler(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);
+ public EasOutboxSyncHandler(final Context context, final Account account,
+ final Mailbox mailbox) {
+ super(context, account, HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv));
+ mMailbox = mailbox;
mCacheDir = context.getCacheDir();
}
- @Override
- public SyncStatus performSync() {
+ public void performSync() {
// Use SMTP flags for sending mail
TrafficStats.setThreadStatsTag(TrafficFlags.getSmtpFlags(mContext, mAccount));
// Get a cursor to Outbox messages
final Cursor c = mContext.getContentResolver().query(Message.CONTENT_URI,
Message.CONTENT_PROJECTION, MAILBOX_KEY_AND_NOT_SEND_FAILED,
new String[] {Long.toString(mMailbox.mId)}, null);
- SyncStatus status = SyncStatus.SUCCESS;
try {
// Loop through the messages, sending each one
while (c.moveToNext()) {
@@ -92,32 +88,19 @@
continue;
}
- sendMessageStatus(message.mId, null, EmailServiceStatus.IN_PROGRESS, 0);
+ // TODO: Fix -- how do we want to signal to UI that we started syncing?
+ // Note the entire callback mechanism here needs improving.
+ //sendMessageStatus(message.mId, null, EmailServiceStatus.IN_PROGRESS, 0);
- status = sendOneMessage(message,
- SmartSendInfo.getSmartSendInfo(mContext, mAccount, message));
- // TODO: Improve handling of individual message send responses.
- switch (status) {
- case SUCCESS:
- break;
- case FAILURE_IO:
- break;
- case FAILURE_LOGIN:
- break;
- case FAILURE_SECURITY:
- break;
- case FAILURE_MESSAGE:
- break;
- case FAILURE_OTHER:
- break;
+ if (!sendOneMessage(message,
+ SmartSendInfo.getSmartSendInfo(mContext, mAccount, message))) {
+ break;
}
}
} finally {
// TODO: Some sort of sendMessageStatus() is needed here.
c.close();
}
-
- return status;
}
/**
@@ -406,15 +389,16 @@
* @param message The message to send.
* @param smartSendInfo The SmartSendInfo for this message, or null if we don't have or don't
* want to use smart send.
- * @return A status value to indicate success or manner of failure for this operation.
+ * @return Whether or not sending this message succeeded.
+ * TODO: Improve how we handle the types of failures. I've left the old error codes in as TODOs
+ * for future reference.
*/
- private SyncStatus sendOneMessage(final Message message,
- final SmartSendInfo smartSendInfo) {
+ private boolean sendOneMessage(final Message message, final SmartSendInfo smartSendInfo) {
final File tmpFile;
try {
tmpFile = File.createTempFile("eas_", "tmp", mCacheDir);
} catch (final IOException e) {
- return SyncStatus.FAILURE_IO;
+ return false; // TODO: Handle SyncStatus.FAILURE_IO;
}
final EasResponse resp;
@@ -424,14 +408,14 @@
final int modeTag = getModeTag(isEas14, smartSendInfo);
try {
if (!writeMessageToTempFile(tmpFile, message, smartSendInfo)) {
- return SyncStatus.FAILURE_IO;
+ return false; // TODO: Handle SyncStatus.FAILURE_IO;
}
final FileInputStream fileStream;
try {
fileStream = new FileInputStream(tmpFile);
} catch (final FileNotFoundException e) {
- return SyncStatus.FAILURE_IO;
+ return false; // TODO: Handle SyncStatus.FAILURE_IO;
}
try {
@@ -462,7 +446,7 @@
try {
resp = sendHttpClientPost(cmd, entity, SEND_MAIL_TIMEOUT);
} catch (final IOException e) {
- return SyncStatus.FAILURE_IO;
+ return false; // TODO: Handle SyncStatus.FAILURE_IO;
}
} finally {
@@ -492,19 +476,19 @@
// The parser holds the status
final int status = p.getStatus();
if (CommandStatus.isNeedsProvisioning(status)) {
- return SyncStatus.FAILURE_SECURITY;
+ return false; // TODO: Handle SyncStatus.FAILURE_SECURITY;
} else if (status == CommandStatus.ITEM_NOT_FOUND &&
smartSendInfo != null) {
// Let's retry without "smart" commands.
return sendOneMessage(message, null);
}
// TODO: Set syncServerId = SEND_FAILED in DB?
- return SyncStatus.FAILURE_MESSAGE;
+ return false; // TODO: Handle SyncStatus.FAILURE_MESSAGE;
} catch (final EmptyStreamException e) {
// This is actually fine; an empty stream means SendMail succeeded
} catch (final IOException e) {
// Parsing failed in some other way.
- return SyncStatus.FAILURE_IO;
+ return false; // TODO: Handle SyncStatus.FAILURE_IO;
}
}
} else if (code == HttpStatus.SC_INTERNAL_SERVER_ERROR && smartSendInfo != null) {
@@ -512,9 +496,9 @@
return sendOneMessage(message, null);
} else {
if (EasResponse.isAuthError(code)) {
- return SyncStatus.FAILURE_LOGIN;
+ return false; // TODO: Handle SyncStatus.FAILURE_LOGIN;
} else if (EasResponse.isProvisionError(code)) {
- return SyncStatus.FAILURE_SECURITY;
+ return false; // TODO: Handle SyncStatus.FAILURE_SECURITY;
}
}
} finally {
@@ -525,7 +509,7 @@
// Delete the sent message.
mContext.getContentResolver().delete(
ContentUris.withAppendedId(Message.CONTENT_URI, message.mId), null, null);
- return SyncStatus.SUCCESS;
+ return true;
}
/**
diff --git a/src/com/android/exchange/service/EasServerConnection.java b/src/com/android/exchange/service/EasServerConnection.java
index 3b0ffa5..b87e128 100644
--- a/src/com/android/exchange/service/EasServerConnection.java
+++ b/src/com/android/exchange/service/EasServerConnection.java
@@ -78,6 +78,14 @@
private boolean mStopped = false;
/**
+ * The protocol version to use, as a double. This is a cached value based on the protocol
+ * version in {@link #mAccount}, so whenever that value is changed,
+ * {@link #uncacheProtocolVersion()} must be called.
+ */
+ private double mProtocolVersionDouble = 0.0d;
+
+
+ /**
* We want to reuse {@link EmailClientConnectionManager} across different requests to the same
* {@link HostAuth}. Since HostAuths have unique ids, we can use that as the cache key.
* All access to the cache must be synchronized in theory, although in practice since we don't
@@ -192,10 +200,10 @@
}
/**
- * Get the protocol version for an account, or a default if we can't determine it.
- * @return The protocol version for account, as a String.
+ * Get the protocol version for {@link #mAccount}, or a default if we can't determine it.
+ * @return The protocol version for {@link #mAccount}, as a String.
*/
- protected String getProtocolVersion() {
+ private String getProtocolVersionString() {
if (mAccount.mProtocolVersion != null) {
return mAccount.mProtocolVersion;
}
@@ -203,13 +211,33 @@
}
/**
+ * If a sync causes us to update our protocol version, this function must be called so that
+ * subsequent calls to {@link #getProtocolVersion()} will do the right thing.
+ */
+ protected void uncacheProtocolVersion() {
+ mProtocolVersionDouble = 0.0d;
+ }
+
+ /**
+ * Get the protocol version for {@link #mAccount}, as a double. This function caches the result
+ * of looking up the value so that subsequent calls do not have to repeat that.
+ * @return The protocol version for {@link #mAccount}, as a double.
+ */
+ protected double getProtocolVersion() {
+ if (mProtocolVersionDouble == 0.0d) {
+ mProtocolVersionDouble = Eas.getProtocolVersionDouble(getProtocolVersionString());
+ }
+ return mProtocolVersionDouble;
+ }
+
+ /**
* Set standard HTTP headers, using a policy key if required
* @param method the method we are going to send
* @param usePolicyKey whether or not a policy key should be sent in the headers
*/
private void setHeaders(final HttpRequestBase method, final boolean usePolicyKey) {
method.setHeader("Authorization", makeAuthString());
- method.setHeader("MS-ASProtocolVersion", getProtocolVersion());
+ method.setHeader("MS-ASProtocolVersion", getProtocolVersionString());
method.setHeader("User-Agent", USER_AGENT);
method.setHeader("Accept-Encoding", "gzip");
if (usePolicyKey) {
@@ -273,9 +301,7 @@
// Send the proper Content-Type header; it's always wbxml except for messages when
// the EAS protocol version is < 14.0
// If entity is null (e.g. for attachments), don't set this header
- final String protocolVersion = getProtocolVersion();
- final Double protocolVersionDouble = Eas.getProtocolVersionDouble(protocolVersion);
- if (msg && (protocolVersionDouble < Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE)) {
+ if (msg && (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE)) {
method.setHeader("Content-Type", "message/rfc822");
} else if (entity != null) {
method.setHeader("Content-Type", "application/vnd.ms-sync.wbxml");
diff --git a/src/com/android/exchange/service/EasSyncHandler.java b/src/com/android/exchange/service/EasSyncHandler.java
index b2af7a2..e65b0eb 100644
--- a/src/com/android/exchange/service/EasSyncHandler.java
+++ b/src/com/android/exchange/service/EasSyncHandler.java
@@ -14,7 +14,7 @@
* Base class for performing a single sync action. It holds the state needed for all sync actions
* (e.g. account and auth info, sync extras and results) and functions to communicate to with the
* app UI.
- * Sublclasses must implement {@link #performSync}, but otherwise have no other requirements.
+ * Subclasses must implement {@link #performSync}, but otherwise have no other requirements.
*/
public abstract class EasSyncHandler extends EasServerConnection {
protected final ContentResolver mContentResolver;
@@ -71,9 +71,6 @@
case Mailbox.TYPE_MAIL:
return new EasMailboxSyncHandler(context, contentResolver, account, mailbox,
syncExtras, syncResult);
- case Mailbox.TYPE_OUTBOX:
- return new EasOutboxSyncHandler(context, contentResolver, account, mailbox,
- syncExtras, syncResult);
}
}
// Could not handle this sync.
diff --git a/src/com/android/exchange/service/EmailSyncAdapterService.java b/src/com/android/exchange/service/EmailSyncAdapterService.java
index 4ed1c69..adb7572 100644
--- a/src/com/android/exchange/service/EmailSyncAdapterService.java
+++ b/src/com/android/exchange/service/EmailSyncAdapterService.java
@@ -498,20 +498,28 @@
} else {
inboxSyncHandler.performSync();
}
+
+ // TODO: Do an outbox sync as well?
} else {
// Sync the mailbox that was explicitly requested.
final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
- final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context, cr,
- account, mailbox, extras, syncResult);
-
- if (syncHandler != null) {
- syncHandler.performSync();
+ if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
+ final EasOutboxSyncHandler outboxSyncHandler =
+ new EasOutboxSyncHandler(context, account, mailbox);
+ outboxSyncHandler.performSync();
} else {
- // We can't sync this mailbox, so just send the expected UI callbacks.
- EmailServiceStatus.syncMailboxStatus(cr, extras, mailboxId,
- EmailServiceStatus.IN_PROGRESS, 0);
- EmailServiceStatus.syncMailboxStatus(cr, extras, mailboxId,
- EmailServiceStatus.SUCCESS, 0);
+ final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context, cr,
+ account, mailbox, extras, syncResult);
+
+ if (syncHandler != null) {
+ syncHandler.performSync();
+ } else {
+ // We can't sync this mailbox, so just send the expected UI callbacks.
+ EmailServiceStatus.syncMailboxStatus(cr, extras, mailboxId,
+ EmailServiceStatus.IN_PROGRESS, 0);
+ EmailServiceStatus.syncMailboxStatus(cr, extras, mailboxId,
+ EmailServiceStatus.SUCCESS, 0);
+ }
}
}