From 03ecce7da8f220e31314bc25ebff96841d24787f Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Thu, 20 Aug 2009 14:38:12 -0700 Subject: [PATCH] Integrate further with the system SyncManager/AccountManager system * Look for, and act on, changes to sync settings via SyncManager/AccountManager * Look for, and act on, deletions from within AccountManager (tested) --- AndroidManifest.xml | 1 + src/com/android/exchange/SyncManager.java | 108 +++++++++++++++++++++- 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 652ba03af..4423c69d2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -23,6 +23,7 @@ + diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java index c36d914ea..75126d392 100644 --- a/src/com/android/exchange/SyncManager.java +++ b/src/com/android/exchange/SyncManager.java @@ -31,15 +31,18 @@ import com.android.email.provider.EmailContent.SyncColumns; import com.android.exchange.utility.FileLogger; import android.accounts.AccountManager; +import android.accounts.OnAccountsUpdatedListener; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SyncStatusObserver; import android.database.ContentObserver; import android.database.Cursor; import android.net.ConnectivityManager; @@ -54,6 +57,7 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.PowerManager.WakeLock; +import android.provider.ContactsContract; import android.util.Log; import java.io.BufferedReader; @@ -163,6 +167,8 @@ public class SyncManager extends Service implements Runnable { private MailboxObserver mMailboxObserver; private SyncedMessageObserver mSyncedMessageObserver; private MessageObserver mMessageObserver; + private EasSyncStatusObserver mSyncStatusObserver; + private EasAccountsUpdatedListener mAccountsUpdatedListener = new EasAccountsUpdatedListener(); private Handler mHandler = new Handler(); private ContentResolver mResolver; @@ -573,6 +579,23 @@ public class SyncManager extends Service implements Runnable { } } + public class EasSyncStatusObserver implements SyncStatusObserver { + public void onStatusChanged(int which) { + // We ignore the argument (we can only get called in one case - when settings change) + // TODO Go through each account and see if sync is enabled and/or automatic for + // the Contacts authority, and set syncInterval accordingly. Then kick ourselves. + if (INSTANCE != null) { + checkPIMSyncSettings(); + } + } + } + + public class EasAccountsUpdatedListener implements OnAccountsUpdatedListener { + public void onAccountsUpdated(android.accounts.Account[] accounts) { + checkWithAccountManager(); + } + } + static public void smLog(String str) { if (INSTANCE != null) { INSTANCE.log(str); @@ -646,7 +669,7 @@ public class SyncManager extends Service implements Runnable { mMailboxObserver = new MailboxObserver(mHandler); mSyncedMessageObserver = new SyncedMessageObserver(mHandler); mMessageObserver = new MessageObserver(mHandler); - + mSyncStatusObserver = new EasSyncStatusObserver(); try { mDeviceId = getDeviceId(); } catch (IOException e) { @@ -900,6 +923,82 @@ public class SyncManager extends Service implements Runnable { } } + /** + * See if we need to change the syncInterval for any of our PIM mailboxes based on changes + * to settings in the AccountManager (sync settings). + * This code is called 1) when SyncManager starts, and 2) when SyncManager is running and there + * are changes made (this is detected via a SyncStatusObserver) + */ + private void checkPIMSyncSettings() { + ContentValues cv = new ContentValues(); + // For now, just Contacts + // First, walk through our list of accounts + List easAccounts = getAccountList(); + for (Account easAccount: easAccounts) { + // Find the contacts mailbox + long contactsId = + Mailbox.findMailboxOfType(this, easAccount.mId, Mailbox.TYPE_CONTACTS); + // Presumably there is one, but if not, it's ok. Just move on... + if (contactsId != Mailbox.NO_MAILBOX) { + // Create an AccountManager style Account + android.accounts.Account acct = + new android.accounts.Account(easAccount.mEmailAddress, + Eas.ACCOUNT_MANAGER_TYPE); + // Get the Contacts mailbox; this happens rarely so it's ok to get it all + Mailbox contacts = Mailbox.restoreMailboxWithId(this, contactsId); + int syncInterval = contacts.mSyncInterval; + // If we're syncable, look further... + if (ContentResolver.getIsSyncable(acct, ContactsContract.AUTHORITY) > 0) { + // If we're supposed to sync automatically (push), set to push if it's not + if (ContentResolver.getSyncAutomatically(acct, ContactsContract.AUTHORITY)) { + if (syncInterval == Mailbox.CHECK_INTERVAL_NEVER || syncInterval > 0) { + log("Sync setting: Contacts for " + acct.name + " changed to push"); + cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_PUSH); + } + // If we're NOT supposed to push, and we're not set up that way, change it + } else if (syncInterval != Mailbox.CHECK_INTERVAL_NEVER) { + log("Sync setting: Contacts for " + acct.name + " changed to manual"); + cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_NEVER); + } + // If not, set it to never check + } else if (syncInterval != Mailbox.CHECK_INTERVAL_NEVER) { + log("Sync setting: Contacts for " + acct.name + " changed to manual"); + cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_NEVER); + } + + // If we've made a change, update the Mailbox, and kick + if (cv.containsKey(MailboxColumns.SYNC_INTERVAL)) { + mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, contactsId), + cv,null, null); + kick("sync settings change"); + } + } + } + } + + private void checkWithAccountManager() { + android.accounts.Account[] accts = + AccountManager.get(this).getAccountsByType(Eas.ACCOUNT_MANAGER_TYPE); + List easAccounts = getAccountList(); + for (Account easAccount: easAccounts) { + String accountName = easAccount.mEmailAddress; + boolean found = false; + for (android.accounts.Account acct: accts) { + if (acct.name.equalsIgnoreCase(accountName)) { + found = true; + break; + } + } + if (!found) { + // This account has been deleted in the AccountManager! + log("Account deleted in AccountManager; deleting from provider: " + accountName); + // TODO This will orphan downloaded attachments; need to handle this + mResolver.delete(ContentUris.withAppendedId(Account.CONTENT_URI, easAccount.mId), + null, null); + } + } + } + private void releaseConnectivityLock(String reason) { // Clear our sync error map when we get connected mSyncErrorMap.clear(); @@ -1048,11 +1147,18 @@ public class SyncManager extends Service implements Runnable { mResolver.registerContentObserver(Mailbox.CONTENT_URI, false, mMailboxObserver); mResolver.registerContentObserver(Message.SYNCED_CONTENT_URI, true, mSyncedMessageObserver); mResolver.registerContentObserver(Message.CONTENT_URI, true, mMessageObserver); + ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, + mSyncStatusObserver); + AccountManager.get(this).addOnAccountsUpdatedListener(mAccountsUpdatedListener, + mHandler, true); mConnectivityReceiver = new ConnectivityReceiver(); registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + // See if any settings have changed while we weren't running... + checkPIMSyncSettings(); + try { while (!mStop) { runAwake(SYNC_MANAGER_ID);