From 48b14fde961ef57103f7a31196254e357987f203 Mon Sep 17 00:00:00 2001 From: Yu Ping Hu Date: Wed, 24 Jul 2013 17:00:35 -0700 Subject: [PATCH] Fix all periodic syncs on upgrade. Bug: 9844218 Change-Id: Ibacb309752b076faa3f96b5ad57dc121efd79bcb --- .../EmailBroadcastProcessorService.java | 93 ++++++++++++++++++- .../email/service/EmailServiceUtils.java | 3 +- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/com/android/email/service/EmailBroadcastProcessorService.java b/src/com/android/email/service/EmailBroadcastProcessorService.java index 092d7e8a3..0873cac31 100644 --- a/src/com/android/email/service/EmailBroadcastProcessorService.java +++ b/src/com/android/email/service/EmailBroadcastProcessorService.java @@ -24,9 +24,14 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.PeriodicSync; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; +import android.os.Bundle; +import android.provider.CalendarContract; +import android.provider.ContactsContract; +import android.text.format.DateUtils; import com.android.email.Preferences; import com.android.email.R; @@ -36,11 +41,15 @@ import com.android.email.provider.AccountReconciler; import com.android.emailcommon.Logging; import com.android.emailcommon.VendorPolicyLoader; import com.android.emailcommon.provider.Account; +import com.android.emailcommon.provider.EmailContent; import com.android.emailcommon.provider.EmailContent.AccountColumns; import com.android.emailcommon.provider.HostAuth; import com.android.mail.utils.LogUtils; +import com.google.common.collect.Maps; -import java.util.HashMap; +import java.util.Collections; +import java.util.List; +import java.util.Map; /** * The service that really handles broadcast intents on a worker thread. @@ -138,7 +147,7 @@ public class EmailBroadcastProcessorService extends IntentService { } private void updateAccountManagerAccountsOfType(final String amAccountType, - final HashMap protocolMap) { + final Map protocolMap) { final android.accounts.Account[] amAccounts = AccountManager.get(this).getAccountsByType(amAccountType); @@ -147,6 +156,76 @@ public class EmailBroadcastProcessorService extends IntentService { } } + /** + * Delete all periodic syncs for an account. + * @param amAccount The account for which to disable syncs. + * @param authority The authority for which to disable syncs. + */ + private void removePeriodicSyncs(final android.accounts.Account amAccount, + final String authority) { + final List syncs = + ContentResolver.getPeriodicSyncs(amAccount, authority); + for (final PeriodicSync sync : syncs) { + ContentResolver.removePeriodicSync(amAccount, authority, sync.extras); + } + } + + /** + * Remove all existing periodic syncs for an account type, and add the necessary syncs. + * @param amAccountType The account type to handle. + * @param syncIntervals The map of all account addresses to sync intervals in the DB. + */ + private void fixPeriodicSyncs(final String amAccountType, + final Map syncIntervals) { + final android.accounts.Account[] amAccounts = + AccountManager.get(this).getAccountsByType(amAccountType); + for (android.accounts.Account amAccount : amAccounts) { + // First delete existing periodic syncs. + removePeriodicSyncs(amAccount, EmailContent.AUTHORITY); + removePeriodicSyncs(amAccount, CalendarContract.AUTHORITY); + removePeriodicSyncs(amAccount, ContactsContract.AUTHORITY); + + // Add back a sync for this account if necessary (i.e. the account has a positive + // sync interval in the DB). This assumes that the email app requires unique email + // addresses for each account, which is currently the case. + final Integer syncInterval = syncIntervals.get(amAccount.name); + if (syncInterval != null && syncInterval > 0) { + // Sync interval is stored in minutes in DB, but we want the value in seconds. + ContentResolver.addPeriodicSync(amAccount, EmailContent.AUTHORITY, Bundle.EMPTY, + syncInterval * DateUtils.MINUTE_IN_MILLIS / DateUtils.SECOND_IN_MILLIS); + } + } + } + + /** Projection used for getting sync intervals for all accounts. */ + private static final String[] ACCOUNT_SYNC_INTERVAL_PROJECTION = + { AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_INTERVAL }; + private static final int ACCOUNT_SYNC_INTERVAL_ADDRESS_COLUMN = 0; + private static final int ACCOUNT_SYNC_INTERVAL_INTERVAL_COLUMN = 1; + + /** + * Get the sync interval for all accounts, as stored in the DB. + * @return The map of all sync intervals by account email address. + */ + private Map getSyncIntervals() { + final Cursor c = getContentResolver().query(Account.CONTENT_URI, + ACCOUNT_SYNC_INTERVAL_PROJECTION, null, null, null); + if (c != null) { + final Map periodicSyncs = + Maps.newHashMapWithExpectedSize(c.getCount()); + try { + while (c.moveToNext()) { + periodicSyncs.put(c.getString(ACCOUNT_SYNC_INTERVAL_ADDRESS_COLUMN), + c.getInt(ACCOUNT_SYNC_INTERVAL_INTERVAL_COLUMN)); + } + } finally { + c.close(); + } + return periodicSyncs; + } + return Collections.emptyMap(); + } + private void onAppUpgrade() { // TODO: Only do this for Email2Google. // When upgrading to Email2Google, we need to essentially rename the account manager @@ -155,7 +234,7 @@ public class EmailBroadcastProcessorService extends IntentService { // name, and from protocol name + "_type" to new account manager type name. (Email1 did // not use distinct account manager types for POP and IMAP, but Email2 does, hence this // weird mapping.) - final HashMap protocolMap = new HashMap(); + final Map protocolMap = Maps.newHashMapWithExpectedSize(4); protocolMap.put("imap", getString(R.string.protocol_legacy_imap)); protocolMap.put("pop3", getString(R.string.protocol_pop3)); protocolMap.put("imap_type", getString(R.string.account_manager_type_legacy_imap)); @@ -171,6 +250,14 @@ public class EmailBroadcastProcessorService extends IntentService { disableComponent(LegacyEmailAuthenticatorService.class); disableComponent(LegacyEasAuthenticatorService.class); + // Fix periodic syncs. + final Map syncIntervals = getSyncIntervals(); + final List serviceList = + EmailServiceUtils.getServiceInfoList(this); + for (final EmailServiceUtils.EmailServiceInfo service : serviceList) { + fixPeriodicSyncs(service.accountType, syncIntervals); + } + // Disable the upgrade broadcast receiver now that we're fully upgraded. disableComponent(EmailUpgradeBroadcastReceiver.class); } diff --git a/src/com/android/email/service/EmailServiceUtils.java b/src/com/android/email/service/EmailServiceUtils.java index ce95a188f..bb78b92e5 100644 --- a/src/com/android/email/service/EmailServiceUtils.java +++ b/src/com/android/email/service/EmailServiceUtils.java @@ -62,7 +62,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -282,7 +281,7 @@ public class EmailServiceUtils { } public static void updateAccountManagerType(Context context, - android.accounts.Account amAccount, final HashMap protocolMap) { + android.accounts.Account amAccount, final Map protocolMap) { final ContentResolver resolver = context.getContentResolver(); final Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?", new String[] { amAccount.name }, null);