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:
parent
b9d6ba11c7
commit
fc579d4477
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue