Add support for the syncMailboxStatus/syncMailboxListStatus callback

* Allows UI to show proper progress indications depending on the status
  of a particular mailbox (running, finished, or error state)
This commit is contained in:
Marc Blank 2009-07-30 13:08:06 -07:00
parent 90ed7a4e23
commit 85ef72b2ce
3 changed files with 110 additions and 20 deletions

View File

@ -81,7 +81,7 @@ public class EasSyncService extends InteractiveSyncService {
MailboxColumns.SYNC_INTERVAL + " IN (" + Account.CHECK_INTERVAL_PING + MailboxColumns.SYNC_INTERVAL + " IN (" + Account.CHECK_INTERVAL_PING +
',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.SERVER_ID + "!=\"" + ',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.SERVER_ID + "!=\"" +
Eas.ACCOUNT_MAILBOX + '\"'; Eas.ACCOUNT_MAILBOX + '\"';
static private final int CHUNK_SIZE = 16 * 1024; static private final int CHUNK_SIZE = 16 * 1024;
// Reasonable default // Reasonable default
@ -136,6 +136,7 @@ public class EasSyncService extends InteractiveSyncService {
mStop = true; mStop = true;
} }
@Override
public int getSyncStatus() { public int getSyncStatus() {
return 0; return 0;
} }
@ -143,6 +144,7 @@ public class EasSyncService extends InteractiveSyncService {
/* (non-Javadoc) /* (non-Javadoc)
* @see com.android.exchange.SyncService#validateAccount(java.lang.String, java.lang.String, java.lang.String, int, boolean, android.content.Context) * @see com.android.exchange.SyncService#validateAccount(java.lang.String, java.lang.String, java.lang.String, int, boolean, android.content.Context)
*/ */
@Override
public void validateAccount(String hostAddress, String userName, String password, int port, public void validateAccount(String hostAddress, String userName, String password, int port,
boolean ssl, Context context) throws MessagingException { boolean ssl, Context context) throws MessagingException {
try { try {
@ -217,23 +219,17 @@ public class EasSyncService extends InteractiveSyncService {
private void doStatusCallback(long messageId, long attachmentId, int status) { private void doStatusCallback(long messageId, long attachmentId, int status) {
try { try {
IEmailServiceCallback cb = SyncManager.getCallback(); SyncManager.callback().loadAttachmentStatus(messageId, attachmentId, status, 0);
if (cb != null) { } catch (RemoteException e) {
cb.loadAttachmentStatus(messageId, attachmentId, status, 0);
}
} catch (RemoteException e2) {
// No danger if the client is no longer around // No danger if the client is no longer around
} }
} }
private void doProgressCallback(long messageId, long attachmentId, int progress) { private void doProgressCallback(long messageId, long attachmentId, int progress) {
try { try {
IEmailServiceCallback cb = SyncManager.getCallback(); SyncManager.callback().loadAttachmentStatus(messageId, attachmentId,
if (cb != null) { EmailServiceStatus.IN_PROGRESS, progress);
cb.loadAttachmentStatus(messageId, attachmentId, EmailServiceStatus.IN_PROGRESS, } catch (RemoteException e) {
progress);
}
} catch (RemoteException e2) {
// No danger if the client is no longer around // No danger if the client is no longer around
} }
} }
@ -371,14 +367,14 @@ public class EasSyncService extends InteractiveSyncService {
return us; return us;
} }
private HttpURLConnection setupEASCommand(String method, String cmd, String extra) private HttpURLConnection setupEASCommand(String method, String cmd, String extra)
throws IOException { throws IOException {
try { try {
String us = makeUriString(cmd, extra); String us = makeUriString(cmd, extra);
URL u = new URL(us); URL u = new URL(us);
HttpURLConnection uc = (HttpURLConnection)u.openConnection(); HttpURLConnection uc = (HttpURLConnection)u.openConnection();
HttpURLConnection.setFollowRedirects(true); HttpURLConnection.setFollowRedirects(true);
if (mSsl) { if (mSsl) {
((HttpsURLConnection)uc).setHostnameVerifier(new AllowAllHostnameVerifier()); ((HttpsURLConnection)uc).setHostnameVerifier(new AllowAllHostnameVerifier());
} }
@ -431,7 +427,16 @@ public class EasSyncService extends InteractiveSyncService {
* @throws EasParserException * @throws EasParserException
*/ */
public void runMain() throws IOException, EasParserException { public void runMain() throws IOException, EasParserException {
// Initialize exit status to success
mExitStatus = EmailServiceStatus.SUCCESS;
try { try {
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, EmailServiceStatus.IN_PROGRESS, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
if (mAccount.mSyncKey == null) { if (mAccount.mSyncKey == null) {
mAccount.mSyncKey = "0"; mAccount.mSyncKey = "0";
userLog("Account syncKey RESET"); userLog("Account syncKey RESET");
@ -487,10 +492,20 @@ public class EasSyncService extends InteractiveSyncService {
} else if (encoding.equalsIgnoreCase("chunked")) { } else if (encoding.equalsIgnoreCase("chunked")) {
// TODO We don't handle this yet // TODO We don't handle this yet
} }
} else if (code == HttpURLConnection.HTTP_UNAUTHORIZED ||
code == HttpURLConnection.HTTP_FORBIDDEN) {
mExitStatus = AbstractSyncService.EXIT_LOGIN_FAILURE;
} else { } else {
userLog("FolderSync response error: " + code); userLog("FolderSync response error: " + code);
} }
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, mExitStatus, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
// Wait for push notifications. // Wait for push notifications.
String threadName = Thread.currentThread().getName(); String threadName = Thread.currentThread().getName();
try { try {
@ -504,7 +519,15 @@ public class EasSyncService extends InteractiveSyncService {
} }
} }
} }
} catch (MalformedURLException e) { } catch (IOException e) {
// We catch this here to send the folder sync status callback
// A folder sync failed callback will get sent from run()
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, EmailServiceStatus.CONNECTION_ERROR, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
throw new IOException(); throw new IOException();
} }
} }
@ -850,6 +873,12 @@ public class EasSyncService extends InteractiveSyncService {
mUserName = ha.mLogin; mUserName = ha.mLogin;
mPassword = ha.mPassword; mPassword = ha.mPassword;
try {
SyncManager.callback().syncMailboxStatus(mMailboxId, EmailServiceStatus.IN_PROGRESS, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
// Make sure account and mailbox are always the latest from the database // Make sure account and mailbox are always the latest from the database
mAccount = Account.restoreAccountWithId(mContext, mAccount.mId); mAccount = Account.restoreAccountWithId(mContext, mAccount.mId);
mMailbox = Mailbox.restoreMailboxWithId(mContext, mMailbox.mId); mMailbox = Mailbox.restoreMailboxWithId(mContext, mMailbox.mId);
@ -887,6 +916,27 @@ public class EasSyncService extends InteractiveSyncService {
} finally { } finally {
userLog(mMailbox.mDisplayName + ": sync finished"); userLog(mMailbox.mDisplayName + ": sync finished");
SyncManager.done(this); SyncManager.done(this);
try {
int status;
switch (mExitStatus) {
case EXIT_IO_ERROR:
status = EmailServiceStatus.CONNECTION_ERROR;
break;
case EXIT_DONE:
status = EmailServiceStatus.SUCCESS;
break;
case EXIT_LOGIN_FAILURE:
status = EmailServiceStatus.LOGIN_FAILED;
break;
default:
status = EmailServiceStatus.REMOTE_EXCEPTION;
break;
}
SyncManager.callback().syncMailboxStatus(mMailboxId, status, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
} }
} }
} }

View File

@ -30,6 +30,7 @@ public interface EmailServiceStatus {
public static final int FOLDER_NOT_RENAMED = 0x13; public static final int FOLDER_NOT_RENAMED = 0x13;
public static final int FOLDER_NOT_CREATED = 0x14; public static final int FOLDER_NOT_CREATED = 0x14;
public static final int REMOTE_EXCEPTION = 0x15; public static final int REMOTE_EXCEPTION = 0x15;
public static final int LOGIN_FAILED = 0x16;
// Maybe we should automatically retry these? // Maybe we should automatically retry these?
public static final int CONNECTION_ERROR = 0x20; public static final int CONNECTION_ERROR = 0x20;

View File

@ -100,6 +100,48 @@ public class SyncManager extends Service implements Runnable {
new HashMap<Long, PendingIntent>(); new HashMap<Long, PendingIntent>();
static private WakeLock mWakeLock = null; static private WakeLock mWakeLock = null;
/**
* Proxy that can be used by various sync adapters to call into SyncManager's callback system.
* Used this way: SyncManager.callback().callbackMethod(args...);
* The proxy wraps checking for existence of a SyncManager instance and an active callback.
* Failures of these callbacks can be safely ignored.
*/
static private final IEmailServiceCallback.Stub sCallbackProxy =
new IEmailServiceCallback.Stub() {
public void loadAttachmentStatus(long messageId, long attachmentId, int statusCode,
int progress) throws RemoteException {
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.loadAttachmentStatus(messageId, attachmentId, statusCode, progress);
}
}
public void sendMessageStatus(long messageId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.sendMessageStatus(messageId, statusCode, progress);
}
}
public void syncMailboxListStatus(long accountId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.syncMailboxListStatus(accountId, statusCode, progress);
}
}
public void syncMailboxStatus(long mailboxId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.syncMailboxListStatus(mailboxId, statusCode, progress);
}
}
};
/** /**
* Create the binder for EmailService implementation here. These are the calls that are * Create the binder for EmailService implementation here. These are the calls that are
* defined in AbstractSyncService. Only validate is now implemented; loadAttachment currently * defined in AbstractSyncService. Only validate is now implemented; loadAttachment currently
@ -372,11 +414,8 @@ public class SyncManager extends Service implements Runnable {
} }
} }
static public IEmailServiceCallback getCallback() { static public IEmailServiceCallback callback() {
if (INSTANCE != null) { return sCallbackProxy;
return INSTANCE.mCallback;
}
return null;
} }
static public AccountList getAccountList() { static public AccountList getAccountList() {