Refactor, cleanup, and fix sync bugs

* Found/fixed major sync bug re: first-time sync (emulator only)
* Moved deviceId code to SyncManager
* Added code to handle some edge cases related to sync errors
This commit is contained in:
Marc Blank 2009-08-07 22:23:10 -07:00
parent b9d6ba11c7
commit fc579d4477
7 changed files with 187 additions and 112 deletions

View File

@ -767,7 +767,12 @@ public abstract class EmailContent {
public static final int CHECK_INTERVAL_NEVER = -1;
public static final int CHECK_INTERVAL_PUSH = -2;
// For EAS...
// Ping indicates that the box is pushed via a "ping" from the server
public static final int CHECK_INTERVAL_PING = -3;
// PingHold indicates a push or ping box that shouldn't sync just yet
public static final int CHECK_INTERVAL_PUSH_HOLD = -4;
public static final int SYNC_WINDOW_USER = -1;

View File

@ -56,14 +56,9 @@ import android.content.Intent;
import android.database.Cursor;
import android.os.RemoteException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
@ -84,20 +79,24 @@ public class EasSyncService extends AbstractSyncService {
private static final String PIM_WINDOW_SIZE = "20";
private static final String WHERE_ACCOUNT_KEY_AND_SERVER_ID =
MailboxColumns.ACCOUNT_KEY + "=? and " + MailboxColumns.SERVER_ID + "=?";
private static final String WHERE_SYNC_INTERVAL_PING =
Mailbox.SYNC_INTERVAL + '=' + Account.CHECK_INTERVAL_PING;
private static final String WHERE_ACCOUNT_AND_SYNC_INTERVAL_PING =
MailboxColumns.ACCOUNT_KEY + "=? and " + MailboxColumns.SYNC_INTERVAL +
'=' + Account.CHECK_INTERVAL_PING;
private static final String AND_FREQUENCY_PING_PUSH_AND_NOT_ACCOUNT_MAILBOX = " AND " +
MailboxColumns.SYNC_INTERVAL + " IN (" + Account.CHECK_INTERVAL_PING +
',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.TYPE + "!=\"" +
Mailbox.TYPE_EAS_ACCOUNT_MAILBOX + '\"';
private static final String WHERE_PUSH_HOLD_NOT_ACCOUNT_MAILBOX =
MailboxColumns.ACCOUNT_KEY + "=? and " + MailboxColumns.SYNC_INTERVAL +
'=' + Account.CHECK_INTERVAL_PUSH_HOLD;
static private final int CHUNK_SIZE = 16 * 1024;
// Reasonable default
String mProtocolVersion = "2.5";
public Double mProtocolVersionDouble;
static String mDeviceId = null;
static String mDeviceType = "Android";
private String mDeviceId = null;
private String mDeviceType = "Android";
AbstractSyncAdapter mTarget;
String mAuthString = null;
String mCmdString = null;
@ -163,17 +162,16 @@ public class EasSyncService extends AbstractSyncService {
boolean ssl, Context context) throws MessagingException {
try {
userLog("Testing EAS: " + hostAddress + ", " + userName + ", ssl = " + ssl);
Serializer s = new Serializer();
s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY).text("0")
.end().end().done();
EasSyncService svc = new EasSyncService("%TestAccount%");
svc.mContext = context;
svc.mHostAddress = hostAddress;
svc.mUserName = userName;
svc.mPassword = password;
svc.mSsl = ssl;
HttpURLConnection uc = svc.sendEASPostCommand("FolderSync", s.toString());
svc.mDeviceId = SyncManager.getDeviceId();
HttpURLConnection uc = svc.setupEASCommand("OPTIONS", null);
int code = uc.getResponseCode();
userLog("Validation response code: " + code);
userLog("Validation (OPTIONS) response: " + code);
if (code == HttpURLConnection.HTTP_OK) {
// No exception means successful validation
userLog("Validation successful");
@ -331,10 +329,8 @@ public class EasSyncService extends AbstractSyncService {
}
@SuppressWarnings("deprecation")
private String makeUriString(String cmd, String extra) {
private String makeUriString(String cmd, String extra) throws IOException {
// Cache the authentication string and the command string
if (mDeviceId == null)
mDeviceId = "droidfu";
String safeUserName = URLEncoder.encode(mUserName);
if (mAuthString == null) {
String cs = mUserName + ':' + mPassword;
@ -342,7 +338,6 @@ public class EasSyncService extends AbstractSyncService {
mCmdString = "&User=" + safeUserName + "&DeviceId=" + mDeviceId + "&DeviceType="
+ mDeviceType;
}
String us = (mSsl ? "https" : "http") + "://" + mHostAddress +
"/Microsoft-Server-ActiveSync";
if (cmd != null) {
@ -432,7 +427,8 @@ public class EasSyncService extends AbstractSyncService {
mAccount.update(mContext, cv);
}
if (mAccount.mSyncKey.equals("0")) {
boolean firstSync = mAccount.mSyncKey.equals("0");
if (firstSync) {
userLog("Initial FolderSync");
}
@ -440,8 +436,9 @@ public class EasSyncService extends AbstractSyncService {
ContentValues cv = new ContentValues();
cv.put(Mailbox.SYNC_INTERVAL, Account.CHECK_INTERVAL_PUSH);
if (mContentResolver.update(Mailbox.CONTENT_URI, cv,
WHERE_SYNC_INTERVAL_PING, null) > 0) {
SyncManager.kick();
WHERE_ACCOUNT_AND_SYNC_INTERVAL_PING,
new String[] {Long.toString(mAccount.mId)}) > 0) {
SyncManager.kick("change ping boxes to push");
}
// Determine our protocol version, if we haven't already
@ -472,7 +469,7 @@ public class EasSyncService extends AbstractSyncService {
}
}
while (!mStop) {
while (!mStop) {
userLog("Sending Account syncKey: " + mAccount.mSyncKey);
Serializer s = new Serializer();
s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY)
@ -501,9 +498,18 @@ public class EasSyncService extends AbstractSyncService {
userLog("FolderSync response error: " + code);
}
// Change all push/hold boxes to push
cv = new ContentValues();
cv.put(Mailbox.SYNC_INTERVAL, Account.CHECK_INTERVAL_PUSH);
if (mContentResolver.update(Mailbox.CONTENT_URI, cv,
WHERE_PUSH_HOLD_NOT_ACCOUNT_MAILBOX,
new String[] {Long.toString(mAccount.mId)}) > 0) {
userLog("Set push/hold boxes to push...");
}
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, mExitStatus, 0);
.syncMailboxListStatus(mAccount.mId, mExitStatus, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
@ -539,7 +545,7 @@ public class EasSyncService extends AbstractSyncService {
// We'll try reloading folders first; this has been observed to work in some cases
if (!mTriedReloadFolderList) {
errorLog("*** PING LOOP: Trying to reload folder list...");
SyncManager.reloadFolderList(mContext, mAccount.mId);
SyncManager.reloadFolderList(mContext, mAccount.mId, true);
mTriedReloadFolderList = true;
// If we've tried that, set all mailboxes (except the account mailbox) to 5 minute sync
} else {
@ -822,37 +828,6 @@ public class EasSyncService extends AbstractSyncService {
return filter;
}
/**
* EAS requires a unique device id, so that sync is possible from a variety of different
* devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other
* device that doesn't provide one, we can create it as droid<n> where <n> is system time.
* This would work on a real device as well, but it would be better to use the "real" id if
* it's available
*/
private String getSimulatedDeviceId() {
try {
File f = mContext.getFileStreamPath("deviceName");
BufferedReader rdr = null;
String id;
if (f.exists() && f.canRead()) {
rdr = new BufferedReader(new FileReader(f), 128);
id = rdr.readLine();
rdr.close();
return id;
} else if (f.createNewFile()) {
BufferedWriter w = new BufferedWriter(new FileWriter(f));
id = "droid" + System.currentTimeMillis();
w.write(id);
w.close();
}
} catch (FileNotFoundException e) {
// We'll just use the default below
} catch (IOException e) {
// We'll just use the default below
}
return "droid0";
}
/**
* Common code to sync E+PIM data
*
@ -886,7 +861,6 @@ public class EasSyncService extends AbstractSyncService {
if (mailbox.mSyncKey == null) {
userLog("Mailbox syncKey RESET");
mailbox.mSyncKey = "0";
mailbox.mSyncInterval = target.mService.mAccount.mSyncInterval;
}
String className = target.getCollectionName();
userLog("Sending " + className + " syncKey: " + mailbox.mSyncKey);
@ -959,12 +933,7 @@ public class EasSyncService extends AbstractSyncService {
public void run() {
mThread = Thread.currentThread();
TAG = mThread.getName();
mDeviceId = android.provider.Settings.Secure.getString(mContext.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
// Generate a device id if we don't have one
if (mDeviceId == null) {
mDeviceId = getSimulatedDeviceId();
}
HostAuth ha = HostAuth.restoreHostAuthWithId(mContext, mAccount.mHostAuthKeyRecv);
mHostAddress = ha.mAddress;
mUserName = ha.mLogin;
@ -982,6 +951,7 @@ public class EasSyncService extends AbstractSyncService {
// Whether or not we're the account mailbox
boolean accountMailbox = false;
try {
mDeviceId = SyncManager.getDeviceId();
if (mMailbox == null || mAccount == null) {
return;
} else if (mMailbox.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
@ -1020,9 +990,6 @@ public class EasSyncService extends AbstractSyncService {
// If this is the account mailbox, wake up SyncManager
// Because this box has a "push" interval, it will be restarted immediately
// which will cause the folder list to be reloaded...
if (accountMailbox) {
SyncManager.kick();
}
try {
int status;
switch (mExitStatus) {
@ -1054,6 +1021,11 @@ public class EasSyncService extends AbstractSyncService {
} else {
userLog(mMailbox.mDisplayName + ": stopped thread finished.");
}
}
// Make sure this gets restarted...
if (accountMailbox) {
SyncManager.kick("account mailbox stopped");
}
}
}
}

View File

@ -33,6 +33,7 @@ import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -53,6 +54,13 @@ import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -86,6 +94,11 @@ public class SyncManager extends Service implements Runnable {
public static final int SYNC_SERVICE_PART_REQUEST = 5;
public static final int SYNC_KICK = 6;
private static final String WHERE_PUSH_OR_PING_NOT_ACCOUNT_MAILBOX =
MailboxColumns.ACCOUNT_KEY + "=? and " + MailboxColumns.TYPE + "!=" +
Mailbox.TYPE_EAS_ACCOUNT_MAILBOX + " and " + MailboxColumns.SYNC_INTERVAL +
" IN (" + Account.CHECK_INTERVAL_PING + ',' + Account.CHECK_INTERVAL_PUSH + ')';
// Offsets into the syncStatus data for EAS that indicate type, exit status, and change count
// The format is S<type_char>:<exit_char>:<change_count>
public static final int STATUS_TYPE_CHAR = 1;
@ -107,6 +120,7 @@ public class SyncManager extends Service implements Runnable {
String mNextWaitReason;
IEmailServiceCallback mCallback;
ConnectivityReceiver mConnectivityReceiver = null;
String mDeviceId = null;
RemoteCallbackList<IEmailServiceCallback> mCallbackList =
new RemoteCallbackList<IEmailServiceCallback>();
@ -191,7 +205,7 @@ public class SyncManager extends Service implements Runnable {
}
public void updateFolderList(long accountId) throws RemoteException {
reloadFolderList(SyncManager.this, accountId);
reloadFolderList(SyncManager.this, accountId, false);
}
public void setLogging(boolean on) throws RemoteException {
@ -314,7 +328,7 @@ public class SyncManager extends Service implements Runnable {
}
// See if there's anything to do...
kick();
kick("account changed");
}
void collectEasAccounts(Cursor c, ArrayList<Account> accounts) {
@ -378,7 +392,9 @@ public class SyncManager extends Service implements Runnable {
@Override
public void onChange(boolean selfChange) {
// See if there's anything to do...
kick();
if (!selfChange) {
kick("mailbox changed");
}
}
}
@ -413,7 +429,9 @@ public class SyncManager extends Service implements Runnable {
public void onChange(boolean selfChange) {
// A rather blunt instrument here. But we don't have information about the URI that
// triggered this, though it must have been an insert
kick();
if (!selfChange) {
kick(null);
}
}
}
@ -491,9 +509,58 @@ public class SyncManager extends Service implements Runnable {
} else {
log("Attempt to start SyncManager though already started before?");
}
mDeviceId = android.provider.Settings.Secure.getString(getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
}
static public void reloadFolderList(Context context, long accountId) {
/**
* EAS requires a unique device id, so that sync is possible from a variety of different
* devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other
* device that doesn't provide one, we can create it as droid<n> where <n> is system time.
* This would work on a real device as well, but it would be better to use the "real" id if
* it's available
*/
static public synchronized String getDeviceId() throws IOException {
if (INSTANCE == null) {
throw new IOException();
}
// If we've already got the id, return it
if (INSTANCE.mDeviceId != null) {
return INSTANCE.mDeviceId;
}
// Otherwise, we'll read the id file or create one if it's not found
try {
File f = INSTANCE.getFileStreamPath("deviceName");
BufferedReader rdr = null;
String id;
if (f.exists() && f.canRead()) {
rdr = new BufferedReader(new FileReader(f), 128);
id = rdr.readLine();
rdr.close();
return id;
} else if (f.createNewFile()) {
BufferedWriter w = new BufferedWriter(new FileWriter(f), 128);
id = "droid" + System.currentTimeMillis();
w.write(id);
w.close();
return id;
}
} catch (FileNotFoundException e) {
// We'll just use the default below
Log.e(TAG, "Can't get device name");
} catch (IOException e) {
// We'll just use the default below
Log.e(TAG, "Can't get device name");
}
throw new IOException();
}
static public void reloadFolderList(Context context, long accountId, boolean force) {
Cursor c = context.getContentResolver().query(Mailbox.CONTENT_URI,
Mailbox.CONTENT_PROJECTION, MailboxColumns.ACCOUNT_KEY + "=? AND " +
MailboxColumns.TYPE + "=?",
@ -505,9 +572,18 @@ public class SyncManager extends Service implements Runnable {
Mailbox m = new Mailbox().restore(c);
String syncKey = m.mSyncKey;
// No need to reload the list if we don't have one
if (syncKey == null || syncKey.equals("0")) {
if (!force && (syncKey == null || syncKey.equals("0"))) {
return;
}
// Change all ping/push boxes to push/hold
ContentValues cv = new ContentValues();
cv.put(Mailbox.SYNC_INTERVAL, Account.CHECK_INTERVAL_PUSH_HOLD);
context.getContentResolver().update(Mailbox.CONTENT_URI, cv,
WHERE_PUSH_OR_PING_NOT_ACCOUNT_MAILBOX,
new String[] {Long.toString(accountId)});
INSTANCE.log("Set push/ping boxes to push/hold");
long id = m.mId;
AbstractSyncService svc = INSTANCE.mServiceMap.get(id);
// Tell the service we're done
@ -522,7 +598,7 @@ public class SyncManager extends Service implements Runnable {
// Abandon the service
INSTANCE.mServiceMap.remove(id);
// And have it start naturally
kick();
kick("reload folder list");
}
}
}
@ -542,7 +618,7 @@ public class SyncManager extends Service implements Runnable {
if (INSTANCE != null) {
AccountObserver obs = INSTANCE.mAccountObserver;
obs.stopAccountSyncs(acctId, false);
obs.addAccountMailbox(acctId);
//obs.addAccountMailbox(acctId);
}
}
@ -550,7 +626,9 @@ public class SyncManager extends Service implements Runnable {
synchronized (mWakeLocks) {
Boolean lock = mWakeLocks.get(id);
if (lock == null) {
INSTANCE.log("+WakeLock requested for " + alarmOwner(id));
if (id > 0) {
INSTANCE.log("+WakeLock requested for " + alarmOwner(id));
}
if (mWakeLock == null) {
PowerManager pm = (PowerManager)INSTANCE
.getSystemService(Context.POWER_SERVICE);
@ -567,7 +645,9 @@ public class SyncManager extends Service implements Runnable {
synchronized (mWakeLocks) {
Boolean lock = mWakeLocks.get(id);
if (lock != null) {
INSTANCE.log("+WakeLock not needed for " + alarmOwner(id));
if (id > 0) {
INSTANCE.log("+WakeLock not needed for " + alarmOwner(id));
}
mWakeLocks.remove(id);
if (mWakeLocks.isEmpty()) {
if (mWakeLock != null) {
@ -613,7 +693,7 @@ public class SyncManager extends Service implements Runnable {
AlarmManager alarmManager = (AlarmManager)INSTANCE
.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millis, pi);
INSTANCE.log("+Alarm set for " + alarmOwner(id) + ", " + millis + "ms");
INSTANCE.log("+Alarm set for " + alarmOwner(id) + ", " + millis/1000 + "s");
}
}
}
@ -640,7 +720,7 @@ public class SyncManager extends Service implements Runnable {
static public void ping(long id) {
if (id < 0) {
kick();
kick("ping SyncManager");
} else {
AbstractSyncService service = INSTANCE.mServiceMap.get(id);
if (service != null) {
@ -677,12 +757,12 @@ public class SyncManager extends Service implements Runnable {
State state = a.getState();
if (state == State.CONNECTED) {
info += " CONNECTED";
kick();
kick("connected");
} else if (state == State.CONNECTING) {
info += " CONNECTING";
} else if (state == State.DISCONNECTED) {
info += " DISCONNECTED";
kick();
kick("disconnected");
} else if (state == State.DISCONNECTING) {
info += " DISCONNECTING";
} else if (state == State.SUSPENDED) {
@ -827,19 +907,26 @@ public class SyncManager extends Service implements Runnable {
long checkMailboxes () {
// First, see if any running mailboxes have been deleted
ArrayList<Long> deadMailboxes = new ArrayList<Long>();
ArrayList<Long> deletedMailboxes = new ArrayList<Long>();
synchronized (mSyncToken) {
for (long mailboxId: mServiceMap.keySet()) {
Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
if (m == null) {
deadMailboxes.add(mailboxId);
log("Stopping sync for mailbox " + mailboxId + "; record not found.");
deletedMailboxes.add(mailboxId);
}
}
}
// If so, stop them
for (Long mailboxId: deadMailboxes) {
stopManualSync(mailboxId);
// If so, stop them or remove them from the map
for (Long mailboxId: deletedMailboxes) {
AbstractSyncService svc = mServiceMap.get(mailboxId);
boolean alive = svc.mThread.isAlive();
log("Deleted mailbox: " + svc.mMailboxName);
if (alive) {
stopManualSync(mailboxId);
} else {
log("Removing from serviceMap");
mServiceMap.remove(mailboxId);
}
}
long nextWait = 10*MINS;
@ -938,7 +1025,7 @@ public class SyncManager extends Service implements Runnable {
AbstractSyncService service = INSTANCE.mServiceMap.get(mailboxId);
if (service != null) {
service.mRequestTime = System.currentTimeMillis() + ms;
kick();
kick("service request");
} else {
startManualSync(mailboxId, reason, null);
}
@ -952,9 +1039,11 @@ public class SyncManager extends Service implements Runnable {
if (service != null) {
service.mRequestTime = System.currentTimeMillis();
Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
service.mMailbox = m;
kick();
if (m != null) {
service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
service.mMailbox = m;
kick("service request immediate");
}
}
}
@ -968,7 +1057,7 @@ public class SyncManager extends Service implements Runnable {
if (service == null) {
service = startManualSync(mailboxId, SYNC_SERVICE_PART_REQUEST, req);
kick();
kick("part request");
} else {
service.addPartRequest(req);
}
@ -1070,8 +1159,11 @@ public class SyncManager extends Service implements Runnable {
/**
* Wake up SyncManager to check for mailboxes needing service
*/
static public void kick() {
static public void kick(String reason) {
if (INSTANCE != null) {
//if (reason != null) {
// INSTANCE.log("Kick: " + reason);
//}
synchronized (INSTANCE) {
INSTANCE.notify();
}
@ -1124,7 +1216,7 @@ public class SyncManager extends Service implements Runnable {
} else {
errorMap.put(mailboxId, INSTANCE.new SyncError(exitStatus, false));
}
kick();
kick("i/o error in sync");
break;
case AbstractSyncService.EXIT_LOGIN_FAILURE:
case AbstractSyncService.EXIT_EXCEPTION:
@ -1136,7 +1228,7 @@ public class SyncManager extends Service implements Runnable {
public static void shutdown() {
INSTANCE.mStop = true;
kick();
kick("shutdown");
INSTANCE.stopSelf();
}

View File

@ -83,6 +83,8 @@ public abstract class AbstractSyncParser extends Parser {
public boolean parse() throws IOException {
int status;
boolean moreAvailable = false;
int interval = mMailbox.mSyncInterval;
// If we're not at the top of the xml tree, throw an exception
if (nextTag(START_DOCUMENT) != Tags.SYNC_SYNC) {
throw new IOException();
@ -110,7 +112,7 @@ public abstract class AbstractSyncParser extends Parser {
} else if (status == 8) {
// This is Bad; it means the server doesn't recognize the serverId it
// sent us. What's needed is a refresh of the folder list.
SyncManager.reloadFolderList(mContext, mAccount.mId);
SyncManager.reloadFolderList(mContext, mAccount.mId, true);
}
// TODO Look at other error codes and consider what's to be done
}
@ -121,8 +123,9 @@ public abstract class AbstractSyncParser extends Parser {
} else if (tag == Tags.SYNC_MORE_AVAILABLE) {
moreAvailable = true;
} else if (tag == Tags.SYNC_SYNC_KEY) {
if (mMailbox.mSyncKey.equals("0"))
if (mMailbox.mSyncKey.equals("0")) {
moreAvailable = true;
}
String newKey = getValue();
mService.userLog("Parsed key for " + mMailbox.mDisplayName + ": " + newKey);
mMailbox.mSyncKey = newKey;
@ -135,16 +138,18 @@ public abstract class AbstractSyncParser extends Parser {
}
}
synchronized (mService.getSynchronizer()) {
if (!mService.isStopped()) {
// Make sure we save away the new syncKey, syncFrequency, etc.
ContentValues cv = new ContentValues();
cv.put(MailboxColumns.SYNC_KEY, mMailbox.mSyncKey);
cv.put(MailboxColumns.SYNC_INTERVAL, mMailbox.mSyncInterval);
mMailbox.update(mContext, cv);
mService.userLog(mMailbox.mDisplayName + " SyncKey saved as: " + mMailbox.mSyncKey);
// If the sync interval has changed, save the change
if (mMailbox.mSyncInterval != interval) {
synchronized (mService.getSynchronizer()) {
if (!mService.isStopped()) {
// Make sure we save away the new syncFrequency
ContentValues cv = new ContentValues();
cv.put(MailboxColumns.SYNC_INTERVAL, mMailbox.mSyncInterval);
mMailbox.update(mContext, cv);
}
}
}
// Let the caller know that there's more to do
return moreAvailable;
}

View File

@ -670,8 +670,6 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
ContentValues cv = new ContentValues();
cv.put(MailboxColumns.SYNC_KEY, mMailbox.mSyncKey);
Mailbox.update(mContext, Mailbox.CONTENT_URI, mMailbox.mId, cv);
mService.userLog("Contacts SyncKey confirmed as: " + mMailbox.mSyncKey);
}
}

View File

@ -442,15 +442,15 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
if (mService.isStopped()) return;
try {
mService.mContext.getContentResolver()
.applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
.applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
mService.userLog(mMailbox.mDisplayName +
" SyncKey saved as: " + mMailbox.mSyncKey);
} catch (RemoteException e) {
// There is nothing to be done here; fail by returning null
} catch (OperationApplicationException e) {
// There is nothing to be done here; fail by returning null
}
}
mService.userLog(mMailbox.mDisplayName + " SyncKey saved as: " + mMailbox.mSyncKey);
}
}

View File

@ -69,7 +69,10 @@ public class FolderSyncParser extends Parser {
public static final List<Integer> mValidFolderTypes = Arrays.asList(INBOX_TYPE, DRAFTS_TYPE,
DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE, CALENDAR_TYPE, CONTACTS_TYPE);
private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
public static final String ALL_BUT_ACCOUNT_MAILBOX = MailboxColumns.ACCOUNT_KEY + "=? and " +
MailboxColumns.TYPE + "!=" + Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;
private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
MailboxColumns.ACCOUNT_KEY + "=?";
private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME +
@ -117,8 +120,8 @@ public class FolderSyncParser extends Parser {
if (status == Eas.FOLDER_STATUS_INVALID_KEY) {
mAccount.mSyncKey = "0";
mService.errorLog("Bad sync key; RESET and delete all folders");
mContentResolver.delete(Mailbox.CONTENT_URI,
MailboxColumns.ACCOUNT_KEY + '=' + mAccountId, null);
mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
new String[] {Long.toString(mAccountId)});
// Stop existing syncs and reconstruct _main
SyncManager.folderListReloaded(mAccountId);
res = true;