From 9f73249031303856670651305adff255a00918b7 Mon Sep 17 00:00:00 2001 From: Andrew Stadler Date: Wed, 3 Mar 2010 22:19:41 -0800 Subject: [PATCH] Continuing work on account migration * Prune all folders, messages & attachments that won't migrate * Clean up SSL/TLS values for better connection results & security * Move account setup lookup code to AccountSettingsUtils to share it * Cleanup config/auto-rotation settings to prevent relaunch of auto-discover or account check (from exchange). * A couple of other very small fixes Bug: 2065528 --- AndroidManifest.xml | 3 + src/com/android/email/VendorPolicyLoader.java | 2 +- .../email/activity/UpgradeAccounts.java | 147 ++++++++++++++++-- .../activity/setup/AccountSettingsUtils.java | 107 +++++++++++++ .../activity/setup/AccountSetupBasics.java | 105 +------------ .../setup/AccountSetupCheckSettings.java | 12 +- .../activity/setup/AccountSetupExchange.java | 6 +- .../android/email/mail/store/LocalStore.java | 5 +- .../android/email/VendorPolicyLoaderTest.java | 2 +- 9 files changed, 264 insertions(+), 125 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 24e12c826..3a9f2a30f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -95,9 +95,12 @@ > + diff --git a/src/com/android/email/VendorPolicyLoader.java b/src/com/android/email/VendorPolicyLoader.java index 35c170ee3..8a80359f2 100644 --- a/src/com/android/email/VendorPolicyLoader.java +++ b/src/com/android/email/VendorPolicyLoader.java @@ -16,7 +16,7 @@ package com.android.email; -import com.android.email.activity.setup.AccountSetupBasics.Provider; +import com.android.email.activity.setup.AccountSettingsUtils.Provider; import android.content.Context; import android.content.pm.ApplicationInfo; diff --git a/src/com/android/email/activity/UpgradeAccounts.java b/src/com/android/email/activity/UpgradeAccounts.java index ff3f41ee1..7c8b74f94 100644 --- a/src/com/android/email/activity/UpgradeAccounts.java +++ b/src/com/android/email/activity/UpgradeAccounts.java @@ -21,12 +21,15 @@ import com.android.email.Email; import com.android.email.LegacyConversions; import com.android.email.Preferences; import com.android.email.R; +import com.android.email.activity.setup.AccountSettingsUtils; +import com.android.email.activity.setup.AccountSettingsUtils.Provider; import com.android.email.mail.Folder; import com.android.email.mail.MessagingException; import com.android.email.mail.Store; import com.android.email.mail.store.LocalStore; import com.android.email.provider.EmailContent; import com.android.email.provider.EmailContent.AccountColumns; +import com.android.email.provider.EmailContent.HostAuth; import android.app.Activity; import android.app.ListActivity; @@ -46,15 +49,23 @@ import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; +import java.net.URI; +import java.net.URISyntaxException; + /** * This activity will be used whenever we have a large/slow bulk upgrade operation. * * Note: It's preferable to check for "accounts needing upgrade" before launching this * activity, so as to not waste time before every launch. * - * TODO: Disable orientation changes, to keep the activity from restarting on rotation. This is - * set in the manifest but for some reason it's not working. + * Note: This activity is set (in the manifest) to disregard configuration changes (e.g. rotation). + * This allows it to continue through without restarting. + * Do not attempt to define orientation-specific resources, they won't be loaded. + * * TODO: More work on actual conversions + * TODO: Confirm from donut sources the right way to ID the drafts, outbox, sent folders in IMAP + * TODO: Smarter cleanup of SSL/TLS situation, since certificates may be bad (see design spec) + * TODO: Trigger refresh after upgrade */ public class UpgradeAccounts extends ListActivity implements OnClickListener { @@ -240,7 +251,7 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { mListView.invalidateViews(); // find a less annoying way to do that break; case MSG_INC_PROGRESS: - mLegacyAccounts[msg.arg1].progress++; + mLegacyAccounts[msg.arg1].progress += msg.arg2; mListView.invalidateViews(); // find a less annoying way to do that break; case MSG_ERROR: @@ -270,9 +281,15 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { } public void incProgress(int accountNum) { + incProgress(accountNum, 1); + } + + public void incProgress(int accountNum, int incrementBy) { + if (incrementBy == 0) return; android.os.Message msg = android.os.Message.obtain(); msg.what = MSG_INC_PROGRESS; msg.arg1 = accountNum; + msg.arg2 = incrementBy; sendMessage(msg); } @@ -311,10 +328,10 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { UpgradeAccounts.this.mHandler.setMaxProgress(i, estimate); } - // Step 2: Clean out IMAP accounts + // Step 2: Scrub accounts, deleting anything we're not keeping to reclaim disk space for (int i = 0; i < mAccountInfo.length; i++) { if (mAccountInfo[i].error == null) { - cleanImapAccount(mContext, mAccountInfo[i].account, i, handler); + scrubAccount(mContext, mAccountInfo[i].account, i, handler); } } @@ -370,25 +387,52 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { } /** - * Clean out an IMAP account. Anything we can reload from server, we delete. This seems - * drastic, but it greatly reduces the risk of running out of disk space by copying everything. + * Clean out an account. + * + * For IMAP: Anything we can reload from server, we delete. This reduces the risk of running + * out of disk space by copying everything. + * For POP: Delete the trash folder (which we won't bring forward). */ - /* package */ void cleanImapAccount(Context context, Account account, int accountNum, + /* package */ static void scrubAccount(Context context, Account account, int accountNum, UIHandler handler) { String storeUri = account.getStoreUri(); - if (!storeUri.startsWith(Store.STORE_SCHEME_IMAP)) { - return; + boolean isImap = storeUri.startsWith(Store.STORE_SCHEME_IMAP); + + try { + Store store = LocalStore.newInstance(account.getLocalStoreUri(), context, null); + Folder[] folders = store.getPersonalNamespaces(); + for (Folder folder : folders) { + folder.open(Folder.OpenMode.READ_ONLY, null); + String folderName = folder.getName(); + if ("drafts".equalsIgnoreCase(folderName)) { + // do not delete drafts + } else if ("outbox".equalsIgnoreCase(folderName)) { + // do not delete outbox + } else if ("sent".equalsIgnoreCase(folderName)) { + // do not delete sent + } else if (isImap || "trash".equalsIgnoreCase(folderName)) { + Log.d(Email.LOG_TAG, "Scrub " + account.getDescription() + "." + folderName); + // for all other folders, delete the folder (and its messages & attachments) + int messageCount = folder.getMessageCount(); + folder.delete(true); + if (handler != null) { + handler.incProgress(accountNum, 1 + messageCount); + } + } + } + int pruned = ((LocalStore)store).pruneCachedAttachments(); + if (handler != null) { + handler.incProgress(accountNum, pruned); + } + } catch (MessagingException e) { + Log.d(Email.LOG_TAG, "Exception while cleaning IMAP account " + e); } - if (handler != null) { - handler.incProgress(accountNum); - } - } /** * Copy an account. */ - /* package */ void copyAccount(Context context, Account account, int accountNum, + /* package */ static void copyAccount(Context context, Account account, int accountNum, UIHandler handler) { // If already exists- just skip it int existCount = EmailContent.count(context, EmailContent.Account.CONTENT_URI, @@ -402,6 +446,7 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { } // Create the new account and write it EmailContent.Account newAccount = LegacyConversions.makeAccount(context, account); + cleanupConnections(context, newAccount, account); newAccount.save(context); if (handler != null) { handler.incProgress(accountNum); @@ -415,7 +460,8 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { /** * Delete an account */ - /* package */ void deleteAccountStore(Context context, Account account, UIHandler handler) { + /* package */ static void deleteAccountStore(Context context, Account account, + UIHandler handler) { try { Store store = LocalStore.newInstance(account.getLocalStoreUri(), context, null); store.delete(); @@ -427,4 +473,73 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener { } } + /** + * Cleanup SSL, TLS, etc for each converted account. + */ + /* package */ static void cleanupConnections(Context context, EmailContent.Account newAccount, + Account account) { + // 1. Look up provider for this email address + String email = newAccount.mEmailAddress; + int atSignPos = email.lastIndexOf('@'); + String domain = email.substring(atSignPos + 1); + Provider p = AccountSettingsUtils.findProviderForDomain(context, domain); + + // 2. If provider found, just use its settings (overriding what user had) + // This is drastic but most reliable. Note: This also benefits from newer provider + // data that might be found in a vendor policy module. + if (p != null) { + // Incoming + try { + URI incomingUriTemplate = p.incomingUriTemplate; + String incomingUsername = newAccount.mHostAuthRecv.mLogin; + String incomingPassword = newAccount.mHostAuthRecv.mPassword; + URI incomingUri = new URI(incomingUriTemplate.getScheme(), incomingUsername + ":" + + incomingPassword, incomingUriTemplate.getHost(), + incomingUriTemplate.getPort(), incomingUriTemplate.getPath(), null, null); + newAccount.mHostAuthRecv.setStoreUri(incomingUri.toString()); + } catch (URISyntaxException e) { + // Ignore - just use the data we copied across (for better or worse) + } + // Outgoing + try { + URI outgoingUriTemplate = p.outgoingUriTemplate; + String outgoingUsername = newAccount.mHostAuthSend.mLogin; + String outgoingPassword = newAccount.mHostAuthSend.mPassword; + URI outgoingUri = new URI(outgoingUriTemplate.getScheme(), outgoingUsername + ":" + + outgoingPassword, outgoingUriTemplate.getHost(), + outgoingUriTemplate.getPort(), outgoingUriTemplate.getPath(), null, null); + newAccount.mHostAuthSend.setStoreUri(outgoingUri.toString()); + } catch (URISyntaxException e) { + // Ignore - just use the data we copied across (for better or worse) + } + Log.d(Email.LOG_TAG, "Rewriting connection details for " + account.getDescription()); + return; + } + + // 3. Otherwise, use simple heuristics to adjust connection and attempt to keep it + // reliable. NOTE: These are the "legacy" ssl/tls encodings, not the ones in + // the current provider. + newAccount.mHostAuthRecv.mFlags |= HostAuth.FLAG_TRUST_ALL_CERTIFICATES; + String receiveUri = account.getStoreUri(); + if (receiveUri.contains("+ssl+")) { + // non-optional SSL - keep as is, with trust all + } else if (receiveUri.contains("+ssl")) { + // optional SSL - TBD + } else if (receiveUri.contains("+tls+")) { + // non-optional TLS - keep as is, with trust all + } else if (receiveUri.contains("+tls")) { + // optional TLS - TBD + } + newAccount.mHostAuthSend.mFlags |= HostAuth.FLAG_TRUST_ALL_CERTIFICATES; + String sendUri = account.getSenderUri(); + if (sendUri.contains("+ssl+")) { + // non-optional SSL - keep as is, with trust all + } else if (sendUri.contains("+ssl")) { + // optional SSL - TBD + } else if (sendUri.contains("+tls+")) { + // non-optional TLS - keep as is, with trust all + } else if (sendUri.contains("+tls")) { + // optional TLS - TBD + } + } } diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java index 696e78452..34187104d 100644 --- a/src/com/android/email/activity/setup/AccountSettingsUtils.java +++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java @@ -17,11 +17,19 @@ package com.android.email.activity.setup; import com.android.email.AccountBackupRestore; +import com.android.email.Email; +import com.android.email.R; +import com.android.email.VendorPolicyLoader; import com.android.email.provider.EmailContent; import com.android.email.provider.EmailContent.AccountColumns; import android.content.ContentValues; import android.content.Context; +import android.content.res.XmlResourceParser; +import android.util.Log; + +import java.io.Serializable; +import java.net.URI; public class AccountSettingsUtils { @@ -50,4 +58,103 @@ public class AccountSettingsUtils { // Update the backup (side copy) of the accounts AccountBackupRestore.backupAccounts(context); } + + /** + * Search the list of known Email providers looking for one that matches the user's email + * domain. We check for vendor supplied values first, then we look in providers_product.xml, + * and finally by the entries in platform providers.xml. This provides a nominal override + * capability. + * + * A match is defined as any provider entry for which the "domain" attribute matches. + * + * @param domain The domain portion of the user's email address + * @return suitable Provider definition, or null if no match found + */ + public static Provider findProviderForDomain(Context context, String domain) { + Provider p = VendorPolicyLoader.getInstance(context).findProviderForDomain(domain); + if (p == null) { + p = findProviderForDomain(context, domain, R.xml.providers_product); + } + if (p == null) { + p = findProviderForDomain(context, domain, R.xml.providers); + } + return p; + } + + /** + * Search a single resource containing known Email provider definitions. + * + * @param domain The domain portion of the user's email address + * @param resourceId Id of the provider resource to scan + * @return suitable Provider definition, or null if no match found + */ + private static Provider findProviderForDomain(Context context, String domain, int resourceId) { + try { + XmlResourceParser xml = context.getResources().getXml(resourceId); + int xmlEventType; + Provider provider = null; + while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { + if (xmlEventType == XmlResourceParser.START_TAG + && "provider".equals(xml.getName()) + && domain.equalsIgnoreCase(getXmlAttribute(context, xml, "domain"))) { + provider = new Provider(); + provider.id = getXmlAttribute(context, xml, "id"); + provider.label = getXmlAttribute(context, xml, "label"); + provider.domain = getXmlAttribute(context, xml, "domain"); + provider.note = getXmlAttribute(context, xml, "note"); + } + else if (xmlEventType == XmlResourceParser.START_TAG + && "incoming".equals(xml.getName()) + && provider != null) { + provider.incomingUriTemplate = new URI(getXmlAttribute(context, xml, "uri")); + provider.incomingUsernameTemplate = getXmlAttribute(context, xml, "username"); + } + else if (xmlEventType == XmlResourceParser.START_TAG + && "outgoing".equals(xml.getName()) + && provider != null) { + provider.outgoingUriTemplate = new URI(getXmlAttribute(context, xml, "uri")); + provider.outgoingUsernameTemplate = getXmlAttribute(context, xml, "username"); + } + else if (xmlEventType == XmlResourceParser.END_TAG + && "provider".equals(xml.getName()) + && provider != null) { + return provider; + } + } + } + catch (Exception e) { + Log.e(Email.LOG_TAG, "Error while trying to load provider settings.", e); + } + return null; + } + + /** + * Attempts to get the given attribute as a String resource first, and if it fails + * returns the attribute as a simple String value. + * @param xml + * @param name + * @return the requested resource + */ + private static String getXmlAttribute(Context context, XmlResourceParser xml, String name) { + int resId = xml.getAttributeResourceValue(null, name, 0); + if (resId == 0) { + return xml.getAttributeValue(null, name); + } + else { + return context.getString(resId); + } + } + + public static class Provider implements Serializable { + private static final long serialVersionUID = 8511656164616538989L; + + public String id; + public String label; + public String domain; + public URI incomingUriTemplate; + public String incomingUsernameTemplate; + public URI outgoingUriTemplate; + public String outgoingUsernameTemplate; + public String note; + } } diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java index a0dc67bd0..d9ec7ef9a 100644 --- a/src/com/android/email/activity/setup/AccountSetupBasics.java +++ b/src/com/android/email/activity/setup/AccountSetupBasics.java @@ -24,6 +24,7 @@ import com.android.email.Utility; import com.android.email.VendorPolicyLoader; import com.android.email.activity.Debug; import com.android.email.activity.MessageList; +import com.android.email.activity.setup.AccountSettingsUtils.Provider; import com.android.email.provider.EmailContent; import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Mailbox; @@ -34,12 +35,10 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.XmlResourceParser; import android.database.Cursor; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @@ -48,7 +47,6 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; -import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; @@ -422,7 +420,7 @@ public class AccountSetupBasics extends Activity String email = mEmailView.getText().toString().trim(); String[] emailParts = email.split("@"); String domain = emailParts[1].trim(); - mProvider = findProviderForDomain(domain); + mProvider = AccountSettingsUtils.findProviderForDomain(this, domain); if (mProvider != null) { if (mProvider.note != null) { showDialog(DIALOG_NOTE); @@ -514,103 +512,4 @@ public class AccountSetupBasics extends Activity break; } } - - /** - * Attempts to get the given attribute as a String resource first, and if it fails - * returns the attribute as a simple String value. - * @param xml - * @param name - * @return the requested resource - */ - private String getXmlAttribute(XmlResourceParser xml, String name) { - int resId = xml.getAttributeResourceValue(null, name, 0); - if (resId == 0) { - return xml.getAttributeValue(null, name); - } - else { - return getString(resId); - } - } - - /** - * Search the list of known Email providers looking for one that matches the user's email - * domain. We check for vendor supplied values first, then we look in providers_product.xml - * first, finally by the entries in platform providers.xml. This provides a nominal override - * capability. - * - * A match is defined as any provider entry for which the "domain" attribute matches. - * - * @param domain The domain portion of the user's email address - * @return suitable Provider definition, or null if no match found - */ - private Provider findProviderForDomain(String domain) { - Provider p = VendorPolicyLoader.getInstance(this).findProviderForDomain(domain); - if (p == null) { - p = findProviderForDomain(domain, R.xml.providers_product); - } - if (p == null) { - p = findProviderForDomain(domain, R.xml.providers); - } - return p; - } - - /** - * Search a single resource containing known Email provider definitions. - * - * @param domain The domain portion of the user's email address - * @param resourceId Id of the provider resource to scan - * @return suitable Provider definition, or null if no match found - */ - private Provider findProviderForDomain(String domain, int resourceId) { - try { - XmlResourceParser xml = getResources().getXml(resourceId); - int xmlEventType; - Provider provider = null; - while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { - if (xmlEventType == XmlResourceParser.START_TAG - && "provider".equals(xml.getName()) - && domain.equalsIgnoreCase(getXmlAttribute(xml, "domain"))) { - provider = new Provider(); - provider.id = getXmlAttribute(xml, "id"); - provider.label = getXmlAttribute(xml, "label"); - provider.domain = getXmlAttribute(xml, "domain"); - provider.note = getXmlAttribute(xml, "note"); - } - else if (xmlEventType == XmlResourceParser.START_TAG - && "incoming".equals(xml.getName()) - && provider != null) { - provider.incomingUriTemplate = new URI(getXmlAttribute(xml, "uri")); - provider.incomingUsernameTemplate = getXmlAttribute(xml, "username"); - } - else if (xmlEventType == XmlResourceParser.START_TAG - && "outgoing".equals(xml.getName()) - && provider != null) { - provider.outgoingUriTemplate = new URI(getXmlAttribute(xml, "uri")); - provider.outgoingUsernameTemplate = getXmlAttribute(xml, "username"); - } - else if (xmlEventType == XmlResourceParser.END_TAG - && "provider".equals(xml.getName()) - && provider != null) { - return provider; - } - } - } - catch (Exception e) { - Log.e(Email.LOG_TAG, "Error while trying to load provider settings.", e); - } - return null; - } - - public static class Provider implements Serializable { - private static final long serialVersionUID = 8511656164616538989L; - - public String id; - public String label; - public String domain; - public URI incomingUriTemplate; - public String incomingUsernameTemplate; - public URI outgoingUriTemplate; - public String outgoingUsernameTemplate; - public String note; - } } diff --git a/src/com/android/email/activity/setup/AccountSetupCheckSettings.java b/src/com/android/email/activity/setup/AccountSetupCheckSettings.java index 84e9c251e..192dcee2f 100644 --- a/src/com/android/email/activity/setup/AccountSetupCheckSettings.java +++ b/src/com/android/email/activity/setup/AccountSetupCheckSettings.java @@ -16,6 +16,7 @@ package com.android.email.activity.setup; +import com.android.email.Email; import com.android.email.R; import com.android.email.mail.AuthenticationFailedException; import com.android.email.mail.CertificateValidationException; @@ -32,6 +33,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Process; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @@ -42,8 +44,9 @@ import android.widget.TextView; * Checks the given settings to make sure that they can be used to send and * receive mail. * - * XXX NOTE: The manifest for this app has it ignore config changes, because + * XXX NOTE: The manifest for this activity has it ignore config changes, because * it doesn't correctly deal with restarting while its thread is running. + * Do not attempt to define orientation-specific resources, they won't be loaded. */ public class AccountSetupCheckSettings extends Activity implements OnClickListener { @@ -149,6 +152,7 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen if (mAutoDiscover) { String userName = intent.getStringExtra(EXTRA_AUTO_DISCOVER_USERNAME); String password = intent.getStringExtra(EXTRA_AUTO_DISCOVER_PASSWORD); + Log.d(Email.LOG_TAG, "Begin auto-discover for " + userName); Store store = Store.getInstance( mAccount.getStoreUri(AccountSetupCheckSettings.this), getApplication(), null); @@ -173,7 +177,9 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen EmailServiceProxy.AUTO_DISCOVER_BUNDLE_HOST_AUTH)); setResult(RESULT_OK, resultIntent); finish(); - } + // auto-discover is never combined with other ops, so exit now + return; + } } if (mDestroyed) { return; @@ -183,6 +189,7 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen return; } if (mCheckIncoming) { + Log.d(Email.LOG_TAG, "Begin check of incoming email settings"); setMessage(R.string.account_setup_check_settings_check_incoming_msg); Store store = Store.getInstance( mAccount.getStoreUri(AccountSetupCheckSettings.this), @@ -197,6 +204,7 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen return; } if (mCheckOutgoing) { + Log.d(Email.LOG_TAG, "Begin check of outgoing email settings"); setMessage(R.string.account_setup_check_settings_check_outgoing_msg); Sender sender = Sender.getInstance(getApplication(), mAccount.getSenderUri(AccountSetupCheckSettings.this)); diff --git a/src/com/android/email/activity/setup/AccountSetupExchange.java b/src/com/android/email/activity/setup/AccountSetupExchange.java index 92a8dfbbf..3c561ca16 100644 --- a/src/com/android/email/activity/setup/AccountSetupExchange.java +++ b/src/com/android/email/activity/setup/AccountSetupExchange.java @@ -78,6 +78,10 @@ import java.net.URISyntaxException; * Write new values (save to provider) * Proceed to options screen * finish() (removes self from back stack) + * + * NOTE: The manifest for this activity has it ignore config changes, because + * we don't want to restart on every orientation - this would launch autodiscover again. + * Do not attempt to define orientation-specific resources, they won't be loaded. */ public class AccountSetupExchange extends Activity implements OnClickListener, OnCheckedChangeListener { @@ -264,7 +268,7 @@ public class AccountSetupExchange extends Activity implements OnClickListener, } String protocol = hostAuth.mProtocol; - if (protocol == null && !protocol.startsWith("eas")) { + if (protocol == null || !protocol.startsWith("eas")) { throw new Error("Unknown account type: " + account.getStoreUri(this)); } diff --git a/src/com/android/email/mail/store/LocalStore.java b/src/com/android/email/mail/store/LocalStore.java index eb44d1c77..01cc16169 100644 --- a/src/com/android/email/mail/store/LocalStore.java +++ b/src/com/android/email/mail/store/LocalStore.java @@ -383,7 +383,8 @@ public class LocalStore extends Store implements PersistentDataCallbacks { /** * Deletes all cached attachments for the entire store. */ - public void pruneCachedAttachments() throws MessagingException { + public int pruneCachedAttachments() throws MessagingException { + int prunedCount = 0; File[] files = mAttachmentsDir.listFiles(); for (File file : files) { if (file.exists()) { @@ -426,8 +427,10 @@ public class LocalStore extends Store implements PersistentDataCallbacks { if (!file.delete()) { file.deleteOnExit(); } + prunedCount++; } } + return prunedCount; } /** diff --git a/tests/src/com/android/email/VendorPolicyLoaderTest.java b/tests/src/com/android/email/VendorPolicyLoaderTest.java index d7e3d89ec..9fcda930b 100644 --- a/tests/src/com/android/email/VendorPolicyLoaderTest.java +++ b/tests/src/com/android/email/VendorPolicyLoaderTest.java @@ -16,7 +16,7 @@ package com.android.email; -import com.android.email.activity.setup.AccountSetupBasics.Provider; +import com.android.email.activity.setup.AccountSettingsUtils.Provider; import android.content.Context; import android.os.Bundle;