diff --git a/emailcommon/src/com/android/emailcommon/service/EmailServiceStatus.java b/emailcommon/src/com/android/emailcommon/service/EmailServiceStatus.java index 8cd577c8d..fb0f88ae2 100644 --- a/emailcommon/src/com/android/emailcommon/service/EmailServiceStatus.java +++ b/emailcommon/src/com/android/emailcommon/service/EmailServiceStatus.java @@ -17,10 +17,20 @@ package com.android.emailcommon.service; +import android.content.ContentResolver; +import android.net.Uri; +import android.os.Bundle; + /** - * Definitions of service status codes returned to IEmailServiceCallback's status method + * Definitions of service status codes returned to IEmailServiceCallback's status method. + * + * Now that all sync requests are sent through the system SyncManager, there's no way to specify the + * {@link IEmailServiceCallback} to {@link ContentResolver#requestSync} since all we have is a + * {@link Bundle}. Instead, the caller requesting the sync specifies values with which to call + * {@link ContentResolver#call} in order to receive a callback, and the + * {@link android.content.ContentProvider} must handle this call. */ -public interface EmailServiceStatus { +public abstract class EmailServiceStatus { public static final int SUCCESS = 0; public static final int IN_PROGRESS = 1; @@ -40,4 +50,43 @@ public interface EmailServiceStatus { // Client certificates used to authenticate cannot be retrieved from the system. public static final int CLIENT_CERTIFICATE_ERROR = 0x21; + + // Keys for the sync extras Bundle that specify the callback. + public static final String SYNC_EXTRAS_CALLBACK_URI = "callback_uri"; + public static final String SYNC_EXTRAS_CALLBACK_METHOD = "callback_method"; + public static final String SYNC_EXTRAS_CALLBACK_ARG = "callback_arg"; + + // Keys for the status Bundle sent to the callback. + public static final String SYNC_STATUS_TYPE = "type"; + public static final String SYNC_STATUS_ID = "id"; + public static final String SYNC_STATUS_CODE = "status_code"; + public static final String SYNC_STATUS_PROGRESS = "progress"; + + // Values for the SYNC_STATUS_TYPE to specify what kind of sync status we're returning. + public static final int SYNC_STATUS_TYPE_MAILBOX = 0; + + /** + * If the sync extras specify a callback, then notify the sync requester of the mailbox's + * sync status. This function is for use by the + * {@link android.content.AbstractThreadedSyncAdapter}. + * @param cr A ContentResolver. + * @param syncExtras The extras provided to the sync request. + * @param mailboxId The mailbox whose status is changing. + * @param statusCode The status code for this mailbox. + * @param progress The progress of this mailbox's sync. + */ + public static void syncMailboxStatus(final ContentResolver cr, final Bundle syncExtras, + final long mailboxId, final int statusCode, final int progress) { + final String callbackUri = syncExtras.getString(SYNC_EXTRAS_CALLBACK_URI); + final String callbackMethod = syncExtras.getString(SYNC_EXTRAS_CALLBACK_METHOD); + if (callbackUri != null && callbackMethod != null) { + final String callbackArg = syncExtras.getString(SYNC_EXTRAS_CALLBACK_ARG, ""); + final Bundle statusExtras = new Bundle(4); + statusExtras.putInt(SYNC_STATUS_TYPE, SYNC_STATUS_TYPE_MAILBOX); + statusExtras.putLong(SYNC_STATUS_ID, mailboxId); + statusExtras.putInt(SYNC_STATUS_CODE, statusCode); + statusExtras.putInt(SYNC_STATUS_PROGRESS, progress); + cr.call(Uri.parse(callbackUri), callbackMethod, callbackArg, statusExtras); + } + } } diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 384f52e6d..556f967b6 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -67,7 +67,6 @@ import com.android.emailcommon.provider.EmailContent.Attachment; import com.android.emailcommon.provider.EmailContent.AttachmentColumns; import com.android.emailcommon.provider.EmailContent.Body; import com.android.emailcommon.provider.EmailContent.BodyColumns; -import com.android.emailcommon.provider.EmailContent.HostAuthColumns; import com.android.emailcommon.provider.EmailContent.MailboxColumns; import com.android.emailcommon.provider.EmailContent.Message; import com.android.emailcommon.provider.EmailContent.MessageColumns; @@ -78,6 +77,7 @@ import com.android.emailcommon.provider.Mailbox; import com.android.emailcommon.provider.Policy; import com.android.emailcommon.provider.QuickResponse; import com.android.emailcommon.service.EmailServiceProxy; +import com.android.emailcommon.service.EmailServiceStatus; import com.android.emailcommon.service.IEmailService; import com.android.emailcommon.service.IEmailServiceCallback; import com.android.emailcommon.service.SearchParams; @@ -93,7 +93,6 @@ import com.android.mail.providers.UIProvider.AccountCursorExtraKeys; import com.android.mail.providers.UIProvider.ConversationPriority; import com.android.mail.providers.UIProvider.ConversationSendingState; import com.android.mail.providers.UIProvider.DraftType; -import com.android.mail.providers.UIProvider.Swipe; import com.android.mail.utils.AttachmentUtils; import com.android.mail.utils.LogUtils; import com.android.mail.utils.MatrixCursorWithCachedColumns; @@ -295,6 +294,8 @@ public class EmailProvider extends ContentProvider { // Query parameter indicating the command came from UIProvider private static final String IS_UIPROVIDER = "is_uiprovider"; + private static final String SYNC_STATUS_CALLBACK_METHOD = "sync_status"; + /** * Wrap the UriMatcher call so we can throw a runtime exception if an unknown Uri is passed in * @param uri the Uri to match @@ -1564,14 +1565,37 @@ public class EmailProvider extends ContentProvider { @Override public Bundle call(String method, String arg, Bundle extras) { LogUtils.d(TAG, "EmailProvider#call(%s, %s)", method, arg); + + // First handle sync status callbacks. + if (TextUtils.equals(method, SYNC_STATUS_CALLBACK_METHOD)) { + final int syncStatusType = extras.getInt(EmailServiceStatus.SYNC_STATUS_TYPE); + switch (syncStatusType) { + case EmailServiceStatus.SYNC_STATUS_TYPE_MAILBOX: + try { + mServiceCallback.syncMailboxStatus( + extras.getLong(EmailServiceStatus.SYNC_STATUS_ID), + extras.getInt(EmailServiceStatus.SYNC_STATUS_CODE), + extras.getInt(EmailServiceStatus.SYNC_STATUS_PROGRESS)); + } catch (RemoteException re) { + // This can't actually happen but I have to pacify the compiler. + } + break; + default: + LogUtils.e(TAG, "Sync status received of unknown type %d", syncStatusType); + break; + } + return null; + } + + // Handle send & save. final Uri accountUri = Uri.parse(arg); final long accountId = Long.parseLong(accountUri.getPathSegments().get(1)); Uri messageUri = null; if (TextUtils.equals(method, UIProvider.AccountCallMethods.SEND_MESSAGE)) { - messageUri = uiSendDraftMessage(accountId, extras); + messageUri = uiSendDraftMessage(accountId, extras); } else if (TextUtils.equals(method, UIProvider.AccountCallMethods.SAVE_MESSAGE)) { - messageUri = uiSaveDraftMessage(accountId, extras); + messageUri = uiSaveDraftMessage(accountId, extras); } final Bundle result; @@ -4150,7 +4174,7 @@ public class EmailProvider extends ContentProvider { private void startSync(final Mailbox mailbox, final int deltaMessageCount) { android.accounts.Account account = getAccountManagerAccount(mailbox.mAccountKey); - Bundle extras = new Bundle(); + Bundle extras = new Bundle(7); extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); @@ -4158,6 +4182,10 @@ public class EmailProvider extends ContentProvider { if (deltaMessageCount != 0) { extras.putInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, deltaMessageCount); } + extras.putString(EmailServiceStatus.SYNC_EXTRAS_CALLBACK_URI, + EmailContent.CONTENT_URI.toString()); + extras.putString(EmailServiceStatus.SYNC_EXTRAS_CALLBACK_METHOD, + SYNC_STATUS_CALLBACK_METHOD); ContentResolver.requestSync(account, EmailContent.AUTHORITY, extras); }