blob: 07989465c888cda97497fbb248b386f2c1170e3d [file] [log] [blame]
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;
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.EmailSyncAdapter.EasEmailSyncParser;
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 {
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 static final String[] FETCH_REQUEST_PROJECTION =
new String[] {EmailContent.RECORD_ID, SyncColumns.SERVER_ID};
private static final int FETCH_REQUEST_RECORD_ID = 0;
private static final int FETCH_REQUEST_SERVER_ID = 1;
private static final String EMAIL_WINDOW_SIZE = "5";
/**
* Holder for fetch request information (record id and server id)
*/
private static class FetchRequest {
final long messageId;
final String serverId;
FetchRequest(final long _messageId, final String _serverId) {
messageId = _messageId;
serverId = _serverId;
}
}
private String getEmailFilter() {
int syncLookback = mMailbox.mSyncLookback;
if (syncLookback == SyncWindow.SYNC_WINDOW_UNKNOWN
|| mMailbox.mType == Mailbox.TYPE_INBOX) {
syncLookback = mAccount.mSyncLookback;
}
switch (syncLookback) {
case SyncWindow.SYNC_WINDOW_AUTO:
return Eas.FILTER_AUTO;
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:
return Eas.FILTER_1_WEEK;
}
}
private ArrayList<FetchRequest> createFetchRequestList(final boolean initialSync) {
final ArrayList<FetchRequest> fetchRequestList = new ArrayList<FetchRequest>();
if (!initialSync) {
// Find partially loaded messages; this should typically be a rare occurrence
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);
try {
// Put all of these messages into a list; we'll need both id and server id
while (c.moveToNext()) {
fetchRequestList.add(new FetchRequest(c.getLong(FETCH_REQUEST_RECORD_ID),
c.getString(FETCH_REQUEST_SERVER_ID)));
}
} finally {
c.close();
}
}
return fetchRequestList;
}
@Override
protected int getTrafficFlag() {
return TrafficFlags.DATA_EMAIL;
}
@Override
protected String getSyncKey() {
if (mMailbox == null) {
return null;
}
if (mMailbox.mSyncKey == null) {
// TODO: Write to DB? Probably not, and just let successful sync do that.
mMailbox.mSyncKey = "0";
}
return mMailbox.mSyncKey;
}
@Override
protected String getFolderClassName() {
return "Email";
}
@Override
protected AbstractSyncParser getParser(final InputStream is) throws IOException {
return new EasEmailSyncParser(mContext, mContentResolver, is, mMailbox, mAccount);
}
@Override
protected void setInitialSyncOptions(final Serializer s) {
// No-op.
}
@Override
protected void setNonInitialSyncOptions(final Serializer s) throws IOException {
// 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
// TODO: Fix.
final boolean hasFetchRequests = false;
if (!hasFetchRequests) {
// 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);
s.data(Tags.SYNC_WINDOW_SIZE, EMAIL_WINDOW_SIZE);
s.start(Tags.SYNC_OPTIONS);
// Set the lookback appropriately (EAS calls this a "filter")
String filter = getEmailFilter();
// We shouldn't get FILTER_AUTO here, but if we do, make it something legal...
if (filter.equals(Eas.FILTER_AUTO)) {
filter = Eas.FILTER_3_DAYS;
}
s.data(Tags.SYNC_FILTER_TYPE, filter);
// 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 {
s.start(Tags.SYNC_OPTIONS);
// Ask for plain text, rather than MIME data. This guarantees that we'll get a usable
// text body
s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_TEXT);
s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
s.end();
}
}
@Override
protected void setUpsyncCommands(final Serializer s) throws IOException {
}
}