Email split, part neuf: Setup, logging, attachment glue

* Make "Exchange" option in account setup depend upon availability of the
  Exchange EmailService
* Make presence of Exchange logging depend upon availability of the
  Exchange EmailService
* Make AttachmentDownloadService use service rather than ExchangeService
  class
* Move SSLUtils to emailcommon/utility
* Move account manager type defs to emailcommon/AccountManagerTypes
* Update proguard.flags
* This is the penultimate CL for the Email package itself; the next CL
  creates a clean, SDK-compatible Email application

Bug: 3442973
Change-Id: I9162cf5fa6b5a043ded0fdd1e25fd3ce5948ad8f
This commit is contained in:
Marc Blank 2011-02-12 18:56:09 -08:00
parent 31d9acbf06
commit 3a5c1fb274
37 changed files with 379 additions and 323 deletions

View File

@ -1,11 +1,11 @@
# keep names that are used by reflection.
-keep class com.android.email.provider.EmailContent$Account
-keep class com.android.emailcommon.provider.EmailContent$Account
-keepclasseswithmembers class * {
public static void actionEditIncomingSettings(android.app.Activity, int, com.android.email.provider.EmailContent$Account);
public static void actionEditIncomingSettings(android.app.Activity, int, com.android.emailcommon.provider.EmailContent$Account);
}
-keepclasseswithmembers class * {
public static void actionEditOutgoingSettings(android.app.Activity, int, com.android.email.provider.EmailContent$Account);
public static void actionEditOutgoingSettings(android.app.Activity, int, com.android.emailcommon.provider.EmailContent$Account);
}
-keepclasseswithmembers class * {
@ -48,7 +48,7 @@
}
-keepclasseswithmembers class com.android.emailcommon.service.PolicySet {
<init>(com.android.email.provider.EmailContent$Account);
<init>(com.android.emailcommon.provider.EmailContent$Account);
<init>(int, int, int, int, boolean, int, int, boolean);
}
@ -64,11 +64,11 @@
*** log(android.database.Cursor);
}
-keepclasseswithmembers class com.android.email.provider.EmailProvider {
-keepclasseswithmembers class com.android.emailcommon.provider.EmailProvider {
*** getReadableDatabase(android.content.Context);
}
-keepclasseswithmembers class com.android.email.provider.EmailContent$Attachment {
-keepclasseswithmembers class com.android.emailcommon.provider.EmailContent$Attachment {
*** createUniqueFile(java.lang.String);
}
@ -162,7 +162,7 @@
*** size();
}
-keepclasseswithmembers class com.android.email.provider.EmailContent$Account {
-keepclasseswithmembers class com.android.emailcommon.provider.EmailContent$Account {
*** getShortcutSafeUri();
}

View File

@ -17,6 +17,7 @@
package com.android.email;
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;
@ -117,7 +118,7 @@ public class AccountBackupRestore {
// 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, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
fromAccount.mEmailAddress, AccountManagerTypes.TYPE_EXCHANGE);
boolean syncContacts = ContentResolver.getSyncAutomatically(acct,
ContactsContract.AUTHORITY);
if (syncContacts) {

View File

@ -21,8 +21,8 @@ import com.android.email.mail.store.Pop3Store.Pop3Message;
import com.android.emailcommon.Api;
import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.AuthenticationFailedException;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.mail.Folder.MessageRetrievalListener;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
@ -273,18 +273,18 @@ public class Controller {
}
/**
* Enable/disable logging for external sync services
* Set logging flags for external sync services
*
* Generally this should be called by anybody who changes Email.DEBUG
*/
public void serviceLogging(int debugEnabled) {
public void serviceLogging(int debugFlags) {
IEmailService service = ExchangeUtils.getExchangeService(mContext, mServiceCallback);
try {
service.setLogging(debugEnabled);
service.setLogging(debugFlags);
} catch (RemoteException e) {
// TODO Change exception handling to be consistent with however this method
// is implemented for other protocols
Log.d("updateMailboxList", "RemoteException" + e);
Log.d("setLogging", "RemoteException" + e);
}
}

View File

@ -23,8 +23,8 @@ import com.android.email.service.MailService;
import com.android.emailcommon.Logging;
import com.android.emailcommon.TempDirectory;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import android.app.Application;
import android.content.ComponentName;
@ -67,6 +67,11 @@ public class Email extends Application {
*/
public static final boolean LOGD = false;
// Exchange debugging flags (passed to Exchange, when available, via EmailServiceProxy)
public static boolean DEBUG_EXCHANGE = false;
public static boolean DEBUG_EXCHANGE_VERBOSE = false;
public static boolean DEBUG_EXCHANGE_FILE = false;
/**
* If true, inhibit hardware graphics acceleration in UI (for a/b testing)
*/
@ -90,9 +95,6 @@ public class Email extends Application {
*/
private static boolean sAccountsChangedNotification = false;
public static final String EXCHANGE_ACCOUNT_MANAGER_TYPE = "com.android.exchange";
public static final String POP_IMAP_ACCOUNT_MANAGER_TYPE = "com.android.email";
private static String sMessageDecodeErrorString;
private static Thread sUiThread;
@ -213,14 +215,14 @@ public class Email extends Application {
* Load enabled debug flags from the preferences and update the EAS debug flag.
*/
public static void updateLoggingFlags(Context context) {
//EXCHANGE-REMOVE-SECTION-START
Preferences prefs = Preferences.getPreferences(context);
int debugLogging = prefs.getEnableDebugLogging() ? Eas.DEBUG_BIT : 0;
int exchangeLogging = prefs.getEnableExchangeLogging() ? Eas.DEBUG_EXCHANGE_BIT : 0;
int fileLogging = prefs.getEnableExchangeFileLogging() ? Eas.DEBUG_FILE_BIT : 0;
int debugBits = debugLogging | exchangeLogging | fileLogging;
int debugLogging = prefs.getEnableDebugLogging() ? EmailServiceProxy.DEBUG_BIT : 0;
int verboseLogging =
prefs.getEnableExchangeLogging() ? EmailServiceProxy.DEBUG_VERBOSE_BIT : 0;
int fileLogging =
prefs.getEnableExchangeFileLogging() ? EmailServiceProxy.DEBUG_FILE_BIT : 0;
int debugBits = debugLogging | verboseLogging | fileLogging;
Controller.getInstance(context).serviceLogging(debugBits);
//EXCHANGE-REMOVE-SECTION-END
}
/**

View File

@ -20,8 +20,6 @@ import com.android.emailcommon.Api;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.exchange.CalendarSyncEnabler;
import com.android.exchange.ExchangeService;
import android.app.Service;
import android.content.Context;
@ -38,9 +36,7 @@ public class ExchangeUtils {
* Starts the service for Exchange, if supported.
*/
public static void startExchangeService(Context context) {
//EXCHANGE-REMOVE-SECTION-START
context.startService(new Intent(context, ExchangeService.class));
//EXCHANGE-REMOVE-SECTION-END
context.startService(new Intent(EmailServiceProxy.EXCHANGE_INTENT));
}
/**
@ -52,23 +48,25 @@ public class ExchangeUtils {
*/
public static IEmailService getExchangeService(Context context,
IEmailServiceCallback callback) {
IEmailService ret = null;
//EXCHANGE-REMOVE-SECTION-START
ret = new EmailServiceProxy(context, ExchangeService.class, callback);
//EXCHANGE-REMOVE-SECTION-END
if (ret == null) {
ret = NullEmailService.INSTANCE;
}
return ret;
return new EmailServiceProxy(context, EmailServiceProxy.EXCHANGE_INTENT, callback);
}
/**
* Determine if the Exchange package is loaded
*
* TODO: This should be dynamic and data-driven for all account types, not just hardcoded
* like this.
*/
public static boolean isExchangeAvailable(Context context) {
return new EmailServiceProxy(context, EmailServiceProxy.EXCHANGE_INTENT, null).test();
}
/**
* Enable calendar sync for all the existing exchange accounts, and post a notification if any.
*/
public static void enableEasCalendarSync(Context context) {
//EXCHANGE-REMOVE-SECTION-START
new CalendarSyncEnabler(context).enableEasCalendarSync();
//EXCHANGE-REMOVE-SECTION-END
// *** TODO: Is this still necessary?
//new CalendarSyncEnabler(context).enableEasCalendarSync();
}
/**
@ -83,6 +81,10 @@ public class ExchangeUtils {
public static class NullEmailService extends Service implements IEmailService {
public static final NullEmailService INSTANCE = new NullEmailService();
public int getApiLevel() {
return Api.LEVEL;
}
public Bundle autoDiscover(String userName, String password) throws RemoteException {
return Bundle.EMPTY;
}
@ -143,11 +145,6 @@ public class ExchangeUtils {
return null;
}
@Override
public int getApiLevel() throws RemoteException {
return Api.LEVEL;
}
@Override
public IBinder onBind(Intent intent) {
return null;

View File

@ -18,7 +18,7 @@ package com.android.email.activity;
import com.android.email.R;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.internal.util.ArrayUtils;
import com.android.emailcommon.utility.Utility;
import android.content.Context;
import android.content.res.Resources;
@ -73,7 +73,7 @@ public class MailboxListItem extends RelativeLayout {
if ((mMailboxId < 0) || (itemMailbox == mMailboxId)) {
return false;
}
return !ArrayUtils.contains(Mailbox.INVALID_DROP_TARGETS, mMailboxType);
return !Utility.arrayContains(Mailbox.INVALID_DROP_TARGETS, mMailboxType);
}
public void setDropTargetBackground(boolean dragInProgress, long itemMailbox) {

View File

@ -20,6 +20,7 @@ import com.android.email.Email;
import com.android.email.R;
import com.android.email.mail.Sender;
import com.android.email.mail.Store;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.CalendarProviderStub;
import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.MessagingException;
@ -543,7 +544,7 @@ public class AccountSettingsFragment extends PreferenceFragment {
mSyncEmail = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_EMAIL);
if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) {
android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
mSyncContacts.setChecked(ContentResolver
.getSyncAutomatically(acct, ContactsContract.AUTHORITY));
mSyncContacts.setOnPreferenceChangeListener(mPreferenceChangeListener);
@ -630,7 +631,7 @@ public class AccountSettingsFragment extends PreferenceFragment {
if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) {
android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
ContentResolver.setSyncAutomatically(acct, ContactsContract.AUTHORITY,
mSyncContacts.isChecked());
ContentResolver.setSyncAutomatically(acct, CalendarProviderStub.AUTHORITY,

View File

@ -16,6 +16,7 @@
package com.android.email.activity.setup;
import com.android.email.ExchangeUtils;
import com.android.email.R;
import com.android.email.VendorPolicyLoader;
import com.android.email.activity.ActivityHelper;
@ -63,14 +64,15 @@ public class AccountSetupAccountType extends AccountSetupActivity implements OnC
((Button)findViewById(R.id.pop)).setOnClickListener(this);
((Button)findViewById(R.id.imap)).setOnClickListener(this);
final Button exchangeButton = (Button) findViewById(R.id.exchange);
exchangeButton.setOnClickListener(this);
exchangeButton.setVisibility(View.INVISIBLE);
final Button previousButton = (Button) findViewById(R.id.previous);
if (previousButton != null) previousButton.setOnClickListener(this);
// TODO If we decide to exclude the Exchange option in POP_IMAP mode, use the following line
// instead of the line that follows it
//if (isExchangeAvailable() && flowMode != SetupData.FLOW_MODE_POP_IMAP) {
if (isExchangeAvailable()) {
//if (ExchangeUtils.isExchangeAvailable(this) && flowMode != SetupData.FLOW_MODE_POP_IMAP) {
if (ExchangeUtils.isExchangeAvailable(this)) {
exchangeButton.setOnClickListener(this);
exchangeButton.setVisibility(View.VISIBLE);
if (VendorPolicyLoader.getInstance(this).useAlternateExchangeStrings()) {
exchangeButton.setText(
@ -141,25 +143,6 @@ public class AccountSetupAccountType extends AccountSetupActivity implements OnC
finish();
}
/**
* Determine if we can show the "exchange" option
*
* TODO: This should be dynamic and data-driven for all account types, not just hardcoded
* like this.
*/
private boolean isExchangeAvailable() {
//EXCHANGE-REMOVE-SECTION-START
try {
URI uri = new URI(SetupData.getAccount().getStoreUri(this));
uri = new URI("eas", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
Store.StoreInfo storeInfo = Store.StoreInfo.getStoreInfo(uri.toString(), this);
return (storeInfo != null && checkAccountInstanceLimit(storeInfo));
} catch (URISyntaxException e) {
}
//EXCHANGE-REMOVE-SECTION-END
return false;
}
/**
* If the optional store specifies a limit on the number of accounts, make sure that we
* don't violate that limit.

View File

@ -20,11 +20,11 @@ import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.ExchangeUtils;
import com.android.email.R;
import com.android.emailcommon.Device;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.ExchangeService;
import android.app.Activity;
import android.content.Context;
@ -122,15 +122,12 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
mPasswordView.addTextChangedListener(validationTextWatcher);
mServerView.addTextChangedListener(validationTextWatcher);
//EXCHANGE-REMOVE-SECTION-START
// Show device ID
try {
String deviceId = ExchangeService.getDeviceId(context);
String deviceId = Device.getDeviceId(context);
((TextView) view.findViewById(R.id.device_id)).setText(deviceId);
} catch (IOException ignore) {
// There's nothing we can do here...
} catch (IOException e) {
// Not required
}
//EXCHANGE-REMOVE-SECTION-END
// Additional setup only used while in "settings" mode
onCreateViewSettingsMode(view);

View File

@ -17,12 +17,11 @@
package com.android.email.activity.setup;
import com.android.email.Email;
import com.android.email.ExchangeUtils;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.service.MailService;
import com.android.emailcommon.Logging;
import com.android.exchange.Eas;
import com.android.exchange.utility.FileLogger;
import android.app.Fragment;
import android.content.Context;
@ -34,8 +33,8 @@ import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
public class DebugFragment extends Fragment implements OnCheckedChangeListener,
View.OnClickListener {
@ -66,19 +65,23 @@ public class DebugFragment extends Fragment implements OnCheckedChangeListener,
mEnableDebugLoggingView = (CheckBox) view.findViewById(R.id.debug_logging);
mEnableDebugLoggingView.setChecked(Email.DEBUG);
//EXCHANGE-REMOVE-SECTION-START
mEnableExchangeLoggingView = (CheckBox) view.findViewById(R.id.exchange_logging);
mEnableExchangeFileLoggingView = (CheckBox) view.findViewById(R.id.exchange_file_logging);
mEnableExchangeLoggingView.setChecked(Eas.PARSER_LOG);
mEnableExchangeFileLoggingView.setChecked(Eas.FILE_LOG);
//EXCHANGE-REMOVE-SECTION-END
mEnableExchangeFileLoggingView =
(CheckBox) view.findViewById(R.id.exchange_file_logging);
// Note: To prevent recursion while presetting checkboxes, assign all listeners last
mEnableDebugLoggingView.setOnCheckedChangeListener(this);
//EXCHANGE-REMOVE-SECTION-START
mEnableExchangeLoggingView.setOnCheckedChangeListener(this);
mEnableExchangeFileLoggingView.setOnCheckedChangeListener(this);
//EXCHANGE-REMOVE-SECTION-END
boolean exchangeAvailable = ExchangeUtils.isExchangeAvailable(context);
if (exchangeAvailable) {
mEnableExchangeLoggingView.setChecked(Email.DEBUG_EXCHANGE_VERBOSE);
mEnableExchangeFileLoggingView.setChecked(Email.DEBUG_EXCHANGE_FILE);
mEnableExchangeLoggingView.setOnCheckedChangeListener(this);
mEnableExchangeFileLoggingView.setOnCheckedChangeListener(this);
} else {
mEnableExchangeLoggingView.setVisibility(View.GONE);
mEnableExchangeFileLoggingView.setVisibility(View.GONE);
}
view.findViewById(R.id.clear_webview_cache).setOnClickListener(this);
@ -99,21 +102,19 @@ public class DebugFragment extends Fragment implements OnCheckedChangeListener,
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (buttonView.getId()) {
case R.id.debug_logging:
mPreferences.setEnableDebugLogging(isChecked);
Email.DEBUG = isChecked;
mPreferences.setEnableDebugLogging(Email.DEBUG);
Email.DEBUG_EXCHANGE = isChecked;
break;
//EXCHANGE-REMOVE-SECTION-START
case R.id.exchange_logging:
case R.id.exchange_logging:
mPreferences.setEnableExchangeLogging(isChecked);
Email.DEBUG_EXCHANGE_VERBOSE = isChecked;
break;
case R.id.exchange_file_logging:
mPreferences.setEnableExchangeFileLogging(isChecked);
if (!isChecked) {
FileLogger.close();
}
Email.DEBUG_EXCHANGE_FILE = isChecked;
break;
//EXCHANGE-REMOVE-SECTION-END
case R.id.debug_disable_graphics_acceleration:
case R.id.debug_disable_graphics_acceleration:
Email.sDebugInhibitGraphicsAcceleration = isChecked;
mPreferences.setInhibitGraphicsAcceleration(isChecked);
break;

View File

@ -21,6 +21,7 @@ import com.android.email.mail.Transport;
import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.CertificateValidationException;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.utility.SSLUtils;
import android.util.Config;
import android.util.Log;

View File

@ -19,6 +19,7 @@ package com.android.email.provider;
import com.android.email.Email;
import com.android.email.provider.ContentCache.CacheToken;
import com.android.email.service.AttachmentDownloadService;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
@ -785,7 +786,7 @@ public class EmailProvider extends ContentProvider {
// Versions >= 5 require that data be preserved!
if (oldVersion < 5) {
android.accounts.Account[] accounts = AccountManager.get(mContext)
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
for (android.accounts.Account account: accounts) {
AccountManager.get(mContext).removeAccount(account, null, null);
}

View File

@ -17,11 +17,10 @@
package com.android.email.service;
import com.android.email.AttachmentInfo;
import com.android.email.Controller.ControllerService;
import com.android.email.Email;
import com.android.email.EmailConnectivityManager;
import com.android.email.NotificationController;
import com.android.email.Controller.ControllerService;
import com.android.email.ExchangeUtils.NullEmailService;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
@ -31,7 +30,6 @@ import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.ExchangeService;
import android.accounts.AccountManager;
import android.app.AlarmManager;
@ -99,8 +97,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
/*package*/ final DownloadSet mDownloadSet = new DownloadSet(new DownloadComparator());
private final HashMap<Long, Class<? extends Service>> mAccountServiceMap =
new HashMap<Long, Class<? extends Service>>();
private final HashMap<Long, Intent> mAccountServiceMap = new HashMap<Long, Intent>();
// A map of attachment storage used per account
// NOTE: This map is not kept current in terms of deletions (i.e. it stores the last calculated
// amount plus the size of any new attachments laoded). If and when we reach the per-account
@ -350,11 +347,12 @@ public class AttachmentDownloadService extends Service implements Runnable {
while (c.moveToNext()) {
long accountKey = c.getLong(AttachmentInfo.COLUMN_ACCOUNT_KEY);
long id = c.getLong(AttachmentInfo.COLUMN_ID);
if (getServiceClassForAccount(accountKey) == null) {
Account account = Account.restoreAccountWithId(mContext, accountKey);
if (account == null) {
// Clean up this orphaned attachment; there's no point in keeping it
// around; then try to find another one
EmailContent.delete(mContext, Attachment.CONTENT_URI, id);
} else if (canPrefetchForAccount(accountKey, cacheDir)) {
} else if (canPrefetchForAccount(account, cacheDir)) {
// Check that the attachment meets system requirements for download
AttachmentInfo info = new AttachmentInfo(mContext, c);
if (info.isEligibleForDownload()) {
@ -417,6 +415,37 @@ public class AttachmentDownloadService extends Service implements Runnable {
processQueue();
}
/**
* Attempt to execute the DownloadRequest, enforcing the maximum downloads per account
* parameter
* @param req the DownloadRequest
* @return whether or not the download was started
*/
/*package*/ synchronized boolean tryStartDownload(DownloadRequest req) {
Intent intent = getServiceIntentForAccount(req.accountId);
if (intent == null) return false;
// Do not download the same attachment multiple times
boolean alreadyInProgress = mDownloadsInProgress.get(req.attachmentId) != null;
if (alreadyInProgress) return false;
try {
if (Email.DEBUG) {
Log.d(TAG, ">> Starting download for attachment #" + req.attachmentId);
}
startDownload(intent, req);
} catch (RemoteException e) {
// TODO: Consider whether we need to do more in this case...
// For now, fix up our data to reflect the failure
cancelDownload(req);
}
return true;
}
private synchronized DownloadRequest getDownloadInProgress(long attachmentId) {
return mDownloadsInProgress.get(attachmentId);
}
/**
* Do the work of starting an attachment download using the EmailService interface, and
* set our watchdog alarm
@ -425,17 +454,15 @@ public class AttachmentDownloadService extends Service implements Runnable {
* @param req the DownloadRequest
* @throws RemoteException
*/
private void startDownload(Class<? extends Service> serviceClass, DownloadRequest req)
private void startDownload(Intent intent, DownloadRequest req)
throws RemoteException {
File file = AttachmentUtilities.getAttachmentFilename(mContext, req.accountId,
req.attachmentId);
req.startTime = System.currentTimeMillis();
req.inProgress = true;
mDownloadsInProgress.put(req.attachmentId, req);
if (serviceClass.equals(NullEmailService.class)) return;
// Now, call the service
EmailServiceProxy proxy =
new EmailServiceProxy(mContext, serviceClass, mServiceCallback);
new EmailServiceProxy(mContext, intent, mServiceCallback);
proxy.loadAttachment(req.attachmentId, file.getAbsolutePath(),
AttachmentUtilities.getAttachmentUri(req.accountId, req.attachmentId)
.toString(), req.priority != PRIORITY_FOREGROUND);
@ -451,37 +478,6 @@ public class AttachmentDownloadService extends Service implements Runnable {
mWatchdogPendingIntent);
}
private synchronized DownloadRequest getDownloadInProgress(long attachmentId) {
return mDownloadsInProgress.get(attachmentId);
}
/**
* Attempt to execute the DownloadRequest, enforcing the maximum downloads per account
* parameter
* @param req the DownloadRequest
* @return whether or not the download was started
*/
/*package*/ synchronized boolean tryStartDownload(DownloadRequest req) {
Class<? extends Service> serviceClass = getServiceClassForAccount(req.accountId);
if (serviceClass == null) return false;
// Do not download the same attachment multiple times
boolean alreadyInProgress = mDownloadsInProgress.get(req.attachmentId) != null;
if (alreadyInProgress) return false;
try {
if (Email.DEBUG) {
Log.d(TAG, ">> Starting download for attachment #" + req.attachmentId);
}
startDownload(serviceClass, req);
} catch (RemoteException e) {
// TODO: Consider whether we need to do more in this case...
// For now, fix up our data to reflect the failure
cancelDownload(req);
}
return true;
}
private void cancelDownload(DownloadRequest req) {
mDownloadsInProgress.remove(req.attachmentId);
req.inProgress = false;
@ -670,31 +666,28 @@ public class AttachmentDownloadService extends Service implements Runnable {
}
/**
* Return the class of the service used by the account type of the provided account id. We
* Return an Intent to be used used based on the account type of the provided account id. We
* cache the results to avoid repeated database access
* @param accountId the id of the account
* @return the service class for the account or null (if the account no longer exists)
* @return the Intent to be used for the account or null (if the account no longer exists)
*/
private synchronized Class<? extends Service> getServiceClassForAccount(long accountId) {
// TODO: We should have some more data-driven way of determining the service class. I'd
// suggest adding an attribute in the stores.xml file
Class<? extends Service> serviceClass = mAccountServiceMap.get(accountId);
if (serviceClass == null) {
private synchronized Intent getServiceIntentForAccount(long accountId) {
// TODO: We should have some more data-driven way of determining the service intent.
Intent serviceIntent = mAccountServiceMap.get(accountId);
if (serviceIntent == null) {
String protocol = Account.getProtocol(mContext, accountId);
if (protocol == null) return null;
serviceClass = ControllerService.class;
// EXCHANGE-REMOVE-SECTION-START
serviceIntent = new Intent(mContext, ControllerService.class);
if (protocol.equals("eas")) {
serviceClass = ExchangeService.class;
serviceIntent = new Intent(EmailServiceProxy.EXCHANGE_INTENT);
}
// EXCHANGE-REMOVE-SECTION-END
mAccountServiceMap.put(accountId, serviceClass);
mAccountServiceMap.put(accountId, serviceIntent);
}
return serviceClass;
return serviceIntent;
}
/*protected*/ void addServiceClass(long accountId, Class<? extends Service> serviceClass) {
mAccountServiceMap.put(accountId, serviceClass);
/*package*/ void addServiceIntentForTest(long accountId, Intent intent) {
mAccountServiceMap.put(accountId, intent);
}
/*package*/ void onChange(Attachment att) {
@ -792,8 +785,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
* Determine whether an attachment can be prefetched for the given account
* @return true if download is allowed, false otherwise
*/
/*package*/ boolean canPrefetchForAccount(long accountId, File dir) {
Account account = Account.restoreAccountWithId(mContext, accountId);
public boolean canPrefetchForAccount(Account account, File dir) {
// Check account, just in case
if (account == null) return false;
// First, check preference and quickly return if prefetch isn't allowed
@ -815,7 +807,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
// Retrieve our idea of currently used attachment storage; since we don't track deletions,
// this number is the "worst case". If the number is greater than what's allowed per
// account, we walk the directory to determine the actual number
Long accountStorage = mAttachmentStorageMap.get(accountId);
Long accountStorage = mAttachmentStorageMap.get(account.mId);
if (accountStorage == null || (accountStorage > perAccountMaxStorage)) {
// Calculate the exact figure for attachment storage for this account
accountStorage = 0L;
@ -826,7 +818,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
}
}
// Cache the value
mAttachmentStorageMap.put(accountId, accountStorage);
mAttachmentStorageMap.put(account.mId, accountStorage);
}
// Return true if we're using less than the maximum per account
@ -834,7 +826,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
return true;
} else {
if (Email.DEBUG) {
Log.d(TAG, ">> Prefetch not allowed for account " + accountId + "; used " +
Log.d(TAG, ">> Prefetch not allowed for account " + account.mId + "; used " +
accountStorage + ", limit " + perAccountMaxStorage);
}
return false;

View File

@ -16,8 +16,8 @@
package com.android.email.service;
import com.android.email.Email;
import com.android.email.activity.setup.AccountSetupBasics;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.CalendarProviderStub;
import com.android.emailcommon.provider.EmailContent;
@ -64,7 +64,7 @@ public class EasAuthenticatorService extends Service {
if (options != null && options.containsKey(OPTIONS_PASSWORD)
&& options.containsKey(OPTIONS_USERNAME)) {
final Account account = new Account(options.getString(OPTIONS_USERNAME),
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
AccountManager.get(EasAuthenticatorService.this).addAccountExplicitly(
account, options.getString(OPTIONS_PASSWORD), null);
@ -101,7 +101,7 @@ public class EasAuthenticatorService extends Service {
Bundle b = new Bundle();
b.putString(AccountManager.KEY_ACCOUNT_NAME, options.getString(OPTIONS_USERNAME));
b.putString(AccountManager.KEY_ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
b.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
return b;
// 2) The other case is that we're creating a new account from an Account manager
// activity. In this case, we add an intent that will be used to gather the

View File

@ -23,6 +23,7 @@ import com.android.email.NotificationController;
import com.android.email.Preferences;
import com.android.email.SecurityPolicy;
import com.android.email.SingleRunningTask;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
@ -652,7 +653,7 @@ public class MailService extends Service {
// See if the account is enabled for sync in AccountManager
android.accounts.Account accountManagerAccount =
new android.accounts.Account(account.mEmailAddress,
Email.POP_IMAP_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_POP_IMAP);
report.syncEnabled = ContentResolver.getSyncAutomatically(accountManagerAccount,
EmailContent.AUTHORITY);
@ -836,7 +837,7 @@ public class MailService extends Service {
@Override
protected void runInternal(Context context) {
android.accounts.Account[] accountManagerAccounts = AccountManager.get(context)
.getAccountsByType(Email.POP_IMAP_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_POP_IMAP);
ArrayList<Account> providerAccounts = getPopImapAccountList(context);
MailService.reconcileAccountsWithAccountManager(context, providerAccounts,
accountManagerAccounts, false, context.getContentResolver());
@ -896,8 +897,8 @@ public class MailService extends Service {
options.putBoolean(EasAuthenticatorService.OPTIONS_CALENDAR_SYNC_ENABLED, calendar);
options.putBoolean(EasAuthenticatorService.OPTIONS_EMAIL_SYNC_ENABLED, email);
String accountType = hostAuthRecv.mProtocol.equals("eas") ?
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE :
Email.POP_IMAP_ACCOUNT_MANAGER_TYPE;
AccountManagerTypes.TYPE_EXCHANGE :
AccountManagerTypes.TYPE_POP_IMAP;
AccountManager.get(context).addAccount(accountType, null, null, options, null, callback,
null);
}

View File

@ -16,8 +16,8 @@
package com.android.email.service;
import com.android.email.Email;
import com.android.email.activity.setup.AccountSetupBasics;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.CalendarProviderStub;
import com.android.emailcommon.provider.EmailContent;
@ -62,7 +62,7 @@ public class PopImapAuthenticatorService extends Service {
if (options != null && options.containsKey(OPTIONS_PASSWORD)
&& options.containsKey(OPTIONS_USERNAME)) {
final Account account = new Account(options.getString(OPTIONS_USERNAME),
Email.POP_IMAP_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_POP_IMAP);
AccountManager.get(PopImapAuthenticatorService.this).addAccountExplicitly(
account, options.getString(OPTIONS_PASSWORD), null);
@ -79,7 +79,7 @@ public class PopImapAuthenticatorService extends Service {
Bundle b = new Bundle();
b.putString(AccountManager.KEY_ACCOUNT_NAME, options.getString(OPTIONS_USERNAME));
b.putString(AccountManager.KEY_ACCOUNT_TYPE, Email.POP_IMAP_ACCOUNT_MANAGER_TYPE);
b.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerTypes.TYPE_POP_IMAP);
return b;
// 2) The other case is that we're creating a new account from an Account manager
// activity. In this case, we add an intent that will be used to gather the

View File

@ -0,0 +1,23 @@
/*
/*
* Copyright (C) 2011 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.emailcommon;
public class AccountManagerTypes {
public static final String TYPE_EXCHANGE = "com.android.exchange";
public static final String TYPE_POP_IMAP = "com.android.email";
}

View File

@ -0,0 +1,105 @@
/*
/*
* Copyright (C) 2011 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.emailcommon;
import com.android.emailcommon.utility.Utility;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Device {
private static String sDeviceId = null;
/**
* EAS requires a unique device id, so that sync is possible from a variety of different
* devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other
* device that doesn't provide one, we can create it as android<n> where <n> is system time.
* This would work on a real device as well, but it would be better to use the "real" id if
* it's available
*/
static public synchronized String getDeviceId(Context context) throws IOException {
if (sDeviceId == null) {
sDeviceId = getDeviceIdInternal(context);
}
return sDeviceId;
}
static private String getDeviceIdInternal(Context context) throws IOException {
if (context == null) {
throw new IllegalStateException("getDeviceId requires a Context");
}
File f = context.getFileStreamPath("deviceName");
BufferedReader rdr = null;
String id;
if (f.exists()) {
if (f.canRead()) {
rdr = new BufferedReader(new FileReader(f), 128);
id = rdr.readLine();
rdr.close();
return id;
} else {
Log.w(Logging.LOG_TAG, f.getAbsolutePath() + ": File exists, but can't read?" +
" Trying to remove.");
if (!f.delete()) {
Log.w(Logging.LOG_TAG, "Remove failed. Tring to overwrite.");
}
}
}
BufferedWriter w = new BufferedWriter(new FileWriter(f), 128);
final String consistentDeviceId = getConsistentDeviceId(context);
if (consistentDeviceId != null) {
// Use different prefix from random IDs.
id = "androidc" + consistentDeviceId;
} else {
id = "android" + System.currentTimeMillis();
}
w.write(id);
w.close();
return id;
}
/**
* @return Device's unique ID if available. null if the device has no unique ID.
*/
public static String getConsistentDeviceId(Context context) {
final String deviceId;
try {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
return null;
}
deviceId = tm.getDeviceId();
if (deviceId == null) {
return null;
}
} catch (Exception e) {
Log.d(Logging.LOG_TAG, "Error in TelephonyManager.getDeviceId(): " + e.getMessage());
return null;
}
return Utility.getSmallHash(deviceId);
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.email.mail.transport;
package com.android.emailcommon.utility;
import android.net.SSLCertificateSocketFactory;

View File

@ -45,7 +45,6 @@ import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.OpenableColumns;
import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@ -505,29 +504,7 @@ public class Utility {
}
}
/**
* @return Device's unique ID if available. null if the device has no unique ID.
*/
public static String getConsistentDeviceId(Context context) {
final String deviceId;
try {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
return null;
}
deviceId = tm.getDeviceId();
if (deviceId == null) {
return null;
}
} catch (Exception e) {
Log.d(Logging.LOG_TAG, "Error in TelephonyManager.getDeviceId(): " + e.getMessage());
return null;
}
return getSmallHash(deviceId);
}
/* package */ static String getSmallHash(final String value) {
public static String getSmallHash(final String value) {
final MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA-1");

View File

@ -16,9 +16,9 @@
package com.android.exchange;
import com.android.email.Email;
import com.android.email.NotificationController;
import com.android.email.R;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.Logging;
import android.accounts.Account;
@ -71,7 +71,7 @@ public class CalendarSyncEnabler {
StringBuilder emailAddresses = new StringBuilder();
Account[] exchangeAccounts = AccountManager.get(mContext)
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
for (Account account : exchangeAccounts) {
final String emailAddress = account.name;
Log.i(Logging.LOG_TAG, "Enabling Exchange calendar sync for " + emailAddress);

View File

@ -16,7 +16,7 @@
package com.android.exchange;
import com.android.email.Email;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.Mailbox;
@ -110,7 +110,8 @@ public class ContactsSyncAdapterService extends Service {
if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
Uri uri = RawContacts.CONTENT_URI.buildUpon()
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE,
AccountManagerTypes.TYPE_EXCHANGE)
.build();
// See if we've got dirty contacts or dirty groups containing our contacts
boolean changed = hasDirtyRows(cr, uri, RawContacts.DIRTY);
@ -118,7 +119,7 @@ public class ContactsSyncAdapterService extends Service {
uri = Groups.CONTENT_URI.buildUpon()
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
AccountManagerTypes.TYPE_EXCHANGE)
.build();
changed = hasDirtyRows(cr, uri, Groups.DIRTY);
}

View File

@ -17,6 +17,7 @@
package com.android.exchange;
import com.android.emailcommon.Device;
import com.android.emailcommon.internet.Rfc822Output;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent.Account;
@ -197,7 +198,7 @@ public class EasOutboxService extends EasSyncService {
setupService();
File cacheDir = mContext.getCacheDir();
try {
mDeviceId = ExchangeService.getDeviceId();
mDeviceId = Device.getDeviceId(mContext);
Cursor c = mContext.getContentResolver().query(Message.CONTENT_URI,
Message.ID_COLUMN_PROJECTION, MAILBOX_KEY_AND_NOT_SEND_FAILED,
new String[] {Long.toString(mMailbox.mId)}, null);

View File

@ -17,6 +17,7 @@
package com.android.exchange;
import com.android.emailcommon.Device;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.mail.MeetingInfo;
import com.android.emailcommon.mail.MessagingException;
@ -853,7 +854,7 @@ public class EasSyncService extends AbstractSyncService {
svc.mPassword = ha.mPassword;
svc.mSsl = (ha.mFlags & HostAuth.FLAG_SSL) != 0;
svc.mTrustSsl = (ha.mFlags & HostAuth.FLAG_TRUST_ALL_CERTIFICATES) != 0;
svc.mDeviceId = ExchangeService.getDeviceId();
svc.mDeviceId = Device.getDeviceId(context);
svc.mAccount = acct;
Serializer s = new Serializer();
s.start(Tags.SEARCH_SEARCH).start(Tags.SEARCH_STORE);
@ -2386,7 +2387,7 @@ public class EasSyncService extends AbstractSyncService {
// Whether or not we're the account mailbox
try {
mDeviceId = ExchangeService.getDeviceId();
mDeviceId = Device.getDeviceId(mContext);
if ((mMailbox == null) || (mAccount == null)) {
return;
} else if (mMailbox.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {

View File

@ -18,9 +18,9 @@
package com.android.exchange;
import com.android.email.Email;
import com.android.email.mail.transport.SSLUtils;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.Api;
import com.android.emailcommon.Logging;
import com.android.emailcommon.Device;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
@ -35,6 +35,7 @@ import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.utility.AccountReconciler;
import com.android.emailcommon.utility.SSLUtils;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.adapter.CalendarSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter;
@ -84,11 +85,6 @@ import android.provider.Calendar.Events;
import android.provider.ContactsContract;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@ -635,7 +631,8 @@ public class ExchangeService extends Service implements Runnable {
stopAccountSyncs(account.mId, true);
// Delete this from AccountManager...
android.accounts.Account acct = new android.accounts.Account(
account.mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
account.mEmailAddress,
AccountManagerTypes.TYPE_EXCHANGE);
AccountManager.get(ExchangeService.this)
.removeAccount(acct, null, null);
mSyncableEasMailboxSelector = null;
@ -779,7 +776,8 @@ public class ExchangeService extends Service implements Runnable {
Cursor c = mResolver.query(Calendars.CONTENT_URI,
new String[] {Calendars._ID, Calendars.SYNC_EVENTS},
CalendarSyncAdapter.CALENDAR_SELECTION,
new String[] {account.mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE},
new String[] {account.mEmailAddress,
AccountManagerTypes.TYPE_EXCHANGE},
null);
if (c != null) {
// Save its id and its sync events status
@ -1039,7 +1037,7 @@ public class ExchangeService extends Service implements Runnable {
*/
private void runAccountReconcilerSync(Context context) {
android.accounts.Account[] accountMgrList = AccountManager.get(context)
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
// Make sure we have an up-to-date sAccountList. If not (for example, if the
// service has been destroyed), we would be reconciling against an empty account
// list, which would cause the deletion of all of our accounts
@ -1077,61 +1075,6 @@ public class ExchangeService extends Service implements Runnable {
}
}
/**
* EAS requires a unique device id, so that sync is possible from a variety of different
* devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other
* device that doesn't provide one, we can create it as droid<n> where <n> is system time.
* This would work on a real device as well, but it would be better to use the "real" id if
* it's available
*/
static public String getDeviceId() throws IOException {
return getDeviceId(null);
}
static public synchronized String getDeviceId(Context context) throws IOException {
if (sDeviceId == null) {
sDeviceId = getDeviceIdInternal(context);
}
return sDeviceId;
}
static private String getDeviceIdInternal(Context context) throws IOException {
if (INSTANCE == null && context == null) {
throw new IOException("No context for getDeviceId");
} else if (context == null) {
context = INSTANCE;
}
File f = context.getFileStreamPath("deviceName");
BufferedReader rdr = null;
String id;
if (f.exists()) {
if (f.canRead()) {
rdr = new BufferedReader(new FileReader(f), 128);
id = rdr.readLine();
rdr.close();
return id;
} else {
Log.w(Logging.LOG_TAG, f.getAbsolutePath() + ": File exists, but can't read?" +
" Trying to remove.");
if (!f.delete()) {
Log.w(Logging.LOG_TAG, "Remove failed. Tring to overwrite.");
}
}
}
BufferedWriter w = new BufferedWriter(new FileWriter(f), 128);
final String consistentDeviceId = Utility.getConsistentDeviceId(context);
if (consistentDeviceId != null) {
// Use different prefix from random IDs.
id = "androidc" + consistentDeviceId;
} else {
id = "android" + System.currentTimeMillis();
}
w.write(id);
w.close();
return id;
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
@ -1488,7 +1431,7 @@ public class ExchangeService extends Service implements Runnable {
// Create an AccountManager style Account
android.accounts.Account acct =
new android.accounts.Account(providerAccount.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
// Get the mailbox; this happens rarely so it's ok to get it all
Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mailboxId);
if (mailbox == null) return;
@ -1739,7 +1682,7 @@ public class ExchangeService extends Service implements Runnable {
}
if (sDeviceId == null) {
try {
getDeviceId(this);
Device.getDeviceId(this);
} catch (IOException e) {
// We can't run in this situation
throw new RuntimeException(e);
@ -2076,7 +2019,7 @@ public class ExchangeService extends Service implements Runnable {
// TODO: Don't rebuild this account manager account each time through
android.accounts.Account accountManagerAccount =
new android.accounts.Account(account.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
if (type == Mailbox.TYPE_CONTACTS || type == Mailbox.TYPE_CALENDAR) {
// We don't sync these automatically if master auto sync is off

View File

@ -17,7 +17,7 @@
package com.android.exchange.adapter;
import com.android.email.Email;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.exchange.Eas;
@ -79,7 +79,7 @@ public abstract class AbstractSyncAdapter {
mContext = service.mContext;
mAccount = service.mAccount;
mAccountManagerAccount = new android.accounts.Account(mAccount.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManagerTypes.TYPE_EXCHANGE);
mContentResolver = mContext.getContentResolver();
}

View File

@ -17,7 +17,7 @@
package com.android.exchange.adapter;
import com.android.email.Email;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.utility.Utility;
@ -166,7 +166,7 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
mEmailAddress = mAccount.mEmailAddress;
Cursor c = mService.mContentResolver.query(Calendars.CONTENT_URI,
new String[] {Calendars._ID}, CALENDAR_SELECTION,
new String[] {mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE}, null);
new String[] {mEmailAddress, AccountManagerTypes.TYPE_EXCHANGE}, null);
if (c == null) return;
try {
if (c.moveToFirst()) {
@ -197,7 +197,7 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
mContentResolver.delete(Calendars.CONTENT_URI, Calendars._SYNC_ACCOUNT +
"=" + DatabaseUtils.sqlEscapeString(mEmailAddress) + " AND " +
Calendars._SYNC_ACCOUNT_TYPE + "=" +
DatabaseUtils.sqlEscapeString(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE), null);
DatabaseUtils.sqlEscapeString(AccountManagerTypes.TYPE_EXCHANGE), null);
}
@Override
@ -387,7 +387,7 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
ContentValues cv = new ContentValues();
cv.put(Events.CALENDAR_ID, mCalendarId);
cv.put(Events._SYNC_ACCOUNT, mEmailAddress);
cv.put(Events._SYNC_ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
cv.put(Events._SYNC_ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
cv.put(Events._SYNC_ID, serverId);
cv.put(Events.HAS_ATTENDEE_DATA, 1);
cv.put(Events._SYNC_DATA, "0");
@ -782,7 +782,7 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
ContentValues cv = new ContentValues();
cv.put(Events.CALENDAR_ID, mCalendarId);
cv.put(Events._SYNC_ACCOUNT, mEmailAddress);
cv.put(Events._SYNC_ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
cv.put(Events._SYNC_ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
// It appears that these values have to be copied from the parent if they are to appear
// Note that they can be overridden below

View File

@ -17,6 +17,7 @@
package com.android.exchange.adapter;
import com.android.emailcommon.AccountManagerTypes;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;
@ -188,8 +189,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
// Make sure ungrouped contacts for Exchange are defaultly visible
ContentValues cv = new ContentValues();
cv.put(Groups.ACCOUNT_NAME, mAccount.mEmailAddress);
cv.put(Groups.ACCOUNT_TYPE,
com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
cv.put(Groups.ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
cv.put(Settings.UNGROUPED_VISIBLE, true);
client.insert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI), cv);
return "0";
@ -903,7 +903,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
return uri.buildUpon()
.appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE,
com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
AccountManagerTypes.TYPE_EXCHANGE)
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.build();
}

View File

@ -17,6 +17,7 @@
package com.android.exchange.provider;
import com.android.email.R;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.Configuration;
import com.android.emailcommon.mail.PackedString;
import com.android.emailcommon.provider.EmailContent;
@ -119,7 +120,7 @@ public class ExchangeDirectoryProvider extends ContentProvider {
// TODO alternative display name
put(Contacts.DISPLAY_NAME_ALTERNATIVE, displayName);
put(RawContacts.ACCOUNT_TYPE, com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
put(RawContacts.ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
put(RawContacts.ACCOUNT_NAME, accountName);
put(RawContacts.RAW_CONTACT_IS_READ_ONLY, 1);
put(Data.IS_READ_ONLY, 1);
@ -207,7 +208,7 @@ public class ExchangeDirectoryProvider extends ContentProvider {
case GAL_DIRECTORIES: {
// Assuming that GAL can be used with all exchange accounts
android.accounts.Account[] accounts = AccountManager.get(getContext())
.getAccountsByType(com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
cursor = new MatrixCursor(projection);
if (accounts != null) {
for (android.accounts.Account account : accounts) {
@ -223,7 +224,7 @@ public class ExchangeDirectoryProvider extends ContentProvider {
Bundle bundle = null;
try {
String accountType =
com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE;
AccountManagerTypes.TYPE_EXCHANGE;
bundle = new AccountServiceProxy(getContext())
.getConfigurationData(accountType);
} catch (RemoteException e) {

View File

@ -16,8 +16,8 @@
package com.android.exchange.utility;
import com.android.email.Email;
import com.android.email.R;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
@ -1208,7 +1208,7 @@ public class CalendarUtilities {
// TODO How will this change if the user changes his account display name?
cv.put(Calendars.DISPLAY_NAME, account.mDisplayName);
cv.put(Calendars._SYNC_ACCOUNT, account.mEmailAddress);
cv.put(Calendars._SYNC_ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
cv.put(Calendars._SYNC_ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
cv.put(Calendars.SYNC_EVENTS, 1);
cv.put(Calendars.SELECTED, 1);
// Don't show attendee status if we're the organizer

View File

@ -18,6 +18,7 @@ package com.android.email;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
@ -46,11 +47,11 @@ public abstract class AccountTestCase extends ProviderTestCase2<EmailProvider> {
protected android.accounts.Account[] getExchangeAccounts() {
return AccountManager.get(getContext())
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
}
protected android.accounts.Account makeAccountManagerAccount(String username) {
return new android.accounts.Account(username, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
return new android.accounts.Account(username, AccountManagerTypes.TYPE_EXCHANGE);
}
protected void createAccountManagerAccount(String username) {

View File

@ -29,6 +29,7 @@ import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.service.EmailServiceStatus;
import android.content.Context;
import android.content.Intent;
import java.io.File;
import java.util.Iterator;
@ -69,7 +70,8 @@ public class AttachmentDownloadServiceTests extends AccountTestCase {
// Use the NullEmailService so that the loadAttachment calls become no-ops
mService = new AttachmentDownloadService();
mService.mContext = mMockContext;
mService.addServiceClass(mAccountId, NullEmailService.class);
mService.addServiceIntentForTest(mAccountId, new Intent(mMockContext,
NullEmailService.class));
mAccountManagerStub = new AttachmentDownloadService.AccountManagerStub(null);
mService.mAccountManagerStub = mAccountManagerStub;
mService.mConnectivityManager = new MockConnectivityManager(getContext(), "mock");
@ -236,11 +238,11 @@ public class AttachmentDownloadServiceTests extends AccountTestCase {
// Mock 2 accounts in total
mAccountManagerStub.setNumberOfAccounts(2);
// With 26% available, we should be ok to prefetch
assertTrue(mService.canPrefetchForAccount(mAccountId, mMockDirectory));
assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory));
// Now change to 24 available
mMockDirectory.setTotalAndUsableSpace(100L, 24L);
// With 24% available, we should NOT be ok to prefetch
assertFalse(mService.canPrefetchForAccount(mAccountId, mMockDirectory));
assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory));
// Now, test per-account storage
// Mock storage @ 100 total and 50 available
@ -249,12 +251,12 @@ public class AttachmentDownloadServiceTests extends AccountTestCase {
mService.mAttachmentStorageMap.remove(mAccountId);
mMockDirectory.setFileLength(11);
// We can prefetch since 11 < 50/4
assertTrue(mService.canPrefetchForAccount(mAccountId, mMockDirectory));
assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory));
// Mock a file of length 13, but need to uncache previous amount first
mService.mAttachmentStorageMap.remove(mAccountId);
mMockDirectory.setFileLength(13);
// We can't prefetch since 13 > 50/4
assertFalse(mService.canPrefetchForAccount(mAccountId, mMockDirectory));
assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory));
}
public void testCanPrefetchForAccountNoBackgroundDownload() {
@ -271,6 +273,6 @@ public class AttachmentDownloadServiceTests extends AccountTestCase {
// With 26% available, we should be ok to prefetch,
// *but* bg download is disabled on the account.
assertFalse(mService.canPrefetchForAccount(account.mId, mMockDirectory));
assertFalse(mService.canPrefetchForAccount(account, mMockDirectory));
}
}

View File

@ -18,10 +18,10 @@ package com.android.email.service;
import com.android.email.AccountTestCase;
import com.android.email.Controller;
import com.android.email.Email;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
import com.android.email.service.MailService.AccountSyncReport;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
@ -87,7 +87,7 @@ public class MailServiceTests extends AccountTestCase {
context.getContentResolver().delete(firstAccount.getUri(), null, null);
// delete the account manager account
android.accounts.Account[] accountManagerAccounts = AccountManager.get(context)
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
.getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
if ((TEST_USER_ACCOUNT + TEST_ACCOUNT_SUFFIX)
.equals(accountManagerAccount.name)) {
@ -112,7 +112,7 @@ public class MailServiceTests extends AccountTestCase {
// Capture the baseline (account manager accounts) so we can measure the changes
// we're making, irrespective of the number of actual accounts, and not destroy them
android.accounts.Account[] baselineAccounts =
AccountManager.get(context).getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
AccountManager.get(context).getAccountsByType(AccountManagerTypes.TYPE_EXCHANGE);
// Set up three accounts, both in AccountManager and in EmailProvider
Account firstAccount = setupProviderAndAccountManagerAccount(getTestAccountName("1"));

View File

@ -0,0 +1,42 @@
/*
/*
* Copyright (C) 2011 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.emailcommon;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.util.Log;
public class DeviceTests extends AndroidTestCase {
public void testGetConsistentDeviceId() {
TelephonyManager tm =
(TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
Log.w(Logging.LOG_TAG, "TelephonyManager not supported. Skipping.");
return;
}
// Note null is a valid return value. But still it should be consistent.
final String deviceId = Device.getConsistentDeviceId(getContext());
final String deviceId2 = Device.getConsistentDeviceId(getContext());
// Should be consistent.
assertEquals(deviceId, deviceId2);
}
}

View File

@ -22,7 +22,6 @@ import com.android.email.R;
import com.android.email.TestUtils;
import com.android.email.UiUtilities;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.provider.EmailContent.Mailbox;
@ -38,13 +37,11 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ListView;
import android.widget.TextView;
@ -207,21 +204,6 @@ public class UtilityUnitTests extends AndroidTestCase {
assertEquals("A\r\nB\r\nC\r\nD", Utility.replaceBareLfWithCrlf("A\nB\r\nC\nD"));
}
public void testGetConsistentDeviceId() {
TelephonyManager tm =
(TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
Log.w(Logging.LOG_TAG, "TelephonyManager not supported. Skipping.");
return;
}
// Note null is a valid return value. But still it should be consistent.
final String deviceId = Utility.getConsistentDeviceId(getContext());
final String deviceId2 = Utility.getConsistentDeviceId(getContext());
// Should be consistent.
assertEquals(deviceId, deviceId2);
}
public void testGetSmallHash() {
assertEquals("1438642069", Utility.getSmallHash(""));
assertEquals("1354919068", Utility.getSmallHash("abc"));

View File

@ -17,8 +17,8 @@
package com.android.exchange;
import com.android.email.AccountTestCase;
import com.android.email.Email;
import com.android.email.NotificationController;
import com.android.emailcommon.AccountManagerTypes;
import com.android.emailcommon.Logging;
import android.accounts.Account;
@ -39,9 +39,6 @@ public class CalendarSyncEnablerTest extends AccountTestCase {
private HashMap<Account, Boolean> origCalendarSyncStates = new HashMap<Account, Boolean>();
// To make the rest of the code shorter thus more readable...
private static final String EAT = Email.EXCHANGE_ACCOUNT_MANAGER_TYPE;
public CalendarSyncEnablerTest() {
super();
}
@ -157,7 +154,7 @@ public class CalendarSyncEnablerTest extends AccountTestCase {
boolean enabled = ContentResolver.getSyncAutomatically(account, Calendar.AUTHORITY);
int syncable = ContentResolver.getIsSyncable(account, Calendar.AUTHORITY);
if (EAT.equals(account.type)) {
if (AccountManagerTypes.TYPE_EXCHANGE.equals(account.type)) {
// Should be enabled.
// assertEquals(message, Boolean.TRUE, (Boolean) enabled);
// assertEquals(message, 1, syncable);
@ -172,7 +169,8 @@ public class CalendarSyncEnablerTest extends AccountTestCase {
// This test can only meaningfully run when there's no exchange accounts
// set up on the device. Otherwise there'll be no difference from
// testEnableEasCalendarSync.
if (AccountManager.get(getContext()).getAccountsByType(EAT).length > 0) {
if (AccountManager.get(getContext()).getAccountsByType(
AccountManagerTypes.TYPE_EXCHANGE).length > 0) {
Log.w(Logging.LOG_TAG, "testEnableEasCalendarSyncWithNoExchangeAccounts skipped:"
+ " It only runs when there's no Exchange account on the device.");
return;

View File

@ -16,6 +16,8 @@
package com.android.exchange;
import com.android.emailcommon.Device;
import android.content.Context;
import android.content.ContextWrapper;
import android.test.AndroidTestCase;
@ -40,7 +42,7 @@ public class ExchangeServiceTest extends AndroidTestCase {
public void testGetDeviceId() throws Exception {
final MyContext context = new MyContext(getContext());
final String id = ExchangeService.getDeviceId(context);
final String id = Device.getDeviceId(context);
// Consists of alpha-numeric
assertTrue(id.matches("^[a-zA-Z0-9]+$"));
@ -49,7 +51,7 @@ public class ExchangeServiceTest extends AndroidTestCase {
// isGetFileStreamPathCalled here.
context.isGetFileStreamPathCalled = false;
final String cachedId = ExchangeService.getDeviceId(context);
final String cachedId = Device.getDeviceId(context);
// Should be the same.
assertEquals(id, cachedId);