replicant-packages_apps_Email/src/com/android/email/AccountBackupRestore.java

227 lines
9.6 KiB
Java
Raw Normal View History

/*
* 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;
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
import com.android.email.service.MailService;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.CalendarProviderStub;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
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 {
// This reduces the need for expensive checks to just the first time only/
// synchronize on AccountBackupRestore.class
private static boolean sBackupsChecked = false;
/**
* 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(Logging.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() {
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 synchronized void restoreAccountsIfNeeded(final Context context) {
// Quick exit if possible
if (sBackupsChecked) return;
// Don't log here; This is called often.
boolean restored = doRestoreAccounts(context, Preferences.getPreferences(context), false);
if (restored) {
// after restoring accounts, register services appropriately
Log.w(Logging.LOG_TAG, "Register services after restoring accounts");
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
// update security profile
SecurityPolicy.getInstance(context).updatePolicies(-1);
// enable/disable other email services as necessary
Email.setServicesEnabledSync(context);
ExchangeUtils.startExchangeService(context);
}
sBackupsChecked = true;
}
/**
* 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 */ synchronized 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).
// This is also the quick check for "no accounts" (the only case in which the returned
// value is -1) and if so, we can exit immediately.
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(Logging.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.isEasAccount(context)) {
android.accounts.Account acct = new android.accounts.Account(
fromAccount.mEmailAddress, AccountManagerTypes.TYPE_EXCHANGE);
boolean syncContacts = ContentResolver.getSyncAutomatically(acct,
ContactsContract.AUTHORITY);
if (syncContacts) {
toAccount.mBackupFlags |= Account.BACKUP_FLAGS_SYNC_CONTACTS;
}
boolean syncCalendar = ContentResolver.getSyncAutomatically(acct,
CalendarProviderStub.AUTHORITY);
if (syncCalendar) {
toAccount.mBackupFlags |= Account.BACKUP_FLAGS_SYNC_CALENDAR;
}
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
boolean syncEmail = ContentResolver.getSyncAutomatically(acct,
EmailContent.AUTHORITY);
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
if (!syncEmail) {
toAccount.mBackupFlags |= Account.BACKUP_FLAGS_DONT_SYNC_EMAIL;
}
}
// Attachment downloading
if ((fromAccount.mFlags & EmailContent.Account.FLAGS_BACKGROUND_ATTACHMENTS) != 0) {
toAccount.mBackupFlags |= Account.BACKUP_FLAGS_BACKGROUND_ATTACHMENTS;
}
// 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 */ synchronized static boolean doRestoreAccounts(Context context,
Preferences preferences, boolean unitTest) {
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(Logging.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.w(Logging.LOG_TAG, "Restoring account:" + backupAccount.getDescription());
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
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);
}
// Restore attachment flag
if (0 != (backupAccount.mBackupFlags & Account.BACKUP_FLAGS_BACKGROUND_ATTACHMENTS)) {
toAccount.mFlags |= EmailContent.Account.FLAGS_BACKGROUND_ATTACHMENTS;
}
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
// Note that the sense of the email flag is opposite that of contacts/calendar flags
boolean email =
(backupAccount.mBackupFlags & Account.BACKUP_FLAGS_DONT_SYNC_EMAIL) == 0;
boolean contacts = false;
boolean calendar = false;
// Handle system account first, then save in provider
if (toAccount.isEasAccount(context)) {
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
contacts = (backupAccount.mBackupFlags & Account.BACKUP_FLAGS_SYNC_CONTACTS) != 0;
calendar = (backupAccount.mBackupFlags & Account.BACKUP_FLAGS_SYNC_CALENDAR) != 0;
}
Use AccountManager for POP/IMAP; refactor setup classes There are two major, interrelated parts to this CL: 1) Clean up the activities to reduce the use of Intents to pass information between activities; instead, we use a common SetupData structure that automatically saved/restored as necessary during the setup flow. A fair amount of code and inconsistent use of Bundle extras has been eliminated in the process. * Create SetupData structure, setters/getters, and initialization methods to simplify the preservation of state during setup flow * Remove all state/flow extras from Intents; Intents now only specify the Activity to be started, which should greatly simplify the transition to Fragments. * Remove all state/flow fields from Activities * Modify existing setup activity unit tests and confirm tests pass 2) Create AccountManager accounts for POP/IMAP email accounts to provide consistency in user experience. Also, internal flows are now identical as between account types. * Move account reconciliation from SyncManager to MailService, so that reconciliation is consistent between email and exchange accounts; move unit tests as appropriate * Add a "Sync Email" setting for POP/IMAP/EAS * Change MailService to respect the "Sync Email" setting in Settings -> Accounts & sync * Create PopImapSyncAdapterService to handle manual POP/IMAP sync as requested by SyncManager; add EmailSyncAdapterService to perform the same function for EAS * Use new PopImapAuthenticatorService to add AccountManager accounts for POP/IMAP accounts; setup appropriate stanzas in AndroidManifest and add related xml files * Update AccountSettings to use SetupData Miscellaneous other changes: * Only allow valid port numbers in incoming/outgoing setup Bug: 1712475 Change-Id: Ibdac52fb2c5578b86bf3992ddb1acd10f162391a
2010-07-08 17:08:47 +00:00
toAccount.save(context);
// Don't simulate AccountManager in unit tests; this results in an NPE
// The unit tests only check EmailProvider based functionality
if (!unitTest) {
MailService.setupAccountManagerAccount(context, toAccount, email, calendar,
contacts, null);
}
result = true;
}
return result;
}
}