Email split, part trois: AccountService
* Create AccountService.aidl and AccountServiceProxy in emailcommon * Implement AccountService in email * Use AccountServiceProxy in Exchange for account reconciliation, notifications, etc. * Move sync window constants into emailcommon * Split attachment provider utilities and constants into emailcommon Bug: 3442973 Change-Id: I89dce28b799b193243c07774dab65d830ae62775
This commit is contained in:
parent
e86789b66e
commit
8a57469460
|
@ -21,7 +21,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
|||
LOCAL_SRC_FILES += \
|
||||
src/com/android/emailcommon/service/IEmailService.aidl \
|
||||
src/com/android/emailcommon/service/IEmailServiceCallback.aidl \
|
||||
src/com/android/emailcommon/service/IPolicyService.aidl
|
||||
src/com/android/emailcommon/service/IPolicyService.aidl \
|
||||
src/com/android/emailcommon/service/IAccountService.aidl
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := android-common
|
||||
# Revive this when the app is unbundled.
|
||||
|
|
|
@ -370,6 +370,17 @@
|
|||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".service.AccountService"
|
||||
android:enabled="true"
|
||||
android:permission="com.android.email.permission.ACCESS_PROVIDER"
|
||||
>
|
||||
<intent-filter>
|
||||
<action
|
||||
android:name="com.android.email.ACCOUNT_INTENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<!--EXCHANGE-REMOVE-SECTION-START-->
|
||||
<!--Required stanza to register the EAS EmailSyncAdapterService with SyncManager -->
|
||||
<service
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.email;
|
||||
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.emailcommon.service.SyncWindow;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -37,14 +38,6 @@ public class Account {
|
|||
public static final int CHECK_INTERVAL_NEVER = -1;
|
||||
public static final int CHECK_INTERVAL_PUSH = -2;
|
||||
|
||||
public static final int SYNC_WINDOW_USER = -1;
|
||||
public static final int SYNC_WINDOW_1_DAY = 1;
|
||||
public static final int SYNC_WINDOW_3_DAYS = 2;
|
||||
public static final int SYNC_WINDOW_1_WEEK = 3;
|
||||
public static final int SYNC_WINDOW_2_WEEKS = 4;
|
||||
public static final int SYNC_WINDOW_1_MONTH = 5;
|
||||
public static final int SYNC_WINDOW_ALL = 6;
|
||||
|
||||
// These flags will never be seen in a "real" (legacy) account
|
||||
public static final int BACKUP_FLAGS_IS_BACKUP = 1;
|
||||
public static final int BACKUP_FLAGS_SYNC_CONTACTS = 2;
|
||||
|
@ -109,7 +102,7 @@ public class Account {
|
|||
mVibrate = false;
|
||||
mVibrateWhenSilent = false;
|
||||
mRingtoneUri = "content://settings/system/notification_sound";
|
||||
mSyncWindow = SYNC_WINDOW_USER; // IMAP & POP3
|
||||
mSyncWindow = SyncWindow.SYNC_WINDOW_USER; // IMAP & POP3
|
||||
mBackupFlags = 0;
|
||||
mProtocolVersion = null;
|
||||
mSecurityFlags = 0;
|
||||
|
@ -171,7 +164,7 @@ public class Account {
|
|||
"content://settings/system/notification_sound");
|
||||
|
||||
mSyncWindow = preferences.mSharedPreferences.getInt(mUuid + KEY_SYNC_WINDOW,
|
||||
SYNC_WINDOW_USER);
|
||||
SyncWindow.SYNC_WINDOW_USER);
|
||||
|
||||
mBackupFlags = preferences.mSharedPreferences.getInt(mUuid + KEY_BACKUP_FLAGS, 0);
|
||||
mProtocolVersion = preferences.mSharedPreferences.getString(mUuid + KEY_PROTOCOL_VERSION,
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package com.android.email;
|
||||
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -69,7 +69,7 @@ public class AttachmentInfo {
|
|||
public AttachmentInfo(Context context, long id, long size, String fileName, String mimeType,
|
||||
long accountKey) {
|
||||
mSize = size;
|
||||
mContentType = AttachmentProvider.inferMimeType(fileName, mimeType);
|
||||
mContentType = AttachmentUtilities.inferMimeType(fileName, mimeType);
|
||||
mName = fileName;
|
||||
mId = id;
|
||||
mAccountKey = accountKey;
|
||||
|
@ -83,7 +83,7 @@ public class AttachmentInfo {
|
|||
}
|
||||
|
||||
// Check for unacceptable attachments by filename extension
|
||||
String extension = AttachmentProvider.getFilenameExtension(mName);
|
||||
String extension = AttachmentUtilities.getFilenameExtension(mName);
|
||||
if (!TextUtils.isEmpty(extension) &&
|
||||
Utility.arrayContains(Email.UNACCEPTABLE_ATTACHMENT_EXTENSIONS, extension)) {
|
||||
canView = false;
|
||||
|
@ -91,7 +91,7 @@ public class AttachmentInfo {
|
|||
}
|
||||
|
||||
// Check for installable attachments by filename extension
|
||||
extension = AttachmentProvider.getFilenameExtension(mName);
|
||||
extension = AttachmentUtilities.getFilenameExtension(mName);
|
||||
if (!TextUtils.isEmpty(extension) &&
|
||||
Utility.arrayContains(Email.INSTALLABLE_ATTACHMENT_EXTENSIONS, extension)) {
|
||||
int sideloadEnabled;
|
||||
|
@ -134,9 +134,9 @@ public class AttachmentInfo {
|
|||
* @return an Intent suitable for loading the attachment
|
||||
*/
|
||||
public Intent getAttachmentIntent(Context context, long accountId) {
|
||||
Uri contentUri = AttachmentProvider.getAttachmentUri(accountId, mId);
|
||||
Uri contentUri = AttachmentUtilities.getAttachmentUri(accountId, mId);
|
||||
if (accountId > 0) {
|
||||
contentUri = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
|
||||
context.getContentResolver(), contentUri);
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
|
@ -154,6 +154,7 @@ public class AttachmentInfo {
|
|||
return mAllowView || mAllowSave;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{Attachment " + mId + ":" + mName + "," + mContentType + "," + mSize + "}";
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.android.email.mail.MessagingException;
|
|||
import com.android.email.mail.Store;
|
||||
import com.android.email.mail.Folder.MessageRetrievalListener;
|
||||
import com.android.email.mail.store.Pop3Store.Pop3Message;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
|
@ -34,6 +33,7 @@ import com.android.emailcommon.Api;
|
|||
import com.android.emailcommon.service.EmailServiceStatus;
|
||||
import com.android.emailcommon.service.IEmailService;
|
||||
import com.android.emailcommon.service.IEmailServiceCallback;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.ContentResolver;
|
||||
|
@ -197,7 +197,8 @@ public class Controller {
|
|||
while (c.moveToNext()) {
|
||||
long mailboxId = c.getLong(EmailContent.ID_PROJECTION_COLUMN);
|
||||
// Must delete attachments BEFORE messages
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(mProviderContext, 0, mailboxId);
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(mProviderContext, 0,
|
||||
mailboxId);
|
||||
resolver.delete(Message.CONTENT_URI, WHERE_MAILBOX_KEY,
|
||||
new String[] {Long.toString(mailboxId)});
|
||||
}
|
||||
|
@ -720,7 +721,7 @@ public class Controller {
|
|||
if (mailbox == null) return;
|
||||
|
||||
// 4. Drop non-essential data for the message (e.g. attachment files)
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mProviderContext, account.mId,
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mProviderContext, account.mId,
|
||||
messageId);
|
||||
|
||||
Uri uri = ContentUris.withAppendedId(EmailContent.Message.SYNCED_CONTENT_URI,
|
||||
|
@ -1003,7 +1004,8 @@ public class Controller {
|
|||
public void deleteSyncedDataSync(long accountId) {
|
||||
try {
|
||||
// Delete synced attachments
|
||||
AttachmentProvider.deleteAllAccountAttachmentFiles(mProviderContext, accountId);
|
||||
AttachmentUtilities.deleteAllAccountAttachmentFiles(mProviderContext,
|
||||
accountId);
|
||||
|
||||
// Delete synced email, leaving only an empty inbox. We do this in two phases:
|
||||
// 1. Delete all non-inbox mailboxes (which will delete all of their messages)
|
||||
|
|
|
@ -19,20 +19,20 @@ package com.android.email;
|
|||
import com.android.email.mail.Address;
|
||||
import com.android.email.mail.Flag;
|
||||
import com.android.email.mail.Message;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.internet.MimeBodyPart;
|
||||
import com.android.email.mail.internet.MimeHeader;
|
||||
import com.android.email.mail.internet.MimeMessage;
|
||||
import com.android.email.mail.internet.MimeMultipart;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.mail.internet.TextBody;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.AttachmentColumns;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
@ -41,7 +41,6 @@ import android.content.ContentValues;
|
|||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -147,108 +146,6 @@ public class LegacyConversions {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy body text (plain and/or HTML) from MimeMessage to provider Message
|
||||
*/
|
||||
public static boolean updateBodyFields(EmailContent.Body body,
|
||||
EmailContent.Message localMessage, ArrayList<Part> viewables)
|
||||
throws MessagingException {
|
||||
|
||||
body.mMessageKey = localMessage.mId;
|
||||
|
||||
StringBuffer sbHtml = null;
|
||||
StringBuffer sbText = null;
|
||||
StringBuffer sbHtmlReply = null;
|
||||
StringBuffer sbTextReply = null;
|
||||
StringBuffer sbIntroText = null;
|
||||
|
||||
for (Part viewable : viewables) {
|
||||
String text = MimeUtility.getTextFromPart(viewable);
|
||||
String[] replyTags = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART);
|
||||
String replyTag = null;
|
||||
if (replyTags != null && replyTags.length > 0) {
|
||||
replyTag = replyTags[0];
|
||||
}
|
||||
// Deploy text as marked by the various tags
|
||||
boolean isHtml = "text/html".equalsIgnoreCase(viewable.getMimeType());
|
||||
|
||||
if (replyTag != null) {
|
||||
boolean isQuotedReply = BODY_QUOTED_PART_REPLY.equalsIgnoreCase(replyTag);
|
||||
boolean isQuotedForward = BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(replyTag);
|
||||
boolean isQuotedIntro = BODY_QUOTED_PART_INTRO.equalsIgnoreCase(replyTag);
|
||||
|
||||
if (isQuotedReply || isQuotedForward) {
|
||||
if (isHtml) {
|
||||
sbHtmlReply = appendTextPart(sbHtmlReply, text);
|
||||
} else {
|
||||
sbTextReply = appendTextPart(sbTextReply, text);
|
||||
}
|
||||
// Set message flags as well
|
||||
localMessage.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK;
|
||||
localMessage.mFlags |= isQuotedReply
|
||||
? EmailContent.Message.FLAG_TYPE_REPLY
|
||||
: EmailContent.Message.FLAG_TYPE_FORWARD;
|
||||
continue;
|
||||
}
|
||||
if (isQuotedIntro) {
|
||||
sbIntroText = appendTextPart(sbIntroText, text);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Most of the time, just process regular body parts
|
||||
if (isHtml) {
|
||||
sbHtml = appendTextPart(sbHtml, text);
|
||||
} else {
|
||||
sbText = appendTextPart(sbText, text);
|
||||
}
|
||||
}
|
||||
|
||||
// write the combined data to the body part
|
||||
if (!TextUtils.isEmpty(sbText)) {
|
||||
String text = sbText.toString();
|
||||
body.mTextContent = text;
|
||||
localMessage.mSnippet = Snippet.fromPlainText(text);
|
||||
}
|
||||
if (!TextUtils.isEmpty(sbHtml)) {
|
||||
String text = sbHtml.toString();
|
||||
body.mHtmlContent = text;
|
||||
if (localMessage.mSnippet == null) {
|
||||
localMessage.mSnippet = Snippet.fromHtmlText(text);
|
||||
}
|
||||
}
|
||||
if (sbHtmlReply != null && sbHtmlReply.length() != 0) {
|
||||
body.mHtmlReply = sbHtmlReply.toString();
|
||||
}
|
||||
if (sbTextReply != null && sbTextReply.length() != 0) {
|
||||
body.mTextReply = sbTextReply.toString();
|
||||
}
|
||||
if (sbIntroText != null && sbIntroText.length() != 0) {
|
||||
body.mIntroText = sbIntroText.toString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to append text to a StringBuffer, creating it if necessary.
|
||||
* Optimization: The majority of the time we are *not* appending - we should have a path
|
||||
* that deals with single strings.
|
||||
*/
|
||||
private static StringBuffer appendTextPart(StringBuffer sb, String newText) {
|
||||
if (newText == null) {
|
||||
return sb;
|
||||
}
|
||||
else if (sb == null) {
|
||||
sb = new StringBuffer(newText);
|
||||
} else {
|
||||
if (sb.length() > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(newText);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy attachments from MimeMessage to provider Message.
|
||||
*
|
||||
|
@ -392,11 +289,11 @@ public class LegacyConversions {
|
|||
|
||||
InputStream in = part.getBody().getInputStream();
|
||||
|
||||
File saveIn = AttachmentProvider.getAttachmentDirectory(context, accountId);
|
||||
File saveIn = AttachmentUtilities.getAttachmentDirectory(context, accountId);
|
||||
if (!saveIn.exists()) {
|
||||
saveIn.mkdirs();
|
||||
}
|
||||
File saveAs = AttachmentProvider.getAttachmentFilename(context, accountId,
|
||||
File saveAs = AttachmentUtilities.getAttachmentFilename(context, accountId,
|
||||
attachmentId);
|
||||
saveAs.createNewFile();
|
||||
FileOutputStream out = new FileOutputStream(saveAs);
|
||||
|
@ -405,7 +302,7 @@ public class LegacyConversions {
|
|||
out.close();
|
||||
|
||||
// update the attachment with the extra information we now know
|
||||
String contentUriString = AttachmentProvider.getAttachmentUri(
|
||||
String contentUriString = AttachmentUtilities.getAttachmentUri(
|
||||
accountId, attachmentId).toString();
|
||||
|
||||
localAttachment.mSize = copySize;
|
||||
|
|
|
@ -33,7 +33,6 @@ import com.android.email.mail.internet.MimeBodyPart;
|
|||
import com.android.email.mail.internet.MimeHeader;
|
||||
import com.android.email.mail.internet.MimeMultipart;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.AttachmentColumns;
|
||||
|
@ -41,6 +40,8 @@ import com.android.email.provider.EmailContent.Mailbox;
|
|||
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||
import com.android.email.provider.EmailContent.MessageColumns;
|
||||
import com.android.email.provider.EmailContent.SyncColumns;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.emailcommon.utility.ConversionUtilities;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
|
@ -300,7 +301,7 @@ public class MessagingController implements Runnable {
|
|||
break;
|
||||
default:
|
||||
// Drop all attachment files related to this mailbox
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(
|
||||
mContext, accountId, localInfo.mId);
|
||||
// Delete the mailbox. Triggers will take care of
|
||||
// related Message, Body and Attachment records.
|
||||
|
@ -736,7 +737,8 @@ public class MessagingController implements Runnable {
|
|||
|
||||
// Delete associated data (attachment files)
|
||||
// Attachment & Body records are auto-deleted when we delete the Message record
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mContext, account.mId, infoToDelete.mId);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mContext, account.mId,
|
||||
infoToDelete.mId);
|
||||
|
||||
// Delete the message itself
|
||||
Uri uriToDelete = ContentUris.withAppendedId(
|
||||
|
@ -1005,7 +1007,7 @@ public class MessagingController implements Runnable {
|
|||
ArrayList<Part> attachments = new ArrayList<Part>();
|
||||
MimeUtility.collectParts(message, viewables, attachments);
|
||||
|
||||
LegacyConversions.updateBodyFields(body, localMessage, viewables);
|
||||
ConversionUtilities.updateBodyFields(body, localMessage, viewables);
|
||||
|
||||
// Commit the message & body to the local store immediately
|
||||
saveOrUpdate(localMessage, context);
|
||||
|
@ -2046,12 +2048,13 @@ public class MessagingController implements Runnable {
|
|||
EmailContent.Message.restoreMessageWithId(mContext, messageId);
|
||||
if (msg != null &&
|
||||
((msg.mFlags & EmailContent.Message.FLAG_TYPE_FORWARD) != 0)) {
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mContext, account.mId,
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mContext, account.mId,
|
||||
messageId);
|
||||
}
|
||||
resolver.update(syncedUri, moveToSentValues, null, null);
|
||||
} else {
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mContext, account.mId, messageId);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mContext, account.mId,
|
||||
messageId);
|
||||
Uri uri =
|
||||
ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI, messageId);
|
||||
resolver.delete(uri, null, null);
|
||||
|
|
|
@ -27,12 +27,12 @@ import com.android.email.Utility;
|
|||
import com.android.email.mail.Address;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Body;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.service.AttachmentDownloadService;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
@ -677,14 +677,14 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
|||
return;
|
||||
}
|
||||
Attachment attachment = Attachment.restoreAttachmentWithId(mContext, info.mId);
|
||||
Uri attachmentUri = AttachmentProvider.getAttachmentUri(mAccountId, attachment.mId);
|
||||
Uri attachmentUri = AttachmentUtilities.getAttachmentUri(mAccountId, attachment.mId);
|
||||
|
||||
try {
|
||||
File downloads = Environment.getExternalStoragePublicDirectory(
|
||||
Environment.DIRECTORY_DOWNLOADS);
|
||||
downloads.mkdirs();
|
||||
File file = Utility.createUniqueFile(downloads, attachment.mFileName);
|
||||
Uri contentUri = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
Uri contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
|
||||
mContext.getContentResolver(), attachmentUri);
|
||||
InputStream in = mContext.getContentResolver().openInputStream(contentUri);
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
|
@ -1076,7 +1076,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
|||
try {
|
||||
return BitmapFactory.decodeStream(
|
||||
mContext.getContentResolver().openInputStream(
|
||||
AttachmentProvider.getAttachmentThumbnailUri(
|
||||
AttachmentUtilities.getAttachmentThumbnailUri(
|
||||
mAccountId, attachment.mId,
|
||||
PREVIEW_ICON_WIDTH,
|
||||
PREVIEW_ICON_HEIGHT)));
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.android.email.provider.EmailContent;
|
|||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.service.MailService;
|
||||
import com.android.emailcommon.service.PolicySet;
|
||||
import com.android.emailcommon.service.SyncWindow;
|
||||
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
|
@ -66,7 +67,7 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
|
|||
public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
|
||||
|
||||
/** Default sync window for new EAS accounts */
|
||||
private static final int SYNC_WINDOW_EAS_DEFAULT = com.android.email.Account.SYNC_WINDOW_3_DAYS;
|
||||
private static final int SYNC_WINDOW_EAS_DEFAULT = SyncWindow.SYNC_WINDOW_3_DAYS;
|
||||
|
||||
public static void actionOptions(Activity fromActivity) {
|
||||
fromActivity.startActivity(new Intent(fromActivity, AccountSetupOptions.class));
|
||||
|
|
|
@ -20,14 +20,12 @@ import com.android.email.Email;
|
|||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.AttachmentColumns;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.provider.EmailContent.MessageColumns;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities.Columns;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -35,9 +33,7 @@ import android.graphics.BitmapFactory;
|
|||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -66,19 +62,6 @@ import java.util.List;
|
|||
*/
|
||||
public class AttachmentProvider extends ContentProvider {
|
||||
|
||||
public static final String AUTHORITY = "com.android.email.attachmentprovider";
|
||||
public static final Uri CONTENT_URI = Uri.parse( "content://" + AUTHORITY);
|
||||
|
||||
private static final String FORMAT_RAW = "RAW";
|
||||
private static final String FORMAT_THUMBNAIL = "THUMBNAIL";
|
||||
|
||||
public static class AttachmentProviderColumns {
|
||||
public static final String _ID = "_id";
|
||||
public static final String DATA = "_data";
|
||||
public static final String DISPLAY_NAME = "_display_name";
|
||||
public static final String SIZE = "_size";
|
||||
}
|
||||
|
||||
private static final String[] MIME_TYPE_PROJECTION = new String[] {
|
||||
AttachmentColumns.MIME_TYPE, AttachmentColumns.FILENAME };
|
||||
private static final int MIME_TYPE_COLUMN_MIME_TYPE = 0;
|
||||
|
@ -87,47 +70,6 @@ public class AttachmentProvider extends ContentProvider {
|
|||
private static final String[] PROJECTION_QUERY = new String[] { AttachmentColumns.FILENAME,
|
||||
AttachmentColumns.SIZE, AttachmentColumns.CONTENT_URI };
|
||||
|
||||
public static Uri getAttachmentUri(long accountId, long id) {
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(accountId))
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getAttachmentThumbnailUri(long accountId, long id,
|
||||
int width, int height) {
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(accountId))
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_THUMBNAIL)
|
||||
.appendPath(Integer.toString(width))
|
||||
.appendPath(Integer.toString(height))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filename for a given attachment. This should be used by any code that is
|
||||
* going to *write* attachments.
|
||||
*
|
||||
* This does not create or write the file, or even the directories. It simply builds
|
||||
* the filename that should be used.
|
||||
*/
|
||||
public static File getAttachmentFilename(Context context, long accountId, long attachmentId) {
|
||||
return new File(getAttachmentDirectory(context, accountId), Long.toString(attachmentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the directory for a given attachment. This should be used by any code that is
|
||||
* going to *write* attachments.
|
||||
*
|
||||
* This does not create or write the directory. It simply builds the pathname that should be
|
||||
* used.
|
||||
*/
|
||||
public static File getAttachmentDirectory(Context context, long accountId) {
|
||||
return context.getDatabasePath(accountId + ".db_att");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
/*
|
||||
|
@ -157,17 +99,17 @@ public class AttachmentProvider extends ContentProvider {
|
|||
List<String> segments = uri.getPathSegments();
|
||||
String id = segments.get(1);
|
||||
String format = segments.get(2);
|
||||
if (FORMAT_THUMBNAIL.equals(format)) {
|
||||
if (AttachmentUtilities.FORMAT_THUMBNAIL.equals(format)) {
|
||||
return "image/png";
|
||||
} else {
|
||||
uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
|
||||
Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION,
|
||||
null, null, null);
|
||||
Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION, null,
|
||||
null, null);
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE);
|
||||
String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME);
|
||||
mimeType = inferMimeType(fileName, mimeType);
|
||||
mimeType = AttachmentUtilities.inferMimeType(fileName, mimeType);
|
||||
return mimeType;
|
||||
}
|
||||
} finally {
|
||||
|
@ -180,82 +122,6 @@ public class AttachmentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to convert unknown or unmapped attachments to something useful based on filename
|
||||
* extensions. The mime type is inferred based upon the table below. It's not perfect, but
|
||||
* it helps.
|
||||
*
|
||||
* <pre>
|
||||
* |---------------------------------------------------------|
|
||||
* | E X T E N S I O N |
|
||||
* |---------------------------------------------------------|
|
||||
* | .eml | known(.png) | unknown(.abc) | none |
|
||||
* | M |-----------------------------------------------------------------------|
|
||||
* | I | none | msg/rfc822 | image/png | app/abc | app/oct-str |
|
||||
* | M |-------------| (always | | | |
|
||||
* | E | app/oct-str | overrides | | | |
|
||||
* | T |-------------| | |-----------------------------|
|
||||
* | Y | text/plain | | | text/plain |
|
||||
* | P |-------------| |-------------------------------------------|
|
||||
* | E | any/type | | any/type |
|
||||
* |---|-----------------------------------------------------------------------|
|
||||
* </pre>
|
||||
*
|
||||
* NOTE: Since mime types on Android are case-*sensitive*, return values are always in
|
||||
* lower case.
|
||||
*
|
||||
* @param fileName The given filename
|
||||
* @param mimeType The given mime type
|
||||
* @return A likely mime type for the attachment
|
||||
*/
|
||||
public static String inferMimeType(final String fileName, final String mimeType) {
|
||||
String resultType = null;
|
||||
String fileExtension = getFilenameExtension(fileName);
|
||||
boolean isTextPlain = "text/plain".equalsIgnoreCase(mimeType);
|
||||
|
||||
if ("eml".equals(fileExtension)) {
|
||||
resultType = "message/rfc822";
|
||||
} else {
|
||||
boolean isGenericType =
|
||||
isTextPlain || "application/octet-stream".equalsIgnoreCase(mimeType);
|
||||
// If the given mime type is non-empty and non-generic, return it
|
||||
if (isGenericType || TextUtils.isEmpty(mimeType)) {
|
||||
if (!TextUtils.isEmpty(fileExtension)) {
|
||||
// Otherwise, try to find a mime type based upon the file extension
|
||||
resultType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
|
||||
if (TextUtils.isEmpty(resultType)) {
|
||||
// Finally, if original mimetype is text/plain, use it; otherwise synthesize
|
||||
resultType = isTextPlain ? mimeType : "application/" + fileExtension;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resultType = mimeType;
|
||||
}
|
||||
}
|
||||
|
||||
// No good guess could be made; use an appropriate generic type
|
||||
if (TextUtils.isEmpty(resultType)) {
|
||||
resultType = isTextPlain ? "text/plain" : "application/octet-stream";
|
||||
}
|
||||
return resultType.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and return filename's extension, converted to lower case, and not including the "."
|
||||
*
|
||||
* @return extension, or null if not found (or null/empty filename)
|
||||
*/
|
||||
public static String getFilenameExtension(String fileName) {
|
||||
String extension = null;
|
||||
if (!TextUtils.isEmpty(fileName)) {
|
||||
int lastDot = fileName.lastIndexOf('.');
|
||||
if ((lastDot > 0) && (lastDot < fileName.length() - 1)) {
|
||||
extension = fileName.substring(lastDot + 1).toLowerCase();
|
||||
}
|
||||
}
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an attachment file. There are two "modes" - "raw", which returns an actual file,
|
||||
* and "thumbnail", which attempts to generate a thumbnail image.
|
||||
|
@ -275,17 +141,17 @@ public class AttachmentProvider extends ContentProvider {
|
|||
String accountId = segments.get(0);
|
||||
String id = segments.get(1);
|
||||
String format = segments.get(2);
|
||||
if (FORMAT_THUMBNAIL.equals(format)) {
|
||||
if (AttachmentUtilities.FORMAT_THUMBNAIL.equals(format)) {
|
||||
int width = Integer.parseInt(segments.get(3));
|
||||
int height = Integer.parseInt(segments.get(4));
|
||||
String filename = "thmb_" + accountId + "_" + id;
|
||||
File dir = getContext().getCacheDir();
|
||||
File file = new File(dir, filename);
|
||||
if (!file.exists()) {
|
||||
Uri attachmentUri =
|
||||
Uri attachmentUri = AttachmentUtilities.
|
||||
getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id));
|
||||
Cursor c = query(attachmentUri,
|
||||
new String[] { AttachmentProviderColumns.DATA }, null, null, null);
|
||||
new String[] { Columns.DATA }, null, null, null);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
|
@ -355,8 +221,8 @@ public class AttachmentProvider extends ContentProvider {
|
|||
if (projection == null) {
|
||||
projection =
|
||||
new String[] {
|
||||
AttachmentProviderColumns._ID,
|
||||
AttachmentProviderColumns.DATA,
|
||||
Columns._ID,
|
||||
Columns.DATA,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -387,16 +253,16 @@ public class AttachmentProvider extends ContentProvider {
|
|||
Object[] values = new Object[projection.length];
|
||||
for (int i = 0, count = projection.length; i < count; i++) {
|
||||
String column = projection[i];
|
||||
if (AttachmentProviderColumns._ID.equals(column)) {
|
||||
if (Columns._ID.equals(column)) {
|
||||
values[i] = id;
|
||||
}
|
||||
else if (AttachmentProviderColumns.DATA.equals(column)) {
|
||||
else if (Columns.DATA.equals(column)) {
|
||||
values[i] = contentUri;
|
||||
}
|
||||
else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) {
|
||||
else if (Columns.DISPLAY_NAME.equals(column)) {
|
||||
values[i] = name;
|
||||
}
|
||||
else if (AttachmentProviderColumns.SIZE.equals(column)) {
|
||||
else if (Columns.SIZE.equals(column)) {
|
||||
values[i] = size;
|
||||
}
|
||||
}
|
||||
|
@ -432,101 +298,6 @@ public class AttachmentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve attachment id to content URI. Returns the resolved content URI (from the attachment
|
||||
* DB) or, if not found, simply returns the incoming value.
|
||||
*
|
||||
* @param attachmentUri
|
||||
* @return resolved content URI
|
||||
*
|
||||
* TODO: Throws an SQLite exception on a missing DB file (e.g. unknown URI) instead of just
|
||||
* returning the incoming uri, as it should.
|
||||
*/
|
||||
public static Uri resolveAttachmentIdToContentUri(ContentResolver resolver, Uri attachmentUri) {
|
||||
Cursor c = resolver.query(attachmentUri,
|
||||
new String[] { AttachmentProvider.AttachmentProviderColumns.DATA },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
final String strUri = c.getString(0);
|
||||
if (strUri != null) {
|
||||
return Uri.parse(strUri);
|
||||
} else {
|
||||
Email.log("AttachmentProvider: attachment with null contentUri");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
return attachmentUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a message, find all attachments and delete associated attachment
|
||||
* files.
|
||||
* @param context
|
||||
* @param accountId the account for the message
|
||||
* @param messageId the message
|
||||
*/
|
||||
public static void deleteAllAttachmentFiles(Context context, long accountId, long messageId) {
|
||||
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, messageId);
|
||||
Cursor c = context.getContentResolver().query(uri, Attachment.ID_PROJECTION,
|
||||
null, null, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
long attachmentId = c.getLong(Attachment.ID_PROJECTION_COLUMN);
|
||||
File attachmentFile = getAttachmentFilename(context, accountId, attachmentId);
|
||||
// Note, delete() throws no exceptions for basic FS errors (e.g. file not found)
|
||||
// it just returns false, which we ignore, and proceed to the next file.
|
||||
// This entire loop is best-effort only.
|
||||
attachmentFile.delete();
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a mailbox, find all messages and delete their attachments.
|
||||
*
|
||||
* @param context
|
||||
* @param accountId the account for the mailbox
|
||||
* @param mailboxId the mailbox for the messages
|
||||
*/
|
||||
public static void deleteAllMailboxAttachmentFiles(Context context, long accountId,
|
||||
long mailboxId) {
|
||||
Cursor c = context.getContentResolver().query(Message.CONTENT_URI,
|
||||
Message.ID_COLUMN_PROJECTION, MessageColumns.MAILBOX_KEY + "=?",
|
||||
new String[] { Long.toString(mailboxId) }, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
long messageId = c.getLong(Message.ID_PROJECTION_COLUMN);
|
||||
deleteAllAttachmentFiles(context, accountId, messageId);
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting or wiping an account, delete all related attachments.
|
||||
*
|
||||
* @param context
|
||||
* @param accountId the account to scrub
|
||||
*/
|
||||
public static void deleteAllAccountAttachmentFiles(Context context, long accountId) {
|
||||
File[] files = getAttachmentDirectory(context, accountId).listFiles();
|
||||
if (files == null) return;
|
||||
for (File file : files) {
|
||||
boolean result = file.delete();
|
||||
if (!result) {
|
||||
Log.e(Email.LOG_TAG, "Failed to delete attachment file " + file.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Need this to suppress warning in unit tests.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.email.service;
|
||||
|
||||
import com.android.email.AccountBackupRestore;
|
||||
import com.android.email.NotificationController;
|
||||
import com.android.email.ResourceHelper;
|
||||
import com.android.emailcommon.service.IAccountService;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public class AccountService extends Service {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private final IAccountService.Stub mBinder = new IAccountService.Stub() {
|
||||
|
||||
@Override
|
||||
public void notifyLoginFailed(long accountId) throws RemoteException {
|
||||
NotificationController.getInstance(mContext).showLoginFailedNotification(accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLoginSucceeded(long accountId) throws RemoteException {
|
||||
NotificationController.getInstance(mContext).cancelLoginFailedNotification(accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewMessages(long accountId) throws RemoteException {
|
||||
MailService.actionNotifyNewMessages(mContext, accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreAccountsIfNeeded() throws RemoteException {
|
||||
AccountBackupRestore.restoreAccountsIfNeeded(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountDeleted() throws RemoteException {
|
||||
MailService.accountDeleted(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccountColor(long accountId) throws RemoteException {
|
||||
return ResourceHelper.getInstance(mContext).getAccountColor(accountId);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (mContext == null) {
|
||||
mContext = this;
|
||||
}
|
||||
return mBinder;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@ import com.android.email.NotificationController;
|
|||
import com.android.email.Utility;
|
||||
import com.android.email.Controller.ControllerService;
|
||||
import com.android.email.ExchangeUtils.NullEmailService;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
|
@ -31,6 +30,7 @@ import com.android.email.provider.EmailContent.Message;
|
|||
import com.android.emailcommon.service.EmailServiceProxy;
|
||||
import com.android.emailcommon.service.EmailServiceStatus;
|
||||
import com.android.emailcommon.service.IEmailServiceCallback;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.exchange.ExchangeService;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
|
@ -427,7 +427,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||
*/
|
||||
private void startDownload(Class<? extends Service> serviceClass, DownloadRequest req)
|
||||
throws RemoteException {
|
||||
File file = AttachmentProvider.getAttachmentFilename(mContext, req.accountId,
|
||||
File file = AttachmentUtilities.getAttachmentFilename(mContext, req.accountId,
|
||||
req.attachmentId);
|
||||
req.startTime = System.currentTimeMillis();
|
||||
req.inProgress = true;
|
||||
|
@ -437,7 +437,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||
EmailServiceProxy proxy =
|
||||
new EmailServiceProxy(mContext, serviceClass, mServiceCallback);
|
||||
proxy.loadAttachment(req.attachmentId, file.getAbsolutePath(),
|
||||
AttachmentProvider.getAttachmentUri(req.accountId, req.attachmentId)
|
||||
AttachmentUtilities.getAttachmentUri(req.accountId, req.attachmentId)
|
||||
.toString(), req.priority != PRIORITY_FOREGROUND);
|
||||
// Lazily initialize our (reusable) pending intent
|
||||
if (mWatchdogPendingIntent == null) {
|
||||
|
@ -949,7 +949,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||
if (att.mMimeType != null) {
|
||||
pw.print(att.mMimeType);
|
||||
} else {
|
||||
pw.print(AttachmentProvider.inferMimeType(fileName, null));
|
||||
pw.print(AttachmentUtilities.inferMimeType(fileName, null));
|
||||
pw.print(" [inferred]");
|
||||
}
|
||||
pw.println(" Size: " + att.mSize);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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.service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public class AccountServiceProxy extends ServiceProxy implements IAccountService {
|
||||
|
||||
public static final String ACCOUNT_INTENT = "com.android.email.ACCOUNT_INTENT";
|
||||
public static final int DEFAULT_ACCOUNT_COLOR = 0xFF0000FF;
|
||||
|
||||
private IAccountService mService = null;
|
||||
private Object mReturn;
|
||||
|
||||
public AccountServiceProxy(Context _context) {
|
||||
super(_context, new Intent(ACCOUNT_INTENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(IBinder binder) {
|
||||
mService = IAccountService.Stub.asInterface(binder);
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLoginFailed(final long accountId) throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException {
|
||||
mService.notifyLoginFailed(accountId);
|
||||
}
|
||||
}, "notifyLoginFailed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLoginSucceeded(final long accountId) throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException {
|
||||
mService.notifyLoginSucceeded(accountId);
|
||||
}
|
||||
}, "notifyLoginSucceeded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewMessages(final long accountId) throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException {
|
||||
mService.notifyNewMessages(accountId);
|
||||
}
|
||||
}, "notifyNewMessages");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountDeleted() throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException {
|
||||
mService.accountDeleted();
|
||||
}
|
||||
}, "accountDeleted");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreAccountsIfNeeded() throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException {
|
||||
mService.restoreAccountsIfNeeded();
|
||||
}
|
||||
}, "restoreAccountsIfNeeded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccountColor(final long accountId) throws RemoteException {
|
||||
setTask(new ProxyTask() {
|
||||
public void run() throws RemoteException{
|
||||
mReturn = mService.getAccountColor(accountId);
|
||||
}
|
||||
}, "getAccountColor");
|
||||
waitForCompletion();
|
||||
if (mReturn == null) {
|
||||
return DEFAULT_ACCOUNT_COLOR;
|
||||
} else {
|
||||
return (Integer)mReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.service;
|
||||
|
||||
interface IAccountService {
|
||||
oneway void notifyLoginFailed(long accountId);
|
||||
oneway void notifyLoginSucceeded(long accountId);
|
||||
oneway void notifyNewMessages(long accountId);
|
||||
|
||||
void accountDeleted();
|
||||
void restoreAccountsIfNeeded();
|
||||
|
||||
int getAccountColor(long accountId);
|
||||
}
|
|
@ -223,6 +223,5 @@ public class PolicyServiceProxy extends ServiceProxy implements IPolicyService {
|
|||
}
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.service;
|
||||
|
||||
public class SyncWindow {
|
||||
public static final int SYNC_WINDOW_USER = -1;
|
||||
public static final int SYNC_WINDOW_1_DAY = 1;
|
||||
public static final int SYNC_WINDOW_3_DAYS = 2;
|
||||
public static final int SYNC_WINDOW_1_WEEK = 3;
|
||||
public static final int SYNC_WINDOW_2_WEEKS = 4;
|
||||
public static final int SYNC_WINDOW_1_MONTH = 5;
|
||||
public static final int SYNC_WINDOW_ALL = 6;
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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.utility;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class AccountReconciler {
|
||||
/**
|
||||
* Compare our account list (obtained from EmailProvider) with the account list owned by
|
||||
* AccountManager. If there are any orphans (an account in one list without a corresponding
|
||||
* account in the other list), delete the orphan, as these must remain in sync.
|
||||
*
|
||||
* Note that the duplication of account information is caused by the Email application's
|
||||
* incomplete integration with AccountManager.
|
||||
*
|
||||
* This function may not be called from the main/UI thread, because it makes blocking calls
|
||||
* into the account manager.
|
||||
*
|
||||
* @param context The context in which to operate
|
||||
* @param emailProviderAccounts the exchange provider accounts to work from
|
||||
* @param accountManagerAccounts The account manager accounts to work from
|
||||
* @param resolver the content resolver for making provider updates (injected for testability)
|
||||
*/
|
||||
public static boolean reconcileAccounts(Context context,
|
||||
List<Account> emailProviderAccounts, android.accounts.Account[] accountManagerAccounts,
|
||||
ContentResolver resolver) {
|
||||
// First, look through our EmailProvider accounts to make sure there's a corresponding
|
||||
// AccountManager account
|
||||
boolean accountsDeleted = false;
|
||||
for (Account providerAccount: emailProviderAccounts) {
|
||||
String providerAccountName = providerAccount.mEmailAddress;
|
||||
boolean found = false;
|
||||
for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
|
||||
if (accountManagerAccount.name.equalsIgnoreCase(providerAccountName)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if ((providerAccount.mFlags & Account.FLAGS_INCOMPLETE) != 0) {
|
||||
if (Email.DEBUG) {
|
||||
Log.d(Email.LOG_TAG,
|
||||
"Account reconciler noticed incomplete account; ignoring");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// This account has been deleted in the AccountManager!
|
||||
Log.d(Email.LOG_TAG, "Account deleted in AccountManager; deleting from provider: " +
|
||||
providerAccountName);
|
||||
// TODO This will orphan downloaded attachments; need to handle this
|
||||
resolver.delete(ContentUris.withAppendedId(Account.CONTENT_URI,
|
||||
providerAccount.mId), null, null);
|
||||
accountsDeleted = true;
|
||||
}
|
||||
}
|
||||
// Now, look through AccountManager accounts to make sure we have a corresponding cached EAS
|
||||
// account from EmailProvider
|
||||
for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
|
||||
String accountManagerAccountName = accountManagerAccount.name;
|
||||
boolean found = false;
|
||||
for (Account cachedEasAccount: emailProviderAccounts) {
|
||||
if (cachedEasAccount.mEmailAddress.equalsIgnoreCase(accountManagerAccountName)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// This account has been deleted from the EmailProvider database
|
||||
Log.d(Email.LOG_TAG,
|
||||
"Account deleted from provider; deleting from AccountManager: " +
|
||||
accountManagerAccountName);
|
||||
// Delete the account
|
||||
AccountManagerFuture<Boolean> blockingResult = AccountManager.get(context)
|
||||
.removeAccount(accountManagerAccount, null, null);
|
||||
try {
|
||||
// Note: All of the potential errors from removeAccount() are simply logged
|
||||
// here, as there is nothing to actually do about them.
|
||||
blockingResult.getResult();
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.w(Email.LOG_TAG, e.toString());
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.w(Email.LOG_TAG, e.toString());
|
||||
} catch (IOException e) {
|
||||
Log.w(Email.LOG_TAG, e.toString());
|
||||
}
|
||||
accountsDeleted = true;
|
||||
}
|
||||
}
|
||||
return accountsDeleted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* 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.utility;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.provider.EmailContent.MessageColumns;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class AttachmentUtilities {
|
||||
public static final String AUTHORITY = "com.android.email.attachmentprovider";
|
||||
public static final Uri CONTENT_URI = Uri.parse( "content://" + AUTHORITY);
|
||||
|
||||
public static final String FORMAT_RAW = "RAW";
|
||||
public static final String FORMAT_THUMBNAIL = "THUMBNAIL";
|
||||
|
||||
public static class Columns {
|
||||
public static final String _ID = "_id";
|
||||
public static final String DATA = "_data";
|
||||
public static final String DISPLAY_NAME = "_display_name";
|
||||
public static final String SIZE = "_size";
|
||||
}
|
||||
|
||||
public static Uri getAttachmentUri(long accountId, long id) {
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(accountId))
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getAttachmentThumbnailUri(long accountId, long id,
|
||||
int width, int height) {
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(accountId))
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_THUMBNAIL)
|
||||
.appendPath(Integer.toString(width))
|
||||
.appendPath(Integer.toString(height))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filename for a given attachment. This should be used by any code that is
|
||||
* going to *write* attachments.
|
||||
*
|
||||
* This does not create or write the file, or even the directories. It simply builds
|
||||
* the filename that should be used.
|
||||
*/
|
||||
public static File getAttachmentFilename(Context context, long accountId, long attachmentId) {
|
||||
return new File(getAttachmentDirectory(context, accountId), Long.toString(attachmentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the directory for a given attachment. This should be used by any code that is
|
||||
* going to *write* attachments.
|
||||
*
|
||||
* This does not create or write the directory. It simply builds the pathname that should be
|
||||
* used.
|
||||
*/
|
||||
public static File getAttachmentDirectory(Context context, long accountId) {
|
||||
return context.getDatabasePath(accountId + ".db_att");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to convert unknown or unmapped attachments to something useful based on filename
|
||||
* extensions. The mime type is inferred based upon the table below. It's not perfect, but
|
||||
* it helps.
|
||||
*
|
||||
* <pre>
|
||||
* |---------------------------------------------------------|
|
||||
* | E X T E N S I O N |
|
||||
* |---------------------------------------------------------|
|
||||
* | .eml | known(.png) | unknown(.abc) | none |
|
||||
* | M |-----------------------------------------------------------------------|
|
||||
* | I | none | msg/rfc822 | image/png | app/abc | app/oct-str |
|
||||
* | M |-------------| (always | | | |
|
||||
* | E | app/oct-str | overrides | | | |
|
||||
* | T |-------------| | |-----------------------------|
|
||||
* | Y | text/plain | | | text/plain |
|
||||
* | P |-------------| |-------------------------------------------|
|
||||
* | E | any/type | | any/type |
|
||||
* |---|-----------------------------------------------------------------------|
|
||||
* </pre>
|
||||
*
|
||||
* NOTE: Since mime types on Android are case-*sensitive*, return values are always in
|
||||
* lower case.
|
||||
*
|
||||
* @param fileName The given filename
|
||||
* @param mimeType The given mime type
|
||||
* @return A likely mime type for the attachment
|
||||
*/
|
||||
public static String inferMimeType(final String fileName, final String mimeType) {
|
||||
String resultType = null;
|
||||
String fileExtension = getFilenameExtension(fileName);
|
||||
boolean isTextPlain = "text/plain".equalsIgnoreCase(mimeType);
|
||||
|
||||
if ("eml".equals(fileExtension)) {
|
||||
resultType = "message/rfc822";
|
||||
} else {
|
||||
boolean isGenericType =
|
||||
isTextPlain || "application/octet-stream".equalsIgnoreCase(mimeType);
|
||||
// If the given mime type is non-empty and non-generic, return it
|
||||
if (isGenericType || TextUtils.isEmpty(mimeType)) {
|
||||
if (!TextUtils.isEmpty(fileExtension)) {
|
||||
// Otherwise, try to find a mime type based upon the file extension
|
||||
resultType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
|
||||
if (TextUtils.isEmpty(resultType)) {
|
||||
// Finally, if original mimetype is text/plain, use it; otherwise synthesize
|
||||
resultType = isTextPlain ? mimeType : "application/" + fileExtension;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resultType = mimeType;
|
||||
}
|
||||
}
|
||||
|
||||
// No good guess could be made; use an appropriate generic type
|
||||
if (TextUtils.isEmpty(resultType)) {
|
||||
resultType = isTextPlain ? "text/plain" : "application/octet-stream";
|
||||
}
|
||||
return resultType.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and return filename's extension, converted to lower case, and not including the "."
|
||||
*
|
||||
* @return extension, or null if not found (or null/empty filename)
|
||||
*/
|
||||
public static String getFilenameExtension(String fileName) {
|
||||
String extension = null;
|
||||
if (!TextUtils.isEmpty(fileName)) {
|
||||
int lastDot = fileName.lastIndexOf('.');
|
||||
if ((lastDot > 0) && (lastDot < fileName.length() - 1)) {
|
||||
extension = fileName.substring(lastDot + 1).toLowerCase();
|
||||
}
|
||||
}
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve attachment id to content URI. Returns the resolved content URI (from the attachment
|
||||
* DB) or, if not found, simply returns the incoming value.
|
||||
*
|
||||
* @param attachmentUri
|
||||
* @return resolved content URI
|
||||
*
|
||||
* TODO: Throws an SQLite exception on a missing DB file (e.g. unknown URI) instead of just
|
||||
* returning the incoming uri, as it should.
|
||||
*/
|
||||
public static Uri resolveAttachmentIdToContentUri(ContentResolver resolver, Uri attachmentUri) {
|
||||
Cursor c = resolver.query(attachmentUri,
|
||||
new String[] { Columns.DATA },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
final String strUri = c.getString(0);
|
||||
if (strUri != null) {
|
||||
return Uri.parse(strUri);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
return attachmentUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a message, find all attachments and delete associated attachment
|
||||
* files.
|
||||
* @param context
|
||||
* @param accountId the account for the message
|
||||
* @param messageId the message
|
||||
*/
|
||||
public static void deleteAllAttachmentFiles(Context context, long accountId, long messageId) {
|
||||
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, messageId);
|
||||
Cursor c = context.getContentResolver().query(uri, Attachment.ID_PROJECTION,
|
||||
null, null, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
long attachmentId = c.getLong(Attachment.ID_PROJECTION_COLUMN);
|
||||
File attachmentFile = getAttachmentFilename(context, accountId, attachmentId);
|
||||
// Note, delete() throws no exceptions for basic FS errors (e.g. file not found)
|
||||
// it just returns false, which we ignore, and proceed to the next file.
|
||||
// This entire loop is best-effort only.
|
||||
attachmentFile.delete();
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a mailbox, find all messages and delete their attachments.
|
||||
*
|
||||
* @param context
|
||||
* @param accountId the account for the mailbox
|
||||
* @param mailboxId the mailbox for the messages
|
||||
*/
|
||||
public static void deleteAllMailboxAttachmentFiles(Context context, long accountId,
|
||||
long mailboxId) {
|
||||
Cursor c = context.getContentResolver().query(Message.CONTENT_URI,
|
||||
Message.ID_COLUMN_PROJECTION, MessageColumns.MAILBOX_KEY + "=?",
|
||||
new String[] { Long.toString(mailboxId) }, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
long messageId = c.getLong(Message.ID_PROJECTION_COLUMN);
|
||||
deleteAllAttachmentFiles(context, accountId, messageId);
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting or wiping an account, delete all related attachments.
|
||||
*
|
||||
* @param context
|
||||
* @param accountId the account to scrub
|
||||
*/
|
||||
public static void deleteAllAccountAttachmentFiles(Context context, long accountId) {
|
||||
File[] files = getAttachmentDirectory(context, accountId).listFiles();
|
||||
if (files == null) return;
|
||||
for (File file : files) {
|
||||
boolean result = file.delete();
|
||||
if (!result) {
|
||||
Log.e(Email.LOG_TAG, "Failed to delete attachment file " + file.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.utility;
|
||||
|
||||
import com.android.email.Snippet;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.internet.MimeHeader;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.EmailContent;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ConversionUtilities {
|
||||
/**
|
||||
* Values for HEADER_ANDROID_BODY_QUOTED_PART to tag body parts
|
||||
*/
|
||||
public static final String BODY_QUOTED_PART_REPLY = "quoted-reply";
|
||||
public static final String BODY_QUOTED_PART_FORWARD = "quoted-forward";
|
||||
public static final String BODY_QUOTED_PART_INTRO = "quoted-intro";
|
||||
|
||||
/**
|
||||
* Helper function to append text to a StringBuffer, creating it if necessary.
|
||||
* Optimization: The majority of the time we are *not* appending - we should have a path
|
||||
* that deals with single strings.
|
||||
*/
|
||||
private static StringBuffer appendTextPart(StringBuffer sb, String newText) {
|
||||
if (newText == null) {
|
||||
return sb;
|
||||
}
|
||||
else if (sb == null) {
|
||||
sb = new StringBuffer(newText);
|
||||
} else {
|
||||
if (sb.length() > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(newText);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy body text (plain and/or HTML) from MimeMessage to provider Message
|
||||
*/
|
||||
public static boolean updateBodyFields(EmailContent.Body body,
|
||||
EmailContent.Message localMessage, ArrayList<Part> viewables)
|
||||
throws MessagingException {
|
||||
|
||||
body.mMessageKey = localMessage.mId;
|
||||
|
||||
StringBuffer sbHtml = null;
|
||||
StringBuffer sbText = null;
|
||||
StringBuffer sbHtmlReply = null;
|
||||
StringBuffer sbTextReply = null;
|
||||
StringBuffer sbIntroText = null;
|
||||
|
||||
for (Part viewable : viewables) {
|
||||
String text = MimeUtility.getTextFromPart(viewable);
|
||||
String[] replyTags = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART);
|
||||
String replyTag = null;
|
||||
if (replyTags != null && replyTags.length > 0) {
|
||||
replyTag = replyTags[0];
|
||||
}
|
||||
// Deploy text as marked by the various tags
|
||||
boolean isHtml = "text/html".equalsIgnoreCase(viewable.getMimeType());
|
||||
|
||||
if (replyTag != null) {
|
||||
boolean isQuotedReply = BODY_QUOTED_PART_REPLY.equalsIgnoreCase(replyTag);
|
||||
boolean isQuotedForward = BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(replyTag);
|
||||
boolean isQuotedIntro = BODY_QUOTED_PART_INTRO.equalsIgnoreCase(replyTag);
|
||||
|
||||
if (isQuotedReply || isQuotedForward) {
|
||||
if (isHtml) {
|
||||
sbHtmlReply = appendTextPart(sbHtmlReply, text);
|
||||
} else {
|
||||
sbTextReply = appendTextPart(sbTextReply, text);
|
||||
}
|
||||
// Set message flags as well
|
||||
localMessage.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK;
|
||||
localMessage.mFlags |= isQuotedReply
|
||||
? EmailContent.Message.FLAG_TYPE_REPLY
|
||||
: EmailContent.Message.FLAG_TYPE_FORWARD;
|
||||
continue;
|
||||
}
|
||||
if (isQuotedIntro) {
|
||||
sbIntroText = appendTextPart(sbIntroText, text);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Most of the time, just process regular body parts
|
||||
if (isHtml) {
|
||||
sbHtml = appendTextPart(sbHtml, text);
|
||||
} else {
|
||||
sbText = appendTextPart(sbText, text);
|
||||
}
|
||||
}
|
||||
|
||||
// write the combined data to the body part
|
||||
if (!TextUtils.isEmpty(sbText)) {
|
||||
String text = sbText.toString();
|
||||
body.mTextContent = text;
|
||||
localMessage.mSnippet = Snippet.fromPlainText(text);
|
||||
}
|
||||
if (!TextUtils.isEmpty(sbHtml)) {
|
||||
String text = sbHtml.toString();
|
||||
body.mHtmlContent = text;
|
||||
if (localMessage.mSnippet == null) {
|
||||
localMessage.mSnippet = Snippet.fromHtmlText(text);
|
||||
}
|
||||
}
|
||||
if (sbHtmlReply != null && sbHtmlReply.length() != 0) {
|
||||
body.mHtmlReply = sbHtmlReply.toString();
|
||||
}
|
||||
if (sbTextReply != null && sbTextReply.length() != 0) {
|
||||
body.mTextReply = sbTextReply.toString();
|
||||
}
|
||||
if (sbIntroText != null && sbIntroText.length() != 0) {
|
||||
body.mIntroText = sbIntroText.toString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -17,9 +17,7 @@
|
|||
|
||||
package com.android.exchange;
|
||||
|
||||
import com.android.email.AccountBackupRestore;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.NotificationController;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.mail.transport.SSLUtils;
|
||||
import com.android.email.provider.EmailContent;
|
||||
|
@ -32,11 +30,12 @@ import com.android.email.provider.EmailContent.Mailbox;
|
|||
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.provider.EmailContent.SyncColumns;
|
||||
import com.android.email.service.MailService;
|
||||
import com.android.emailcommon.Api;
|
||||
import com.android.emailcommon.service.AccountServiceProxy;
|
||||
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.exchange.adapter.CalendarSyncAdapter;
|
||||
import com.android.exchange.adapter.ContactsSyncAdapter;
|
||||
import com.android.exchange.utility.FileLogger;
|
||||
|
@ -1046,8 +1045,15 @@ public class ExchangeService extends Service implements Runnable {
|
|||
// list, which would cause the deletion of all of our accounts
|
||||
AccountList accountList = collectEasAccounts(context, new AccountList());
|
||||
alwaysLog("Reconciling accounts...");
|
||||
MailService.reconcileAccountsWithAccountManager(context, accountList, accountMgrList,
|
||||
false, context.getContentResolver());
|
||||
boolean accountsDeleted = AccountReconciler.reconcileAccounts(context, accountList,
|
||||
accountMgrList, context.getContentResolver());
|
||||
if (accountsDeleted) {
|
||||
try {
|
||||
new AccountServiceProxy(context).accountDeleted();
|
||||
} catch (RemoteException e) {
|
||||
// ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void log(String str) {
|
||||
|
@ -1749,13 +1755,22 @@ public class ExchangeService extends Service implements Runnable {
|
|||
@Override
|
||||
public void run() {
|
||||
synchronized (sSyncLock) {
|
||||
// ExchangeService cannot start unless we can connect to AccountService
|
||||
if (!new AccountServiceProxy(ExchangeService.this).test()) {
|
||||
log("!!! Email application not found; stopping self");
|
||||
stopSelf();
|
||||
}
|
||||
// Restore accounts, if it has not happened already
|
||||
AccountBackupRestore.restoreAccountsIfNeeded(ExchangeService.this);
|
||||
try {
|
||||
new AccountServiceProxy(ExchangeService.this).restoreAccountsIfNeeded();
|
||||
} catch (RemoteException e) {
|
||||
// If we can't restore accounts, don't run
|
||||
return;
|
||||
}
|
||||
// Run the reconciler and clean up any mismatched accounts - if we weren't
|
||||
// running when accounts were deleted, it won't have been called.
|
||||
runAccountReconcilerSync(ExchangeService.this);
|
||||
// Update other services depending on final account configuration
|
||||
Email.setServicesEnabledSync(ExchangeService.this);
|
||||
maybeStartExchangeServiceThread();
|
||||
if (sServiceThread == null) {
|
||||
log("!!! EAS ExchangeService, stopping self");
|
||||
|
@ -2385,8 +2400,12 @@ public class ExchangeService extends Service implements Runnable {
|
|||
if (account == null) return;
|
||||
if (exchangeService.releaseSyncHolds(exchangeService,
|
||||
AbstractSyncService.EXIT_LOGIN_FAILURE, account)) {
|
||||
NotificationController.getInstance(exchangeService)
|
||||
.cancelLoginFailedNotification(accountId);
|
||||
try {
|
||||
new AccountServiceProxy(exchangeService).notifyLoginSucceeded(
|
||||
accountId);
|
||||
} catch (RemoteException e) {
|
||||
// No harm if the notification fails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2413,8 +2432,11 @@ public class ExchangeService extends Service implements Runnable {
|
|||
break;
|
||||
// These errors are not retried automatically
|
||||
case AbstractSyncService.EXIT_LOGIN_FAILURE:
|
||||
NotificationController.getInstance(exchangeService)
|
||||
.showLoginFailedNotification(m.mAccountKey);
|
||||
try {
|
||||
new AccountServiceProxy(exchangeService).notifyLoginFailed(m.mAccountKey);
|
||||
} catch (RemoteException e) {
|
||||
// ? Anything to do?
|
||||
}
|
||||
// Fall through
|
||||
case AbstractSyncService.EXIT_SECURITY_FAILURE:
|
||||
case AbstractSyncService.EXIT_EXCEPTION:
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.exchange;
|
||||
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.service.PolicyServiceProxy;
|
||||
import com.android.emailcommon.service.PolicySet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public class PolicyServiceDelegate {
|
||||
|
||||
public static boolean isActive(Context context, PolicySet policies) {
|
||||
try {
|
||||
return new PolicyServiceProxy(context).isActive(policies);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void policiesRequired(Context context, long accountId) {
|
||||
try {
|
||||
new PolicyServiceProxy(context).policiesRequired(accountId);
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void updatePolicies(Context context, long accountId) {
|
||||
try {
|
||||
new PolicyServiceProxy(context).updatePolicies(accountId);
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAccountHoldFlag(Context context, Account account, boolean newState) {
|
||||
try {
|
||||
new PolicyServiceProxy(context).setAccountHoldFlag(account.mId, newState);
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActiveAdmin(Context context) {
|
||||
try {
|
||||
return new PolicyServiceProxy(context).isActiveAdmin();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void remoteWipe(Context context) {
|
||||
try {
|
||||
new PolicyServiceProxy(context).remoteWipe();
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupported(Context context, PolicySet policies) {
|
||||
try {
|
||||
return new PolicyServiceProxy(context).isSupported(policies);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PolicySet clearUnsupportedPolicies(Context context, PolicySet policies) {
|
||||
try {
|
||||
return new PolicyServiceProxy(context).clearUnsupportedPolicies(policies);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
throw new IllegalStateException("PolicyService transaction failed");
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package com.android.exchange.adapter;
|
||||
|
||||
import com.android.email.LegacyConversions;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.mail.Address;
|
||||
import com.android.email.mail.MeetingInfo;
|
||||
|
@ -26,8 +25,8 @@ import com.android.email.mail.PackedString;
|
|||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.internet.MimeMessage;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.AccountColumns;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
|
@ -36,8 +35,10 @@ import com.android.email.provider.EmailContent.Mailbox;
|
|||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.provider.EmailContent.MessageColumns;
|
||||
import com.android.email.provider.EmailContent.SyncColumns;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.service.MailService;
|
||||
import com.android.emailcommon.service.AccountServiceProxy;
|
||||
import com.android.emailcommon.service.SyncWindow;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.emailcommon.utility.ConversionUtilities;
|
||||
import com.android.exchange.Eas;
|
||||
import com.android.exchange.EasSyncService;
|
||||
import com.android.exchange.MessageMoveRequest;
|
||||
|
@ -117,22 +118,23 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
|
|||
mService.clearRequests();
|
||||
mFetchRequestList.clear();
|
||||
// Delete attachments...
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(mContext, mAccount.mId, mMailbox.mId);
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext, mAccount.mId,
|
||||
mMailbox.mId);
|
||||
}
|
||||
|
||||
private String getEmailFilter() {
|
||||
switch (mAccount.mSyncLookback) {
|
||||
case com.android.email.Account.SYNC_WINDOW_1_DAY:
|
||||
case SyncWindow.SYNC_WINDOW_1_DAY:
|
||||
return Eas.FILTER_1_DAY;
|
||||
case com.android.email.Account.SYNC_WINDOW_3_DAYS:
|
||||
case SyncWindow.SYNC_WINDOW_3_DAYS:
|
||||
return Eas.FILTER_3_DAYS;
|
||||
case com.android.email.Account.SYNC_WINDOW_1_WEEK:
|
||||
case SyncWindow.SYNC_WINDOW_1_WEEK:
|
||||
return Eas.FILTER_1_WEEK;
|
||||
case com.android.email.Account.SYNC_WINDOW_2_WEEKS:
|
||||
case SyncWindow.SYNC_WINDOW_2_WEEKS:
|
||||
return Eas.FILTER_2_WEEKS;
|
||||
case com.android.email.Account.SYNC_WINDOW_1_MONTH:
|
||||
case SyncWindow.SYNC_WINDOW_1_MONTH:
|
||||
return Eas.FILTER_1_MONTH;
|
||||
case com.android.email.Account.SYNC_WINDOW_ALL:
|
||||
case SyncWindow.SYNC_WINDOW_ALL:
|
||||
return Eas.FILTER_ALL;
|
||||
default:
|
||||
return Eas.FILTER_1_WEEK;
|
||||
|
@ -496,7 +498,7 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
|
|||
MimeUtility.collectParts(mimeMessage, viewables, attachments);
|
||||
Body tempBody = new Body();
|
||||
// updateBodyFields fills in the content fields of the Body
|
||||
LegacyConversions.updateBodyFields(tempBody, msg, viewables);
|
||||
ConversionUtilities.updateBodyFields(tempBody, msg, viewables);
|
||||
// But we need them in the message itself for handling during commit()
|
||||
msg.mHtml = tempBody.mHtmlContent;
|
||||
msg.mText = tempBody.mTextContent;
|
||||
|
@ -770,7 +772,7 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
|
|||
for (Long id : deletedEmails) {
|
||||
ops.add(ContentProviderOperation.newDelete(
|
||||
ContentUris.withAppendedId(Message.CONTENT_URI, id)).build());
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mContext, mAccount.mId, id);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mContext, mAccount.mId, id);
|
||||
}
|
||||
|
||||
if (!changedEmails.isEmpty()) {
|
||||
|
@ -822,7 +824,11 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
|
|||
cv.put(EmailContent.ADD_COLUMN_NAME, notifyCount);
|
||||
Uri uri = ContentUris.withAppendedId(Account.ADD_TO_FIELD_URI, mAccount.mId);
|
||||
mContentResolver.update(uri, cv, null, null);
|
||||
MailService.actionNotifyNewMessages(mContext, mAccount.mId);
|
||||
try {
|
||||
new AccountServiceProxy(mService.mContext).notifyNewMessages(mAccount.mId);
|
||||
} catch (RemoteException e) {
|
||||
// ? Anything to do here?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
package com.android.exchange.adapter;
|
||||
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.AccountColumns;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.exchange.Eas;
|
||||
import com.android.exchange.ExchangeService;
|
||||
import com.android.exchange.MockParserStream;
|
||||
|
@ -187,7 +187,7 @@ public class FolderSyncParser extends AbstractSyncParser {
|
|||
ops.add(ContentProviderOperation.newDelete(
|
||||
ContentUris.withAppendedId(Mailbox.CONTENT_URI,
|
||||
c.getLong(0))).build());
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(mContext,
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext,
|
||||
mAccountId, mMailbox.mId);
|
||||
}
|
||||
} finally {
|
||||
|
|
|
@ -18,7 +18,6 @@ package com.android.exchange.utility;
|
|||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.R;
|
||||
import com.android.email.ResourceHelper;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.mail.Address;
|
||||
import com.android.email.provider.EmailContent;
|
||||
|
@ -26,6 +25,7 @@ import com.android.email.provider.EmailContent.Account;
|
|||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.service.AccountServiceProxy;
|
||||
import com.android.exchange.Eas;
|
||||
import com.android.exchange.EasSyncService;
|
||||
import com.android.exchange.ExchangeService;
|
||||
|
@ -1215,8 +1215,12 @@ public class CalendarUtilities {
|
|||
cv.put(Calendars.ORGANIZER_CAN_RESPOND, 0);
|
||||
|
||||
// TODO Coordinate account colors w/ Calendar, if possible
|
||||
// Make Email account color opaque
|
||||
int color = ResourceHelper.getInstance(service.mContext).getAccountColor(account.mId);
|
||||
int color = AccountServiceProxy.DEFAULT_ACCOUNT_COLOR;
|
||||
try {
|
||||
color = new AccountServiceProxy(service.mContext).getAccountColor(account.mId);
|
||||
} catch (RemoteException e) {
|
||||
// Use the default
|
||||
}
|
||||
cv.put(Calendars.COLOR, color);
|
||||
cv.put(Calendars.TIMEZONE, Time.getCurrentTimezone());
|
||||
cv.put(Calendars.ACCESS_LEVEL, Calendars.OWNER_ACCESS);
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.android.email.provider.AttachmentProvider;
|
|||
import com.android.email.provider.ContentCache;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
|
@ -37,8 +38,6 @@ import android.test.mock.MockCursor;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Helper classes (and possibly methods) for database related tests.
|
||||
*/
|
||||
|
@ -225,7 +224,7 @@ public final class DBTestHelper {
|
|||
|
||||
final AttachmentProvider ap = new AttachmentProvider();
|
||||
ap.attachInfo(providerContext, null);
|
||||
resolver.addProvider(AttachmentProvider.AUTHORITY, ap);
|
||||
resolver.addProvider(AttachmentUtilities.AUTHORITY, ap);
|
||||
|
||||
ContentCache.invalidateAllCachesForTest();
|
||||
|
||||
|
|
|
@ -20,21 +20,22 @@ import com.android.email.mail.Address;
|
|||
import com.android.email.mail.BodyPart;
|
||||
import com.android.email.mail.Flag;
|
||||
import com.android.email.mail.Message;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.MessageTestUtils;
|
||||
import com.android.email.mail.MessageTestUtils.MessageBuilder;
|
||||
import com.android.email.mail.MessageTestUtils.MultipartBuilder;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.MessageTestUtils.MessageBuilder;
|
||||
import com.android.email.mail.MessageTestUtils.MultipartBuilder;
|
||||
import com.android.email.mail.internet.MimeBodyPart;
|
||||
import com.android.email.mail.internet.MimeHeader;
|
||||
import com.android.email.mail.internet.MimeMessage;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.mail.internet.TextBody;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.emailcommon.utility.ConversionUtilities;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
|
@ -191,7 +192,7 @@ public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> {
|
|||
viewables.add(emptyTextPart);
|
||||
|
||||
// a "null" body part of type text/plain should result in a null mTextContent
|
||||
boolean result = LegacyConversions.updateBodyFields(localBody, localMessage, viewables);
|
||||
boolean result = ConversionUtilities.updateBodyFields(localBody, localMessage, viewables);
|
||||
assertTrue(result);
|
||||
assertNull(localBody.mTextContent);
|
||||
}
|
||||
|
|
|
@ -17,17 +17,16 @@
|
|||
package com.android.email;
|
||||
|
||||
import com.android.email.Utility.NewFileCreator;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
import android.database.MatrixCursor;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
@ -422,13 +421,13 @@ public class UtilityUnitTests extends AndroidTestCase {
|
|||
Attachment att = ProviderTestUtils.setupAttachment(mailbox.mId, "name", 123, true,
|
||||
providerContext);
|
||||
long attachmentId = att.mId;
|
||||
Uri uri = AttachmentProvider.getAttachmentUri(account.mId, attachmentId);
|
||||
Uri uri = AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
|
||||
|
||||
// Case 1: exists in the provider.
|
||||
assertEquals("name", Utility.getContentFileName(providerContext, uri));
|
||||
|
||||
// Case 2: doesn't exist in the provider
|
||||
Uri notExistUri = AttachmentProvider.getAttachmentUri(account.mId, 123456789);
|
||||
Uri notExistUri = AttachmentUtilities.getAttachmentUri(account.mId, 123456789);
|
||||
String lastPathSegment = notExistUri.getLastPathSegment();
|
||||
assertEquals(lastPathSegment, Utility.getContentFileName(providerContext, notExistUri));
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import com.android.email.mail.internet.MimeHeader;
|
|||
import com.android.email.mail.internet.MimeMessage;
|
||||
import com.android.email.mail.internet.MimeMultipart;
|
||||
import com.android.email.mail.internet.TextBody;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
|
@ -63,7 +63,7 @@ public class MessageTestUtils {
|
|||
* @return AttachmentProvider content URI
|
||||
*/
|
||||
public static Uri contentUri(long attachmentId, EmailContent.Account account) {
|
||||
return AttachmentProvider.getAttachmentUri(account.mId, attachmentId);
|
||||
return AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,11 +19,11 @@ package com.android.email.provider;
|
|||
import com.android.email.AttachmentInfo;
|
||||
import com.android.email.R;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.provider.AttachmentProvider.AttachmentProviderColumns;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
@ -53,7 +53,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
ContentResolver mMockResolver;
|
||||
|
||||
public AttachmentProviderTests() {
|
||||
super(AttachmentProvider.class, AttachmentProvider.AUTHORITY);
|
||||
super(AttachmentProvider.class, AttachmentUtilities.AUTHORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,9 +76,10 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
* test insert() - should do nothing
|
||||
*/
|
||||
public void testUnimplemented() {
|
||||
assertEquals(0, mMockResolver.delete(AttachmentProvider.CONTENT_URI, null, null));
|
||||
assertEquals(0, mMockResolver.update(AttachmentProvider.CONTENT_URI, null, null, null));
|
||||
assertEquals(null, mMockResolver.insert(AttachmentProvider.CONTENT_URI, null));
|
||||
assertEquals(0, mMockResolver.delete(AttachmentUtilities.CONTENT_URI, null, null));
|
||||
assertEquals(0, mMockResolver.update(AttachmentUtilities.CONTENT_URI, null, null,
|
||||
null));
|
||||
assertEquals(null, mMockResolver.insert(AttachmentUtilities.CONTENT_URI, null));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,9 +101,12 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on
|
||||
// a legitimate implementation. Asserts below will catch this and fail the test
|
||||
// if necessary.
|
||||
Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
|
||||
Uri attachment2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
|
||||
Uri attachment3Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
|
||||
Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
|
||||
attachment1Id);
|
||||
Uri attachment2Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
|
||||
attachment2Id);
|
||||
Uri attachment3Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
|
||||
attachment3Id);
|
||||
|
||||
// Test with no attachment found - should return null
|
||||
Cursor c = mMockResolver.query(attachment1Uri, (String[])null, null, (String[])null, null);
|
||||
|
@ -113,31 +117,32 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
Attachment newAttachment1 = ProviderTestUtils.setupAttachment(message1Id, "file1", 100,
|
||||
false, mMockContext);
|
||||
newAttachment1.mContentUri =
|
||||
AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id).toString();
|
||||
AttachmentUtilities.getAttachmentUri(account1.mId, attachment1Id).toString();
|
||||
attachment1Id = addAttachmentToDb(account1, newAttachment1);
|
||||
assertEquals("Broken test: Unexpected id assignment", 1, attachment1Id);
|
||||
|
||||
Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file2", 200,
|
||||
false, mMockContext);
|
||||
newAttachment2.mContentUri =
|
||||
AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
|
||||
AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id).toString();
|
||||
attachment2Id = addAttachmentToDb(account1, newAttachment2);
|
||||
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
|
||||
|
||||
Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 300,
|
||||
false, mMockContext);
|
||||
newAttachment3.mContentUri =
|
||||
AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id).toString();
|
||||
AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id).toString();
|
||||
attachment3Id = addAttachmentToDb(account1, newAttachment3);
|
||||
assertEquals("Broken test: Unexpected id assignment", 3, attachment3Id);
|
||||
|
||||
// Return a row with all columns specified
|
||||
attachment2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
|
||||
attachment2Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
|
||||
c = mMockResolver.query(
|
||||
attachment2Uri,
|
||||
new String[] { AttachmentProviderColumns._ID, AttachmentProviderColumns.DATA,
|
||||
AttachmentProviderColumns.DISPLAY_NAME,
|
||||
AttachmentProviderColumns.SIZE },
|
||||
new String[] { AttachmentUtilities.Columns._ID,
|
||||
AttachmentUtilities.Columns.DATA,
|
||||
AttachmentUtilities.Columns.DISPLAY_NAME,
|
||||
AttachmentUtilities.Columns.SIZE },
|
||||
null, null, null);
|
||||
assertEquals(1, c.getCount());
|
||||
assertTrue(c.moveToFirst());
|
||||
|
@ -147,12 +152,13 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
assertEquals(200, c.getInt(3)); // size
|
||||
|
||||
// Return a row with permuted columns
|
||||
attachment3Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
|
||||
attachment3Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id);
|
||||
c = mMockResolver.query(
|
||||
attachment3Uri,
|
||||
new String[] { AttachmentProviderColumns.SIZE,
|
||||
AttachmentProviderColumns.DISPLAY_NAME,
|
||||
AttachmentProviderColumns.DATA, AttachmentProviderColumns._ID },
|
||||
new String[] { AttachmentUtilities.Columns.SIZE,
|
||||
AttachmentUtilities.Columns.DISPLAY_NAME,
|
||||
AttachmentUtilities.Columns.DATA,
|
||||
AttachmentUtilities.Columns._ID },
|
||||
null, null, null);
|
||||
assertEquals(1, c.getCount());
|
||||
assertTrue(c.moveToFirst());
|
||||
|
@ -264,7 +270,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
long attachment5Id = 5;
|
||||
long attachment6Id = 6;
|
||||
|
||||
Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
|
||||
Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
|
||||
attachment1Id);
|
||||
|
||||
// Test with no attachment found - should return null
|
||||
String type = mMockResolver.getType(attachment1Uri);
|
||||
|
@ -298,27 +305,29 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
attachment6Id = addAttachmentToDb(account1, newAttachment6);
|
||||
|
||||
// Check the returned filetypes
|
||||
Uri uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
|
||||
Uri uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("image/jpg", type);
|
||||
uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
|
||||
uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("text/plain", type);
|
||||
uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment4Id);
|
||||
uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment4Id);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("application/msword", type);
|
||||
uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment5Id);
|
||||
uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment5Id);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("application/xyz", type);
|
||||
uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment6Id);
|
||||
uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment6Id);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("application/octet-stream", type);
|
||||
|
||||
// Check the returned filetypes for the thumbnails
|
||||
uri = AttachmentProvider.getAttachmentThumbnailUri(account1.mId, attachment2Id, 62, 62);
|
||||
uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId, attachment2Id, 62,
|
||||
62);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("image/png", type);
|
||||
uri = AttachmentProvider.getAttachmentThumbnailUri(account1.mId, attachment3Id, 62, 62);
|
||||
uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId, attachment3Id, 62,
|
||||
62);
|
||||
type = mMockResolver.getType(uri);
|
||||
assertEquals("image/png", type);
|
||||
}
|
||||
|
@ -355,42 +364,49 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
final String FILE_NO_EXT = "myfile";
|
||||
|
||||
// .eml files always override mime type
|
||||
assertEquals("message/rfc822", AttachmentProvider.inferMimeType("a.eml", null));
|
||||
assertEquals("message/rfc822", AttachmentProvider.inferMimeType("a.eml", ""));
|
||||
assertEquals("message/rfc822", AttachmentProvider.inferMimeType("a.eml", DEFAULT_LOWER));
|
||||
assertEquals("message/rfc822", AttachmentProvider.inferMimeType("a.eMl", TEXT_PLAIN));
|
||||
assertEquals("message/rfc822", AttachmentProvider.inferMimeType("a.eml", TYPE_IMG_PNG));
|
||||
assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", null));
|
||||
assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", ""));
|
||||
assertEquals("message/rfc822",
|
||||
AttachmentUtilities.inferMimeType("a.eml", DEFAULT_LOWER));
|
||||
assertEquals("message/rfc822",
|
||||
AttachmentUtilities.inferMimeType("a.eMl", TEXT_PLAIN));
|
||||
assertEquals("message/rfc822",
|
||||
AttachmentUtilities.inferMimeType("a.eml", TYPE_IMG_PNG));
|
||||
|
||||
// Non-generic, non-empty mime type; return it
|
||||
assertEquals("mime/type", AttachmentProvider.inferMimeType(FILE_PNG, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentProvider.inferMimeType(FILE_ABC, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentProvider.inferMimeType(FILE_NO_EXT, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentProvider.inferMimeType(null, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentProvider.inferMimeType("", "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_PNG, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_ABC, "Mime/TyPe"));
|
||||
assertEquals("mime/type",
|
||||
AttachmentUtilities.inferMimeType(FILE_NO_EXT, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentUtilities.inferMimeType(null, "Mime/TyPe"));
|
||||
assertEquals("mime/type", AttachmentUtilities.inferMimeType("", "Mime/TyPe"));
|
||||
|
||||
// Recognizable file extension; return known type
|
||||
assertEquals("image/png", AttachmentProvider.inferMimeType(FILE_PNG, null));
|
||||
assertEquals("image/png", AttachmentProvider.inferMimeType(FILE_PNG, ""));
|
||||
assertEquals("image/png", AttachmentProvider.inferMimeType(FILE_PNG, DEFAULT_MIX));
|
||||
assertEquals("image/png", AttachmentProvider.inferMimeType(FILE_PNG, TEXT_PLAIN));
|
||||
assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, null));
|
||||
assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, ""));
|
||||
assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, DEFAULT_MIX));
|
||||
assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, TEXT_PLAIN));
|
||||
|
||||
// Unrecognized and non-empty file extension, non-"text/plain" type; generate mime type
|
||||
assertEquals("application/abc", AttachmentProvider.inferMimeType(FILE_ABC, null));
|
||||
assertEquals("application/abc", AttachmentProvider.inferMimeType(FILE_ABC, ""));
|
||||
assertEquals("application/abc", AttachmentProvider.inferMimeType(FILE_ABC, DEFAULT_MIX));
|
||||
assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, null));
|
||||
assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, ""));
|
||||
assertEquals("application/abc",
|
||||
AttachmentUtilities.inferMimeType(FILE_ABC, DEFAULT_MIX));
|
||||
|
||||
// Unrecognized and empty file extension, non-"text/plain" type; return "app/octet-stream"
|
||||
assertEquals(DEFAULT_LOWER, AttachmentProvider.inferMimeType(FILE_NO_EXT, null));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentProvider.inferMimeType(FILE_NO_EXT, ""));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentProvider.inferMimeType(FILE_NO_EXT, DEFAULT_MIX));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentProvider.inferMimeType(null, null));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentProvider.inferMimeType("", ""));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, null));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, ""));
|
||||
assertEquals(DEFAULT_LOWER,
|
||||
AttachmentUtilities.inferMimeType(FILE_NO_EXT, DEFAULT_MIX));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(null, null));
|
||||
assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType("", ""));
|
||||
|
||||
// Unrecognized or empty file extension, "text/plain" type; return "text/plain"
|
||||
assertEquals(TEXT_PLAIN, AttachmentProvider.inferMimeType(FILE_ABC, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentProvider.inferMimeType(FILE_NO_EXT, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentProvider.inferMimeType(null, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentProvider.inferMimeType("", TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(FILE_ABC, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN,
|
||||
AttachmentUtilities.inferMimeType(FILE_NO_EXT, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(null, TEXT_PLAIN));
|
||||
assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType("", TEXT_PLAIN));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,17 +417,17 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
final String FILE_EXTENSION = "myfile.pDf";
|
||||
final String FILE_TWO_EXTENSIONS = "myfile.false.AbC";
|
||||
|
||||
assertNull(AttachmentProvider.getFilenameExtension(null));
|
||||
assertNull(AttachmentProvider.getFilenameExtension(""));
|
||||
assertNull(AttachmentProvider.getFilenameExtension(FILE_NO_EXTENSION));
|
||||
assertNull(AttachmentUtilities.getFilenameExtension(null));
|
||||
assertNull(AttachmentUtilities.getFilenameExtension(""));
|
||||
assertNull(AttachmentUtilities.getFilenameExtension(FILE_NO_EXTENSION));
|
||||
|
||||
assertEquals("pdf", AttachmentProvider.getFilenameExtension(FILE_EXTENSION));
|
||||
assertEquals("abc", AttachmentProvider.getFilenameExtension(FILE_TWO_EXTENSIONS));
|
||||
assertEquals("pdf", AttachmentUtilities.getFilenameExtension(FILE_EXTENSION));
|
||||
assertEquals("abc", AttachmentUtilities.getFilenameExtension(FILE_TWO_EXTENSIONS));
|
||||
|
||||
// The API makes no claim as to how these are handled (it probably should),
|
||||
// but make sure that they don't crash.
|
||||
AttachmentProvider.getFilenameExtension("filename.");
|
||||
AttachmentProvider.getFilenameExtension(".extension");
|
||||
AttachmentUtilities.getFilenameExtension("filename.");
|
||||
AttachmentUtilities.getFilenameExtension(".extension");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -431,8 +447,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on
|
||||
// a legitimate implementation. Asserts below will catch this and fail the test
|
||||
// if necessary.
|
||||
Uri file1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
|
||||
Uri file2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
|
||||
Uri file1Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment1Id);
|
||||
Uri file2Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
|
||||
|
||||
// Test with no attachment found
|
||||
AssetFileDescriptor afd;
|
||||
|
@ -463,7 +479,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
false, mMockContext);
|
||||
newAttachment2.mContentId = null;
|
||||
newAttachment2.mContentUri =
|
||||
AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
|
||||
AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id)
|
||||
.toString();
|
||||
newAttachment2.mMimeType = "image/png";
|
||||
attachment2Id = addAttachmentToDb(account1, newAttachment2);
|
||||
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
|
||||
|
@ -496,10 +513,10 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on
|
||||
// a legitimate implementation. Asserts below will catch this and fail the test
|
||||
// if necessary.
|
||||
Uri thumb1Uri = AttachmentProvider.getAttachmentThumbnailUri(account1.mId, attachment1Id,
|
||||
62, 62);
|
||||
Uri thumb2Uri = AttachmentProvider.getAttachmentThumbnailUri(account1.mId, attachment2Id,
|
||||
62, 62);
|
||||
Uri thumb1Uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId,
|
||||
attachment1Id, 62, 62);
|
||||
Uri thumb2Uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId,
|
||||
attachment2Id, 62, 62);
|
||||
|
||||
// Test with an attached database, but no attachment found
|
||||
AssetFileDescriptor afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r");
|
||||
|
@ -521,7 +538,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
false, mMockContext);
|
||||
newAttachment2.mContentId = null;
|
||||
newAttachment2.mContentUri =
|
||||
AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
|
||||
AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id)
|
||||
.toString();
|
||||
newAttachment2.mMimeType = "image/png";
|
||||
attachment2Id = addAttachmentToDb(account1, newAttachment2);
|
||||
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
|
||||
|
@ -539,7 +557,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
false, mMockContext);
|
||||
newAttachment.mContentUri = contentUriStr;
|
||||
long attachmentId = addAttachmentToDb(account, newAttachment);
|
||||
Uri attachmentUri = AttachmentProvider.getAttachmentUri(account.mId, attachmentId);
|
||||
Uri attachmentUri = AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
|
||||
return attachmentUri;
|
||||
}
|
||||
|
||||
|
@ -557,12 +575,13 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
final long message1Id = 1;
|
||||
// We use attachmentId == 1 but any other id would do
|
||||
final long attachment1Id = 1;
|
||||
final Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
|
||||
final Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
|
||||
attachment1Id);
|
||||
|
||||
// Test with no attachment found - should return input
|
||||
// We know that the attachmentId 1 does not exist because there are no attachments
|
||||
// created at this point
|
||||
Uri result = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
Uri result = AttachmentUtilities.resolveAttachmentIdToContentUri(
|
||||
mMockResolver, attachment1Uri);
|
||||
assertEquals(attachment1Uri, result);
|
||||
|
||||
|
@ -571,8 +590,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
// the DB, and does not sample the files, so we won't bother creating the files
|
||||
{
|
||||
Uri attachmentUri = createAttachment(account1, message1Id, "file:///path/to/file");
|
||||
Uri contentUri = AttachmentProvider.resolveAttachmentIdToContentUri(mMockResolver,
|
||||
attachmentUri);
|
||||
Uri contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
|
||||
mMockResolver, attachmentUri);
|
||||
// When the attachment is found, return the stored content_uri value
|
||||
assertEquals("file:///path/to/file", contentUri.toString());
|
||||
}
|
||||
|
@ -580,8 +599,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
// Test with existing attachement and contentUri == null
|
||||
{
|
||||
Uri attachmentUri = createAttachment(account1, message1Id, null);
|
||||
Uri contentUri = AttachmentProvider.resolveAttachmentIdToContentUri(mMockResolver,
|
||||
attachmentUri);
|
||||
Uri contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
|
||||
mMockResolver, attachmentUri);
|
||||
// When contentUri is null should return input
|
||||
assertEquals(attachmentUri, contentUri);
|
||||
}
|
||||
|
@ -615,25 +634,30 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
createAttachmentFile(account1, newAttachment3.mId);
|
||||
|
||||
// Confirm 3 attachment files found
|
||||
File attachmentsDir = AttachmentProvider.getAttachmentDirectory(mMockContext, account1.mId);
|
||||
File attachmentsDir = AttachmentUtilities.getAttachmentDirectory(mMockContext,
|
||||
account1.mId);
|
||||
assertEquals(3, attachmentsDir.listFiles().length);
|
||||
|
||||
// Command deletion of some files and check for results
|
||||
|
||||
// Message 4 has no attachments so no files should be deleted
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mMockContext, account1.mId, message4Id);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
|
||||
message4Id);
|
||||
assertEquals(3, attachmentsDir.listFiles().length);
|
||||
|
||||
// Message 3 has no attachment files so no files should be deleted
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mMockContext, account1.mId, message3Id);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
|
||||
message3Id);
|
||||
assertEquals(3, attachmentsDir.listFiles().length);
|
||||
|
||||
// Message 2 has 2 attachment files so this should delete 2 files
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mMockContext, account1.mId, message2Id);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
|
||||
message2Id);
|
||||
assertEquals(1, attachmentsDir.listFiles().length);
|
||||
|
||||
// Message 1 has 1 attachment file so this should delete the last file
|
||||
AttachmentProvider.deleteAllAttachmentFiles(mMockContext, account1.mId, message1Id);
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
|
||||
message1Id);
|
||||
assertEquals(0, attachmentsDir.listFiles().length);
|
||||
}
|
||||
|
||||
|
@ -655,15 +679,18 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
populateAccountMailbox(account1, mailbox2Id, 1);
|
||||
|
||||
// Confirm four attachment files found
|
||||
File attachmentsDir = AttachmentProvider.getAttachmentDirectory(mMockContext, account1.mId);
|
||||
File attachmentsDir = AttachmentUtilities.getAttachmentDirectory(mMockContext,
|
||||
account1.mId);
|
||||
assertEquals(4, attachmentsDir.listFiles().length);
|
||||
|
||||
// Command the deletion of mailbox 1 - we should lose 3 attachment files
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(mMockContext, account1Id, mailbox1Id);
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(mMockContext, account1Id,
|
||||
mailbox1Id);
|
||||
assertEquals(1, attachmentsDir.listFiles().length);
|
||||
|
||||
// Command the deletion of mailbox 2 - we should lose 1 attachment file
|
||||
AttachmentProvider.deleteAllMailboxAttachmentFiles(mMockContext, account1Id, mailbox2Id);
|
||||
AttachmentUtilities.deleteAllMailboxAttachmentFiles(mMockContext, account1Id,
|
||||
mailbox2Id);
|
||||
assertEquals(0, attachmentsDir.listFiles().length);
|
||||
}
|
||||
|
||||
|
@ -697,18 +724,20 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
|
|||
populateAccountMailbox(account2, mailbox4Id, 2);
|
||||
|
||||
// Confirm eleven attachment files found
|
||||
File directory1 = AttachmentProvider.getAttachmentDirectory(mMockContext, account1.mId);
|
||||
File directory1 = AttachmentUtilities.getAttachmentDirectory(mMockContext,
|
||||
account1.mId);
|
||||
assertEquals(4, directory1.listFiles().length);
|
||||
File directory2 = AttachmentProvider.getAttachmentDirectory(mMockContext, account2.mId);
|
||||
File directory2 = AttachmentUtilities.getAttachmentDirectory(mMockContext,
|
||||
account2.mId);
|
||||
assertEquals(7, directory2.listFiles().length);
|
||||
|
||||
// Command the deletion of account 1 - we should lose 4 attachment files
|
||||
AttachmentProvider.deleteAllAccountAttachmentFiles(mMockContext, account1Id);
|
||||
AttachmentUtilities.deleteAllAccountAttachmentFiles(mMockContext, account1Id);
|
||||
assertEquals(0, directory1.listFiles().length);
|
||||
assertEquals(7, directory2.listFiles().length);
|
||||
|
||||
// Command the deletion of account 2 - we should lose 7 attachment file
|
||||
AttachmentProvider.deleteAllAccountAttachmentFiles(mMockContext, account2Id);
|
||||
AttachmentUtilities.deleteAllAccountAttachmentFiles(mMockContext, account2Id);
|
||||
assertEquals(0, directory1.listFiles().length);
|
||||
assertEquals(0, directory2.listFiles().length);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue