diff options
| author | Andrew Stadler <stadler@android.com> | 2010-01-20 11:25:28 -0800 |
|---|---|---|
| committer | Android Git Automerger <android-git-automerger@android.com> | 2010-01-20 11:25:28 -0800 |
| commit | d3998ebe4e3581bbd34669fa5fb78537fa6ec98b (patch) | |
| tree | 8f417a19e1eb22a25f8cb8278b29909d5bebcaf9 | |
| parent | 80eb4fd0fed32800cd0c78e0e26ca0b3d54c7d2b (diff) | |
| parent | 85d765f41c20e6efb3b120055eb4f1efae166e8b (diff) | |
| download | android_packages_apps_Email-d3998ebe4e3581bbd34669fa5fb78537fa6ec98b.tar.gz android_packages_apps_Email-d3998ebe4e3581bbd34669fa5fb78537fa6ec98b.tar.bz2 android_packages_apps_Email-d3998ebe4e3581bbd34669fa5fb78537fa6ec98b.zip | |
am 85d765f4: Quick backup/restore of accounts DO NOT MERGE
Merge commit '85d765f41c20e6efb3b120055eb4f1efae166e8b' into eclair-plus-aosp
* commit '85d765f41c20e6efb3b120055eb4f1efae166e8b':
Quick backup/restore of accounts DO NOT MERGE
20 files changed, 861 insertions, 19 deletions
diff --git a/src/com/android/email/Account.java b/src/com/android/email/Account.java index cea3a25d6..236db1a4c 100644 --- a/src/com/android/email/Account.java +++ b/src/com/android/email/Account.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.net.Uri; -import java.io.Serializable; import java.util.Arrays; import java.util.UUID; @@ -30,7 +29,7 @@ import java.util.UUID; * Account stores all of the settings for a single account defined by the user. It is able to save * and delete itself given a Preferences to work with. Each account is defined by a UUID. */ -public class Account implements Serializable { +public class Account { public static final int DELETE_POLICY_NEVER = 0; public static final int DELETE_POLICY_7DAYS = 1; public static final int DELETE_POLICY_ON_DELETE = 2; @@ -46,12 +45,11 @@ public class Account implements Serializable { public static final int SYNC_WINDOW_1_MONTH = 5; public static final int SYNC_WINDOW_ALL = 6; - /** - * This should never be used for persistance, only for marshalling. - * TODO: Remove serializable (VERY SLOW) and replace with Parcelable - */ - private static final long serialVersionUID = 1L; - + // These flags will never be seen in a "real" (legacy) account + public static final int BACKUP_FLAGS_IS_BACKUP = 1; + public static final int BACKUP_FLAGS_SYNC_CONTACTS = 2; + public static final int BACKUP_FLAGS_IS_DEFAULT = 4; + // transient values - do not serialize private transient Preferences mPreferences; @@ -74,6 +72,8 @@ public class Account implements Serializable { boolean mVibrate; String mRingtoneUri; int mSyncWindow; + int mBackupFlags; // for account backups only + String mProtocolVersion; // for account backups only /** * <pre> @@ -88,6 +88,8 @@ public class Account implements Serializable { * All new fields should have named keys */ private final String KEY_SYNC_WINDOW = ".syncWindow"; + private final String KEY_BACKUP_FLAGS = ".backupFlags"; + private final String KEY_PROTOCOL_VERSION = ".protocolVersion"; public Account(Context context) { // TODO Change local store path to something readable / recognizable @@ -99,6 +101,8 @@ public class Account implements Serializable { mVibrate = false; mRingtoneUri = "content://settings/system/notification_sound"; mSyncWindow = SYNC_WINDOW_USER; // IMAP & POP3 + mBackupFlags = 0; + mProtocolVersion = null; } Account(Preferences preferences, String uuid) { @@ -157,6 +161,10 @@ public class Account implements Serializable { mSyncWindow = preferences.mSharedPreferences.getInt(mUuid + KEY_SYNC_WINDOW, SYNC_WINDOW_USER); + + mBackupFlags = preferences.mSharedPreferences.getInt(mUuid + KEY_BACKUP_FLAGS, 0); + mProtocolVersion = preferences.mSharedPreferences.getString(mUuid + KEY_PROTOCOL_VERSION, + null); } public String getUuid() { @@ -252,6 +260,8 @@ public class Account implements Serializable { editor.remove(mUuid + ".vibrate"); editor.remove(mUuid + ".ringtone"); editor.remove(mUuid + KEY_SYNC_WINDOW); + editor.remove(mUuid + KEY_BACKUP_FLAGS); + editor.remove(mUuid + KEY_PROTOCOL_VERSION); // also delete any deprecated fields editor.remove(mUuid + ".transportUri"); @@ -315,6 +325,8 @@ public class Account implements Serializable { editor.putBoolean(mUuid + ".vibrate", mVibrate); editor.putString(mUuid + ".ringtone", mRingtoneUri); editor.putInt(mUuid + KEY_SYNC_WINDOW, mSyncWindow); + editor.putInt(mUuid + KEY_BACKUP_FLAGS, mBackupFlags); + editor.putString(mUuid + KEY_PROTOCOL_VERSION, mProtocolVersion); // The following fields are *not* written because they need to be more fine-grained // and not risk rewriting with old data. diff --git a/src/com/android/email/AccountBackupRestore.java b/src/com/android/email/AccountBackupRestore.java new file mode 100644 index 000000000..376c29f5c --- /dev/null +++ b/src/com/android/email/AccountBackupRestore.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.email; + +import com.android.email.mail.store.ExchangeStore; +import com.android.email.provider.EmailContent; +import com.android.exchange.Eas; + +import android.accounts.AccountManagerFuture; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.provider.ContactsContract; +import android.util.Log; + +/** + * Utility functions to support backup and restore of accounts. + * + * In the short term, this is used to work around local database failures. In the long term, + * this will also support server-side backups, providing support for automatic account restoration + * when switching or replacing phones. + */ +public class AccountBackupRestore { + + /** + * Backup accounts. Can be called from UI thread (does work in a new thread) + */ + public static void backupAccounts(final Context context) { + if (Email.DEBUG) { + Log.v(Email.LOG_TAG, "backupAccounts"); + } + // Because we typically call this from the UI, let's do the work in a thread + new Thread() { + @Override + public void run() { + synchronized(AccountBackupRestore.class) { + doBackupAccounts(context, Preferences.getPreferences(context)); + } + } + }.start(); + } + + /** + * Restore accounts if needed. This is blocking, and should only be called in specific + * startup/entry points. + */ + public static void restoreAccountsIfNeeded(final Context context) { + // Don't log here; This is called often. + boolean restored; + synchronized(AccountBackupRestore.class) { + restored = doRestoreAccounts(context, Preferences.getPreferences(context)); + } + if (restored) { + // after restoring accounts, register services appropriately + Log.w(Email.LOG_TAG, "Register services after restoring accounts"); + Email.setServicesEnabled(context); + context.startService(new Intent(context.getApplicationContext(), + com.android.exchange.SyncManager.class)); + } + } + + /** + * Non-UI-Thread worker to backup all accounts + * + * @param context used to access the provider + * @param preferences used to access the backups (provided separately for testability) + */ + /* package */ static void doBackupAccounts(Context context, Preferences preferences) { + // 1. Wipe any existing backup accounts + Account[] oldBackups = preferences.getAccounts(); + for (Account backup : oldBackups) { + backup.delete(preferences); + } + + // 2. Identify the default account (if any). This is required because setting + // the default account flag is lazy,and sometimes we don't have any flags set. We'll + // use this to make it explicit (see loop, below). + long defaultAccountId = EmailContent.Account.getDefaultAccountId(context); + if (defaultAccountId == -1) { + return; + } + + // 3. Create new backup(s), if any + Cursor c = context.getContentResolver().query(EmailContent.Account.CONTENT_URI, + EmailContent.Account.CONTENT_PROJECTION, null, null, null); + try { + while (c.moveToNext()) { + EmailContent.Account fromAccount = + EmailContent.getContent(c, EmailContent.Account.class); + if (Email.DEBUG) { + Log.v(Email.LOG_TAG, "Backing up account:" + fromAccount.getDisplayName()); + } + Account toAccount = LegacyConversions.makeLegacyAccount(context, fromAccount); + + // Determine if contacts are also synced, and if so, record that + if (fromAccount.mHostAuthRecv.mProtocol.equals("eas")) { + android.accounts.Account acct = new android.accounts.Account( + fromAccount.mEmailAddress, Eas.ACCOUNT_MANAGER_TYPE); + boolean syncContacts = ContentResolver.getSyncAutomatically(acct, + ContactsContract.AUTHORITY); + if (syncContacts) { + toAccount.mBackupFlags |= Account.BACKUP_FLAGS_SYNC_CONTACTS; + } + } + + // If this is the default account, mark it as such + if (fromAccount.mId == defaultAccountId) { + toAccount.mBackupFlags |= Account.BACKUP_FLAGS_IS_DEFAULT; + } + + // Mark this account as a backup of a Provider account, instead of a legacy + // account to upgrade + toAccount.mBackupFlags |= Account.BACKUP_FLAGS_IS_BACKUP; + + toAccount.save(preferences); + } + } finally { + c.close(); + } + } + + /** + * Restore all accounts. This is blocking. + * + * @param context used to access the provider + * @param preferences used to access the backups (provided separately for testability) + * @return true if accounts were restored (meaning services should be restarted, etc.) + */ + /* package */ static boolean doRestoreAccounts(Context context, Preferences preferences) { + boolean result = false; + + // 1. Quick check - if we have any accounts, get out + int numAccounts = EmailContent.count(context, EmailContent.Account.CONTENT_URI, null, null); + if (numAccounts > 0) { + return result; + } + // 2. Quick check - if no backup accounts, get out + Account[] backups = preferences.getAccounts(); + if (backups.length == 0) { + return result; + } + + Log.w(Email.LOG_TAG, "*** Restoring Email Accounts, found " + backups.length); + + // 3. Possible lost accounts situation - check for any backups, and restore them + for (Account backupAccount : backups) { + // don't back up any leftover legacy accounts (these are migrated elsewhere). + if ((backupAccount.mBackupFlags & Account.BACKUP_FLAGS_IS_BACKUP) == 0) { + continue; + } + // Restore the account + Log.v(Email.LOG_TAG, "Restoring account:" + backupAccount.getDescription()); + EmailContent.Account toAccount = + LegacyConversions.makeAccount(context, backupAccount); + + // Mark the default account if this is it + if (0 != (backupAccount.mBackupFlags & Account.BACKUP_FLAGS_IS_DEFAULT)) { + toAccount.setDefaultAccount(true); + } + + // For exchange accounts, handle system account first, then save in provider + if (toAccount.mHostAuthRecv.mProtocol.equals("eas")) { + // Recreate entry in Account Manager as well, if needed + // Set "sync contacts" mode as well, if needed + boolean alsoSyncContacts = + (backupAccount.mBackupFlags & Account.BACKUP_FLAGS_SYNC_CONTACTS) != 0; + + // Use delete-then-add semantic to simplify handling of update-in-place +// AccountManagerFuture<Boolean> removeResult = ExchangeStore.removeSystemAccount( +// context.getApplicationContext(), toAccount, null); +// try { +// // This call blocks until removeSystemAccount completes. Result is not used. +// removeResult.getResult(); +// } catch (AccountsException e) { +// Log.d(Email.LOG_TAG, "removeSystemAccount failed: " + e); +// // log and discard - we don't care if remove fails, generally +// } catch (IOException e) { +// Log.d(Email.LOG_TAG, "removeSystemAccount failed: " + e); +// // log and discard - we don't care if remove fails, generally +// } + + // NOTE: We must use the Application here, rather than the current context, because + // all future references to AccountManager will use the context passed in here + // TODO: Need to implement overwrite semantics for an already-installed account + AccountManagerFuture<Bundle> addAccountResult = ExchangeStore.addSystemAccount( + context.getApplicationContext(), toAccount, alsoSyncContacts, null); +// try { +// // This call blocks until addSystemAccount completes. Result is not used. +// addAccountResult.getResult(); + toAccount.save(context); +// } catch (OperationCanceledException e) { +// Log.d(Email.LOG_TAG, "addAccount was canceled"); +// } catch (IOException e) { +// Log.d(Email.LOG_TAG, "addAccount failed: " + e); +// } catch (AuthenticatorException e) { +// Log.d(Email.LOG_TAG, "addAccount failed: " + e); +// } + + } else { + // non-eas account - save it immediately + toAccount.save(context); + } + // report that an account was restored + result = true; + } + return result; + } +} diff --git a/src/com/android/email/LegacyConversions.java b/src/com/android/email/LegacyConversions.java index 4c1ccf855..6c424df51 100644 --- a/src/com/android/email/LegacyConversions.java +++ b/src/com/android/email/LegacyConversions.java @@ -521,4 +521,84 @@ public class LegacyConversions { } mp.addBodyPart(bp); } + + /** + * Conversion from provider account to legacy account + * + * Used for backup/restore. + * + * @param context application context + * @param fromAccount the provider account to be backed up (including transient hostauth's) + * @result a legacy Account object ready to be committed to preferences + */ + /* package */ static Account makeLegacyAccount(Context context, + EmailContent.Account fromAccount) { + Account result = new Account(context); + + result.setDescription(fromAccount.getDisplayName()); + result.setEmail(fromAccount.getEmailAddress()); + // fromAccount.mSyncKey - assume lost if restoring + result.setSyncWindow(fromAccount.getSyncLookback()); + result.setAutomaticCheckIntervalMinutes(fromAccount.getSyncInterval()); + // fromAccount.mHostAuthKeyRecv - id not saved; will be reassigned when restoring + // fromAccount.mHostAuthKeySend - id not saved; will be reassigned when restoring + + // Provider Account flags, and how they are mapped. + // FLAGS_NOTIFY_NEW_MAIL -> mNotifyNewMail + // FLAGS_VIBRATE -> mVibrate + // DELETE_POLICY_NEVER -> mDeletePolicy + // DELETE_POLICY_7DAYS + // DELETE_POLICY_ON_DELETE + result.setNotifyNewMail(0 != + (fromAccount.getFlags() & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL)); + result.setVibrate(0 != + (fromAccount.getFlags() & EmailContent.Account.FLAGS_VIBRATE)); + result.setDeletePolicy(fromAccount.getDeletePolicy()); + + result.mUuid = fromAccount.getUuid(); + result.setName(fromAccount.mSenderName); + result.setRingtone(fromAccount.mRingtoneUri); + result.mProtocolVersion = fromAccount.mProtocolVersion; + // int fromAccount.mNewMessageCount = will be reset on next sync + + // Use the existing conversions from HostAuth <-> Uri + result.setStoreUri(fromAccount.getStoreUri(context)); + result.setSenderUri(fromAccount.getSenderUri(context)); + + return result; + } + + /** + * Conversion from legacy account to provider account + * + * Used for backup/restore and for account migration. + */ + /* package */ static EmailContent.Account makeAccount(Context context, Account fromAccount) { + + EmailContent.Account result = new EmailContent.Account(); + + result.setDisplayName(fromAccount.getDescription()); + result.setEmailAddress(fromAccount.getEmail()); + result.mSyncKey = ""; + result.setSyncLookback(fromAccount.getSyncWindow()); + result.setSyncInterval(fromAccount.getAutomaticCheckIntervalMinutes()); + // result.mHostAuthKeyRecv + // result.mHostAuthKeySend; + int flags = 0; + if (fromAccount.isNotifyNewMail()) flags |= EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL; + if (fromAccount.isVibrate()) flags |= EmailContent.Account.FLAGS_VIBRATE; + result.setFlags(flags); + result.setDeletePolicy(fromAccount.getDeletePolicy()); + // result.setDefaultAccount(); + result.mCompatibilityUuid = fromAccount.getUuid(); + result.setSenderName(fromAccount.getName()); + result.setRingtone(fromAccount.getRingtone()); + result.mProtocolVersion = fromAccount.mProtocolVersion; + result.mNewMessageCount = 0; + + result.setStoreUri(context, fromAccount.getStoreUri()); + result.setSenderUri(context, fromAccount.getSenderUri()); + + return result; + } } diff --git a/src/com/android/email/activity/AccountFolderList.java b/src/com/android/email/activity/AccountFolderList.java index b321dfe29..08ae5fca0 100644 --- a/src/com/android/email/activity/AccountFolderList.java +++ b/src/com/android/email/activity/AccountFolderList.java @@ -16,6 +16,7 @@ package com.android.email.activity; +import com.android.email.AccountBackupRestore; import com.android.email.Controller; import com.android.email.Email; import com.android.email.R; @@ -460,6 +461,8 @@ public class AccountFolderList extends ListActivity Uri uri = ContentUris.withAppendedId( EmailContent.Account.CONTENT_URI, mSelectedContextAccount.mId); AccountFolderList.this.getContentResolver().delete(uri, null, null); + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(AccountFolderList.this); } catch (Exception e) { // Ignore } diff --git a/src/com/android/email/activity/Welcome.java b/src/com/android/email/activity/Welcome.java index 0bf77b3a7..7fd15b261 100644 --- a/src/com/android/email/activity/Welcome.java +++ b/src/com/android/email/activity/Welcome.java @@ -16,6 +16,7 @@ package com.android.email.activity; +import com.android.email.AccountBackupRestore; import com.android.email.activity.setup.AccountSetupBasics; import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Mailbox; @@ -42,6 +43,13 @@ public class Welcome extends Activity { public void onCreate(Bundle icicle) { super.onCreate(icicle); + // Restore accounts, if it has not happened already + // NOTE: This is blocking, which it should not be (in the UI thread) + // We're going to live with this for the short term and replace with something + // smarter. Long-term fix: Move this, and most of the code below, to an AsyncTask + // and do the DB work in a thread. Then post handler to finish() as appropriate. + AccountBackupRestore.restoreAccountsIfNeeded(this); + // Because the app could be reloaded (for debugging, etc.), we need to make sure that // SyncManager gets a chance to start. There is no harm to starting it if it has already // been started diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java index 99b779786..57f1cac00 100644 --- a/src/com/android/email/activity/setup/AccountSettingsUtils.java +++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.AccountBackupRestore; import com.android.email.provider.EmailContent; import com.android.email.provider.EmailContent.AccountColumns; @@ -45,5 +46,7 @@ public class AccountSettingsUtils { cv.put(AccountColumns.SYNC_LOOKBACK, account.mSyncLookback); account.update(context, cv); } + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(context); } } diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java index e29b73f76..2b805c72f 100644 --- a/src/com/android/email/activity/setup/AccountSetupBasics.java +++ b/src/com/android/email/activity/setup/AccountSetupBasics.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.AccountBackupRestore; import com.android.email.Email; import com.android.email.EmailAddressValidator; import com.android.email.R; @@ -380,6 +381,8 @@ public class AccountSetupBasics extends Activity // At this point we write the Account object to the DB for the first time. // From now on we'll only pass the accountId around. mAccount.save(this); + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(this); Email.setServicesEnabled(this); AccountSetupNames.actionSetNames(this, mAccount.mId, false); finish(); diff --git a/src/com/android/email/activity/setup/AccountSetupExchange.java b/src/com/android/email/activity/setup/AccountSetupExchange.java index dfeca770e..c89f8acca 100644 --- a/src/com/android/email/activity/setup/AccountSetupExchange.java +++ b/src/com/android/email/activity/setup/AccountSetupExchange.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.AccountBackupRestore; import com.android.email.R; import com.android.email.Utility; import com.android.email.provider.EmailContent; @@ -288,6 +289,8 @@ public class AccountSetupExchange extends Activity implements OnClickListener, // Account.save will save the HostAuth's mAccount.save(this); } + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(this); finish(); } else { // Go directly to end - there is no 2nd screen for incoming settings diff --git a/src/com/android/email/activity/setup/AccountSetupIncoming.java b/src/com/android/email/activity/setup/AccountSetupIncoming.java index f8625e15e..f93d49b3a 100644 --- a/src/com/android/email/activity/setup/AccountSetupIncoming.java +++ b/src/com/android/email/activity/setup/AccountSetupIncoming.java @@ -17,6 +17,7 @@ package com.android.email.activity.setup; import com.android.email.Account; +import com.android.email.AccountBackupRestore; import com.android.email.R; import com.android.email.Utility; import com.android.email.provider.EmailContent; @@ -334,6 +335,8 @@ public class AccountSetupIncoming extends Activity implements OnClickListener { } else { mAccount.save(this); } + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(this); finish(); } else { /* diff --git a/src/com/android/email/activity/setup/AccountSetupNames.java b/src/com/android/email/activity/setup/AccountSetupNames.java index b99cf0550..2486a381b 100644 --- a/src/com/android/email/activity/setup/AccountSetupNames.java +++ b/src/com/android/email/activity/setup/AccountSetupNames.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.AccountBackupRestore; import com.android.email.R; import com.android.email.Utility; import com.android.email.activity.MessageList; @@ -117,6 +118,8 @@ public class AccountSetupNames extends Activity implements OnClickListener { cv.put(AccountColumns.DISPLAY_NAME, mAccount.getDisplayName()); cv.put(AccountColumns.SENDER_NAME, name); mAccount.update(this, cv); + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(this); // Exit or dispatch per flow mode if (getIntent().getBooleanExtra(EXTRA_EAS_FLOW, false)) { diff --git a/src/com/android/email/activity/setup/AccountSetupOutgoing.java b/src/com/android/email/activity/setup/AccountSetupOutgoing.java index 0b2138c07..40e369efd 100644 --- a/src/com/android/email/activity/setup/AccountSetupOutgoing.java +++ b/src/com/android/email/activity/setup/AccountSetupOutgoing.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.AccountBackupRestore; import com.android.email.R; import com.android.email.Utility; import com.android.email.provider.EmailContent; @@ -255,6 +256,8 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener, } else { mAccount.save(this); } + // Update the backup (side copy) of the accounts + AccountBackupRestore.backupAccounts(this); finish(); } else { AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault, false); diff --git a/src/com/android/email/mail/store/ExchangeStore.java b/src/com/android/email/mail/store/ExchangeStore.java index 69f6e60d1..013287897 100644 --- a/src/com/android/email/mail/store/ExchangeStore.java +++ b/src/com/android/email/mail/store/ExchangeStore.java @@ -29,6 +29,7 @@ import com.android.exchange.SyncManager; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; import android.content.Context; import android.os.Bundle; import android.os.RemoteException; @@ -79,8 +80,8 @@ public class ExchangeStore extends Store { mTransport.checkSettings(mUri); } - static public void addSystemAccount(Context context, Account acct, boolean syncContacts, - AccountManagerCallback<Bundle> callback) { + static public AccountManagerFuture<Bundle> addSystemAccount(Context context, Account acct, + boolean syncContacts, AccountManagerCallback<Bundle> callback) { // Create a description of the new account Bundle options = new Bundle(); options.putString(EasAuthenticatorService.OPTIONS_USERNAME, acct.mEmailAddress); @@ -90,10 +91,25 @@ public class ExchangeStore extends Store { // Here's where we tell AccountManager about the new account. The addAccount // method in AccountManager calls the addAccount method in our authenticator // service (EasAuthenticatorService) - AccountManager.get(context).addAccount(Eas.ACCOUNT_MANAGER_TYPE, null, null, + return AccountManager.get(context).addAccount(Eas.ACCOUNT_MANAGER_TYPE, null, null, options, null, callback, null); } + /** + * Remove an account from the Account manager - see {@link AccountManager#removeAccount( + * android.accounts.Account, AccountManagerCallback, android.os.Handler)}. + * + * @param context context to use + * @param acct the account to remove + * @param callback async results callback - pass null to use blocking mode + */ + static public AccountManagerFuture<Boolean> removeSystemAccount(Context context, Account acct, + AccountManagerCallback<Bundle> callback) { + android.accounts.Account systemAccount = + new android.accounts.Account(acct.mEmailAddress, Eas.ACCOUNT_MANAGER_TYPE); + return AccountManager.get(context).removeAccount(systemAccount, null, null); + } + @Override public Folder getFolder(String name) { return null; diff --git a/src/com/android/email/provider/EmailContent.java b/src/com/android/email/provider/EmailContent.java index 955ea0d27..cc060c72d 100644 --- a/src/com/android/email/provider/EmailContent.java +++ b/src/com/android/email/provider/EmailContent.java @@ -1066,7 +1066,7 @@ public abstract class EmailContent { * with accounts set up by previous versions, because there are externals references * to the Uuid (e.g. desktop shortcuts). */ - String getUuid() { + public String getUuid() { return mCompatibilityUuid; } diff --git a/src/com/android/email/service/BootReceiver.java b/src/com/android/email/service/BootReceiver.java index 74d569f07..880773c2b 100644 --- a/src/com/android/email/service/BootReceiver.java +++ b/src/com/android/email/service/BootReceiver.java @@ -16,6 +16,7 @@ package com.android.email.service; +import com.android.email.AccountBackupRestore; import com.android.email.Email; import android.content.BroadcastReceiver; @@ -25,6 +26,9 @@ import android.content.Intent; public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + // Restore accounts, if it has not happened already + AccountBackupRestore.restoreAccountsIfNeeded(context); + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { // Returns true if there are any accounts if (Email.setServicesEnabled(context)) { diff --git a/src/com/android/email/service/MailService.java b/src/com/android/email/service/MailService.java index 48c18bf22..557ce8fb7 100644 --- a/src/com/android/email/service/MailService.java +++ b/src/com/android/email/service/MailService.java @@ -16,6 +16,7 @@ package com.android.email.service;
+import com.android.email.AccountBackupRestore;
import com.android.email.Controller;
import com.android.email.Email;
import com.android.email.R;
@@ -149,6 +150,9 @@ public class MailService extends Service { public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
+ // Restore accounts, if it has not happened already
+ AccountBackupRestore.restoreAccountsIfNeeded(this);
+
// TODO this needs to be passed through the controller and back to us
this.mStartId = startId;
String action = intent.getAction();
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java index e83dba5f2..0133aafaf 100644 --- a/src/com/android/exchange/SyncManager.java +++ b/src/com/android/exchange/SyncManager.java @@ -17,6 +17,7 @@ package com.android.exchange; +import com.android.email.AccountBackupRestore; import com.android.email.mail.MessagingException; import com.android.email.mail.store.TrustManagerFactory; import com.android.email.provider.EmailContent; @@ -816,6 +817,10 @@ public class SyncManager extends Service implements Runnable { @Override public int onStartCommand(Intent intent, int flags, int startId) { alwaysLog("!!! EAS SyncManager, onStartCommand"); + + // Restore accounts, if it has not happened already + AccountBackupRestore.restoreAccountsIfNeeded(this); + maybeStartSyncManagerThread(); if (sServiceThread == null) { alwaysLog("!!! EAS SyncManager, stopping self"); diff --git a/tests/src/com/android/email/AccountBackupRestoreTests.java b/tests/src/com/android/email/AccountBackupRestoreTests.java new file mode 100644 index 000000000..47466e716 --- /dev/null +++ b/tests/src/com/android/email/AccountBackupRestoreTests.java @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.email; + +import com.android.email.provider.EmailContent; +import com.android.email.provider.EmailProvider; +import com.android.email.provider.ProviderTestUtils; + +import android.content.Context; +import android.database.Cursor; +import android.test.ProviderTestCase2; +import android.test.suitebuilder.annotation.MediumTest; + +/** + * This is a series of unit tests for backup/restore of the Account class. + * + * Technically these are functional because they use the underlying preferences framework. + * + * NOTE: These tests are destructive of any "legacy" accounts that might be lying around. + */ +@MediumTest +public class AccountBackupRestoreTests extends ProviderTestCase2<EmailProvider> { + + private Preferences mPreferences; + private Context mMockContext; + + public AccountBackupRestoreTests() { + super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mMockContext = getMockContext(); + // Note: preferences are not supported by this mock context, so we must + // explicitly use (and clean out) the real ones for now. + mPreferences = Preferences.getPreferences(mContext); + } + + /** + * Delete any dummy accounts we set up for this test + */ + @Override + protected void tearDown() throws Exception { + super.tearDown(); + deleteLegacyAccounts(); + } + + /** + * Delete *all* legacy accounts + */ + private void deleteLegacyAccounts() { + Account[] oldAccounts = mPreferences.getAccounts(); + for (Account oldAccount : oldAccounts) { + oldAccount.delete(mPreferences); + } + } + + /** + * Test backup with no accounts + */ + public void testNoAccountBackup() { + // create some "old" backups or legacy accounts + Account backupAccount = new Account(mMockContext); + backupAccount.save(mPreferences); + // confirm they are there + Account[] oldBackups = mPreferences.getAccounts(); + assertTrue(oldBackups.length >= 1); + // make sure there are no accounts in the provider + int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, + null, null); + assertEquals(0, numAccounts); + // run backups + AccountBackupRestore.doBackupAccounts(mMockContext, mPreferences); + // confirm there are no backups made + Account[] backups = mPreferences.getAccounts(); + assertEquals(0, backups.length); + } + + /** + * Test backup with accounts + */ + public void testBackup() { + // Clear the decks + deleteLegacyAccounts(); + + // Create real accounts in need of backup + EmailContent.Account liveAccount1 = + ProviderTestUtils.setupAccount("testBackup1", false, mMockContext); + liveAccount1.mHostAuthRecv = + ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mMockContext); + liveAccount1.mHostAuthSend = + ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mMockContext); + liveAccount1.setDefaultAccount(true); + liveAccount1.save(mMockContext); + EmailContent.Account liveAccount2 = + ProviderTestUtils.setupAccount("testBackup2", false, mMockContext); + liveAccount2.mHostAuthRecv = + ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mMockContext); + liveAccount2.mHostAuthSend = + ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mMockContext); + liveAccount2.setDefaultAccount(false); + liveAccount2.save(mMockContext); + + // run backups + AccountBackupRestore.doBackupAccounts(mMockContext, mPreferences); + + // Confirm we have two backups now + // Deep inspection is not performed here - see LegacyConversionsTests + // We just check for basic identity & flags + Account[] backups = mPreferences.getAccounts(); + assertEquals(2, backups.length); + for (Account backup : backups) { + if ("testBackup1".equals(backup.getDescription())) { + assertTrue(0 != (backup.mBackupFlags & Account.BACKUP_FLAGS_IS_DEFAULT)); + } else if ("testBackup2".equals(backup.getDescription())) { + assertFalse(0 != (backup.mBackupFlags & Account.BACKUP_FLAGS_IS_DEFAULT)); + } else { + fail("unexpected backup name=" + backup.getDescription()); + } + } + Account backup1 = backups[0]; + assertTrue(0 != (backup1.mBackupFlags & Account.BACKUP_FLAGS_IS_BACKUP)); + assertEquals(liveAccount1.getDisplayName(), backup1.getDescription()); + } + + /** + * TODO: Test backup EAS accounts, with and without contacts sync + * + * Blocker: We need to inject the dependency on ContentResolver.getSyncAutomatically() + * so we can make our fake accounts appear to be syncable or non-syncable + */ + + /** + * Test no-restore with accounts found + */ + public void testNoAccountRestore1() { + // make sure there are no real backups + deleteLegacyAccounts(); + + // make sure there are test backups available + Account backupAccount1 = setupLegacyBackupAccount("backup1"); + backupAccount1.save(mPreferences); + Account backupAccount2 = setupLegacyBackupAccount("backup2"); + backupAccount2.save(mPreferences); + + // make sure there are accounts + EmailContent.Account existing = + ProviderTestUtils.setupAccount("existing", true, mMockContext); + + // run the restore + boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); + assertFalse(anyRestored); + + // make sure accounts still there + int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, + null, null); + assertEquals(1, numAccounts); + } + + /** + * Test no-restore with no accounts & no backups + */ + public void testNoAccountRestore2() { + // make sure there are no real backups + deleteLegacyAccounts(); + + // make sure there are no accounts + int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, + null, null); + assertEquals(0, numAccounts); + + // run the restore + boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); + assertFalse(anyRestored); + + // make sure accounts still there + numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, + null, null); + assertEquals(0, numAccounts); + } + + /** + * Test restore with 2 accounts. + * Repeats test to verify restore of default account + */ + public void testAccountRestore() { + // make sure there are no real backups + deleteLegacyAccounts(); + + // create test backups + Account backupAccount1 = setupLegacyBackupAccount("backup1"); + backupAccount1.mBackupFlags |= Account.BACKUP_FLAGS_IS_DEFAULT; + backupAccount1.save(mPreferences); + Account backupAccount2 = setupLegacyBackupAccount("backup2"); + backupAccount2.save(mPreferences); + + // run the restore + boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); + assertTrue(anyRestored); + + // Check the restored accounts + // Deep inspection is not performed here - see LegacyConversionsTests for that + // We just check for basic identity & flags + Cursor c = mMockContext.getContentResolver().query(EmailContent.Account.CONTENT_URI, + EmailContent.Account.CONTENT_PROJECTION, null, null, null); + try { + assertEquals(2, c.getCount()); + while (c.moveToNext()) { + EmailContent.Account restored = + EmailContent.getContent(c, EmailContent.Account.class); + if ("backup1".equals(restored.getDisplayName())) { + assertTrue(restored.mIsDefault); + } else if ("backup2".equals(restored.getDisplayName())) { + assertFalse(restored.mIsDefault); + } else { + fail("Unexpected restore account name=" + restored.getDisplayName()); + } + } + } finally { + c.close(); + } + + // clear out the backups & accounts and try again + deleteLegacyAccounts(); + mMockContext.getContentResolver().delete(EmailContent.Account.CONTENT_URI, null, null); + + Account backupAccount3 = setupLegacyBackupAccount("backup3"); + backupAccount3.save(mPreferences); + Account backupAccount4 = setupLegacyBackupAccount("backup4"); + backupAccount4.mBackupFlags |= Account.BACKUP_FLAGS_IS_DEFAULT; + backupAccount4.save(mPreferences); + + // run the restore + AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); + + // Check the restored accounts + // Deep inspection is not performed here - see LegacyConversionsTests for that + // We just check for basic identity & flags + c = mMockContext.getContentResolver().query(EmailContent.Account.CONTENT_URI, + EmailContent.Account.CONTENT_PROJECTION, null, null, null); + try { + assertEquals(2, c.getCount()); + while (c.moveToNext()) { + EmailContent.Account restored = + EmailContent.getContent(c, EmailContent.Account.class); + if ("backup3".equals(restored.getDisplayName())) { + assertFalse(restored.mIsDefault); + } else if ("backup4".equals(restored.getDisplayName())) { + assertTrue(restored.mIsDefault); + } else { + fail("Unexpected restore account name=" + restored.getDisplayName()); + } + } + } finally { + c.close(); + } + } + + /** + * TODO: Test restore EAS accounts, with and without contacts sync + * + * Blocker: We need to inject the dependency on account manager to catch the calls to it + */ + + /** + * Setup a legacy backup account with many fields prefilled. + */ + private Account setupLegacyBackupAccount(String name) { + Account backup = new Account(mMockContext); + + // fill in useful fields + backup.mUuid = "test-uid-" + name; + backup.mStoreUri = "store://test/" + name; + backup.mLocalStoreUri = "local://localhost/" + name; + backup.mSenderUri = "sender://test/" + name; + backup.mDescription = name; + backup.mName = "name " + name; + backup.mEmail = "email " + name; + backup.mAutomaticCheckIntervalMinutes = 100; + backup.mLastAutomaticCheckTime = 200; + backup.mNotifyNewMail = true; + backup.mDraftsFolderName = "drafts " + name; + backup.mSentFolderName = "sent " + name; + backup.mTrashFolderName = "trash " + name; + backup.mOutboxFolderName = "outbox " + name; + backup.mAccountNumber = 300; + backup.mVibrate = true; + backup.mRingtoneUri = "ringtone://test/" + name; + backup.mSyncWindow = 400; + backup.mBackupFlags = Account.BACKUP_FLAGS_IS_BACKUP; + backup.mProtocolVersion = "proto version" + name; + backup.mDeletePolicy = Account.DELETE_POLICY_NEVER; + return backup; + } +} diff --git a/tests/src/com/android/email/AccountUnitTests.java b/tests/src/com/android/email/AccountUnitTests.java index ff097993b..ef1797a7c 100644 --- a/tests/src/com/android/email/AccountUnitTests.java +++ b/tests/src/com/android/email/AccountUnitTests.java @@ -134,7 +134,37 @@ public class AccountUnitTests extends AndroidTestCase { storedPolicy = mPreferences.mSharedPreferences.getInt(mUuid + ".deletePolicy", -1); assertEquals(Account.DELETE_POLICY_ON_DELETE, storedPolicy); } - + + /** + * Test new flags field (added only for backups - not used by real/legacy accounts) + */ + public void testFlagsField() { + createTestAccount(); + assertEquals(0, mAccount.mBackupFlags); + mAccount.save(mPreferences); + mAccount.mBackupFlags = -1; + mAccount.refresh(mPreferences); + assertEquals(0, mAccount.mBackupFlags); + + mAccount.mBackupFlags = Account.BACKUP_FLAGS_IS_BACKUP; + mAccount.save(mPreferences); + mAccount.mBackupFlags = -1; + mAccount.refresh(mPreferences); + assertEquals(Account.BACKUP_FLAGS_IS_BACKUP, mAccount.mBackupFlags); + + mAccount.mBackupFlags = Account.BACKUP_FLAGS_SYNC_CONTACTS; + mAccount.save(mPreferences); + mAccount.mBackupFlags = -1; + mAccount.refresh(mPreferences); + assertEquals(Account.BACKUP_FLAGS_SYNC_CONTACTS, mAccount.mBackupFlags); + + mAccount.mBackupFlags = Account.BACKUP_FLAGS_IS_DEFAULT; + mAccount.save(mPreferences); + mAccount.mBackupFlags = -1; + mAccount.refresh(mPreferences); + assertEquals(Account.BACKUP_FLAGS_IS_DEFAULT, mAccount.mBackupFlags); + } + /** * Create a dummy account with minimal fields */ diff --git a/tests/src/com/android/email/LegacyConversionsTests.java b/tests/src/com/android/email/LegacyConversionsTests.java index 3fceb32b3..e487ffeac 100644 --- a/tests/src/com/android/email/LegacyConversionsTests.java +++ b/tests/src/com/android/email/LegacyConversionsTests.java @@ -16,6 +16,7 @@ package com.android.email; +import com.android.email.Account; import com.android.email.mail.Address; import com.android.email.mail.BodyPart; import com.android.email.mail.Flag; @@ -65,13 +66,14 @@ public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { private static final String RECIPIENT_BCC = "recipient-bcc@android.com"; private static final String REPLY_TO = "reply-to@android.com"; private static final String SUBJECT = "This is the subject"; - private static final String BODY = "This is the body. This is also the body."; private static final String MESSAGE_ID = "Test-Message-ID"; private static final String MESSAGE_ID_2 = "Test-Message-ID-Second"; EmailProvider mProvider; Context mProviderContext; Context mContext; + Account mLegacyAccount = null; + Preferences mPreferences = null; public LegacyConversionsTests() { super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); @@ -87,6 +89,9 @@ public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { @Override public void tearDown() throws Exception { super.tearDown(); + if (mLegacyAccount != null) { + mLegacyAccount.delete(mPreferences); + } } /** @@ -155,7 +160,7 @@ public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { } if (sender != null) { Address[] addresses = Address.parse(sender); - message.setFrom(Address.parse(sender)[0]); + message.setFrom(addresses[0]); } if (subject != null) { message.setSubject(subject); @@ -480,4 +485,130 @@ public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { // cv.put("attachment_count", attachments.size()); } + + /** + * Test conversion of a legacy account to a provider account + */ + public void testMakeProviderAccount() throws MessagingException { + + setupLegacyAccount("testMakeProviderAccount", true); + EmailContent.Account toAccount = + LegacyConversions.makeAccount(mProviderContext, mLegacyAccount); + checkProviderAccount("testMakeProviderAccount", mLegacyAccount, toAccount); + } + + /** + * Test conversion of a provider account to a legacy account + */ + public void testMakeLegacyAccount() throws MessagingException { + EmailContent.Account fromAccount = ProviderTestUtils.setupAccount("convert-to-legacy", + false, mProviderContext); + fromAccount.mHostAuthRecv = + ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mProviderContext); + fromAccount.mHostAuthSend = + ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mProviderContext); + fromAccount.save(mProviderContext); + + Account toAccount = LegacyConversions.makeLegacyAccount(mProviderContext, fromAccount); + checkLegacyAccount("testMakeLegacyAccount", fromAccount, toAccount); + } + + /** + * Setup a legacy account in mLegacyAccount with many fields prefilled. + */ + private void setupLegacyAccount(String name, boolean saveIt) { + // prefs & legacy account are saved for cleanup (it's stored in the real prefs file) + mPreferences = Preferences.getPreferences(mProviderContext); + mLegacyAccount = new Account(mProviderContext); + + // fill in useful fields + mLegacyAccount.mUuid = "test-uid-" + name; + mLegacyAccount.mStoreUri = "store://test/" + name; + mLegacyAccount.mLocalStoreUri = "local://localhost/" + name; + mLegacyAccount.mSenderUri = "sender://test/" + name; + mLegacyAccount.mDescription = "description " + name; + mLegacyAccount.mName = "name " + name; + mLegacyAccount.mEmail = "email " + name; + mLegacyAccount.mAutomaticCheckIntervalMinutes = 100; + mLegacyAccount.mLastAutomaticCheckTime = 200; + mLegacyAccount.mNotifyNewMail = true; + mLegacyAccount.mDraftsFolderName = "drafts " + name; + mLegacyAccount.mSentFolderName = "sent " + name; + mLegacyAccount.mTrashFolderName = "trash " + name; + mLegacyAccount.mOutboxFolderName = "outbox " + name; + mLegacyAccount.mAccountNumber = 300; + mLegacyAccount.mVibrate = true; + mLegacyAccount.mRingtoneUri = "ringtone://test/" + name; + mLegacyAccount.mSyncWindow = 400; + mLegacyAccount.mBackupFlags = 0; + mLegacyAccount.mDeletePolicy = Account.DELETE_POLICY_NEVER; + + if (saveIt) { + mLegacyAccount.save(mPreferences); + } + } + + /** + * Compare a provider account to the legacy account it was created from + */ + private void checkProviderAccount(String tag, Account expect, EmailContent.Account actual) + throws MessagingException { + assertEquals(tag + " description", expect.getDescription(), actual.mDisplayName); + assertEquals(tag + " email", expect.getEmail(), actual.mEmailAddress); + assertEquals(tag + " sync key", "", actual.mSyncKey); + assertEquals(tag + " lookback", expect.getSyncWindow(), actual.mSyncLookback); + assertEquals(tag + " sync intvl", expect.getAutomaticCheckIntervalMinutes(), + actual.mSyncInterval); + // These asserts are checking mHostAuthKeyRecv & mHostAuthKeySend + assertEquals(tag + " store", expect.getStoreUri(), actual.getStoreUri(mProviderContext)); + assertEquals(tag + " sender", expect.getSenderUri(), actual.getSenderUri(mProviderContext)); + // Synthesize & check flags + int expectFlags = 0; + if (expect.mNotifyNewMail) expectFlags |= EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL; + if (expect.mVibrate) expectFlags |= EmailContent.Account.FLAGS_VIBRATE; + expectFlags |= + (expect.mDeletePolicy << EmailContent.Account.FLAGS_DELETE_POLICY_SHIFT) + & EmailContent.Account.FLAGS_DELETE_POLICY_MASK; + assertEquals(tag + " flags", expectFlags, actual.mFlags); + assertEquals(tag + " default", false, actual.mIsDefault); + assertEquals(tag + " uuid", expect.getUuid(), actual.mCompatibilityUuid); + assertEquals(tag + " name", expect.getName(), actual.mSenderName); + assertEquals(tag + " ringtone", expect.getRingtone(), actual.mRingtoneUri); + assertEquals(tag + " proto vers", expect.mProtocolVersion, actual.mProtocolVersion); + assertEquals(tag + " new count", 0, actual.mNewMessageCount); + } + + /** + * Compare a legacy account to the provider account it was created from + */ + private void checkLegacyAccount(String tag, EmailContent.Account expect, Account actual) + throws MessagingException { + int expectFlags = expect.getFlags(); + + assertEquals(tag + " uuid", expect.mCompatibilityUuid, actual.mUuid); + assertEquals(tag + " store", expect.getStoreUri(mProviderContext), actual.mStoreUri); + assertTrue(actual.mLocalStoreUri.startsWith("local://localhost")); + assertEquals(tag + " sender", expect.getSenderUri(mProviderContext), actual.mSenderUri); + assertEquals(tag + " description", expect.getDisplayName(), actual.mDescription); + assertEquals(tag + " name", expect.getSenderName(), actual.mName); + assertEquals(tag + " email", expect.getEmailAddress(), actual.mEmail); + assertEquals(tag + " checkintvl", expect.getSyncInterval(), + actual.mAutomaticCheckIntervalMinutes); + assertEquals(tag + " checktime", 0, actual.mLastAutomaticCheckTime); + assertEquals(tag + " notify", + (expectFlags & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL) != 0, + actual.mNotifyNewMail); + assertEquals(tag + " drafts", null, actual.mDraftsFolderName); + assertEquals(tag + " sent", null, actual.mSentFolderName); + assertEquals(tag + " trash", null, actual.mTrashFolderName); + assertEquals(tag + " outbox", null, actual.mOutboxFolderName); + assertEquals(tag + " acct #", -1, actual.mAccountNumber); + assertEquals(tag + " vibrate", (expectFlags & EmailContent.Account.FLAGS_VIBRATE) != 0, + actual.mVibrate); + assertEquals(tag + " ", expect.getRingtone(), actual.mRingtoneUri); + assertEquals(tag + " sync window", expect.getSyncLookback(), actual.mSyncWindow); + assertEquals(tag + " backup flags", 0, actual.mBackupFlags); + assertEquals(tag + " proto vers", expect.mProtocolVersion, actual.mProtocolVersion); + assertEquals(tag + " delete policy", expect.getDeletePolicy(), actual.getDeletePolicy()); + } } diff --git a/tests/src/com/android/email/PreferencesUnitTests.java b/tests/src/com/android/email/PreferencesUnitTests.java index 3216ccea1..c9129f799 100644 --- a/tests/src/com/android/email/PreferencesUnitTests.java +++ b/tests/src/com/android/email/PreferencesUnitTests.java @@ -16,7 +16,6 @@ package com.android.email; -import android.content.SharedPreferences; import android.net.Uri; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -34,7 +33,6 @@ public class PreferencesUnitTests extends AndroidTestCase { private Preferences mPreferences; - private String mUuid; private Account mAccount; @Override @@ -94,8 +92,6 @@ public class PreferencesUnitTests extends AndroidTestCase { private void createTestAccount() { mAccount = new Account(getContext()); mAccount.save(mPreferences); - - mUuid = mAccount.getUuid(); } } |
