Fix problem with sending attachments in Exchange

The problem was that when the attachment was attempted to be opened
from the Exchange process, it didn't have access to the cached file.
Instead, use a content provider uri to reference the cached file.

Bug: 8400456

Change-Id: I80abd66642e938cf09f73bf0e9bd049aa8d7ba1d
This commit is contained in:
Paul Westbrook 2013-03-21 16:54:49 -07:00
parent 68a8e21248
commit 5a3aebbd2d
4 changed files with 70 additions and 16 deletions

View File

@ -239,11 +239,12 @@ public class Rfc822Output {
inStream = new ByteArrayInputStream(attachment.mContentBytes);
} else {
// First try the cached file
final String cachedFile = attachment.getCachedFilePath();
final String cachedFile = attachment.getCachedFileUri();
if (!TextUtils.isEmpty(cachedFile)) {
final Uri cachedFileUri = Uri.parse(cachedFile);
try {
inStream = new FileInputStream(cachedFile);
} catch (IOException e) {
inStream = context.getContentResolver().openInputStream(cachedFileUri);
} catch (FileNotFoundException e) {
// Couldn't open the cached file, fall back to the original content uri
inStream = null;

View File

@ -1196,6 +1196,8 @@ public abstract class EmailContent {
public static final String ATTACHMENT_PROVIDER_LEGACY_URI_PREFIX =
"content://com.android.email.attachmentprovider";
public static final String CACHED_FILE_QUERY_PARAM = "filePath";
public static Uri CONTENT_URI;
// This must be used with an appended id: ContentUris.withAppendedId(MESSAGE_ID_URI, id)
public static Uri MESSAGE_ID_URI;
@ -1217,7 +1219,7 @@ public abstract class EmailContent {
public long mSize;
public String mContentId;
private String mContentUri;
private String mCachedFile;
private String mCachedFileUri;
public long mMessageKey;
public String mLocation;
public String mEncoding;
@ -1295,12 +1297,12 @@ public abstract class EmailContent {
mBaseUri = CONTENT_URI;
}
public void setCachedFilePath(String cachedFile) {
mCachedFile = cachedFile;
public void setCachedFileUri(String cachedFile) {
mCachedFileUri = cachedFile;
}
public String getCachedFilePath() {
return mCachedFile;
public String getCachedFileUri() {
return mCachedFileUri;
}
public void setContentUri(String contentUri) {
@ -1404,7 +1406,7 @@ public abstract class EmailContent {
mSize = cursor.getLong(CONTENT_SIZE_COLUMN);
mContentId = cursor.getString(CONTENT_CONTENT_ID_COLUMN);
mContentUri = cursor.getString(CONTENT_CONTENT_URI_COLUMN);
mCachedFile = cursor.getString(CONTENT_CACHED_FILE_COLUMN);
mCachedFileUri = cursor.getString(CONTENT_CACHED_FILE_COLUMN);
mMessageKey = cursor.getLong(CONTENT_MESSAGE_ID_COLUMN);
mLocation = cursor.getString(CONTENT_LOCATION_COLUMN);
mEncoding = cursor.getString(CONTENT_ENCODING_COLUMN);
@ -1425,7 +1427,7 @@ public abstract class EmailContent {
values.put(AttachmentColumns.SIZE, mSize);
values.put(AttachmentColumns.CONTENT_ID, mContentId);
values.put(AttachmentColumns.CONTENT_URI, mContentUri);
values.put(AttachmentColumns.CACHED_FILE, mCachedFile);
values.put(AttachmentColumns.CACHED_FILE, mCachedFileUri);
values.put(AttachmentColumns.MESSAGE_KEY, mMessageKey);
values.put(AttachmentColumns.LOCATION, mLocation);
values.put(AttachmentColumns.ENCODING, mEncoding);
@ -1453,7 +1455,7 @@ public abstract class EmailContent {
dest.writeLong(mSize);
dest.writeString(mContentId);
dest.writeString(mContentUri);
dest.writeString(mCachedFile);
dest.writeString(mCachedFileUri);
dest.writeLong(mMessageKey);
dest.writeString(mLocation);
dest.writeString(mEncoding);
@ -1479,7 +1481,7 @@ public abstract class EmailContent {
mSize = in.readLong();
mContentId = in.readString();
mContentUri = in.readString();
mCachedFile = in.readString();
mCachedFileUri = in.readString();
mMessageKey = in.readLong();
mLocation = in.readString();
mEncoding = in.readString();
@ -1514,7 +1516,7 @@ public abstract class EmailContent {
@Override
public String toString() {
return "[" + mFileName + ", " + mMimeType + ", " + mSize + ", " + mContentId + ", "
+ mContentUri + ", " + mCachedFile + ", " + mMessageKey + ", "
+ mContentUri + ", " + mCachedFileUri + ", " + mMessageKey + ", "
+ mLocation + ", " + mEncoding + ", " + mFlags + ", " + mContentBytes + ", "
+ mAccountKey + "," + mUiState + "," + mUiDestination + ","
+ mUiDownloadedSize + "]";

View File

@ -53,6 +53,7 @@ import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.ProviderUnavailableException;
import com.android.mail.utils.LogUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -745,11 +746,13 @@ public class Utility {
} else if (attachment.mContentBytes != null) {
return true;
} else {
final String cachedFile = attachment.getCachedFilePath();
final String cachedFile = attachment.getCachedFileUri();
// Try the cached file first
if (!TextUtils.isEmpty(cachedFile)) {
final Uri cachedFileUri = Uri.parse(cachedFile);
try {
final InputStream inStream = new FileInputStream(cachedFile);
final InputStream inStream =
context.getContentResolver().openInputStream(cachedFileUri);
try {
inStream.close();
} catch (IOException e) {
@ -758,6 +761,7 @@ public class Utility {
return true;
} catch (FileNotFoundException e) {
// We weren't able to open the file, try the content uri below
LogUtils.e(Logging.LOG_TAG, e, "not able to open cached file");
}
}
final String contentUri = attachment.getContentUri();

View File

@ -37,8 +37,10 @@ import android.database.MergeCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.provider.BaseColumns;
import android.text.TextUtils;
@ -101,6 +103,7 @@ import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@ -199,6 +202,7 @@ public class EmailProvider extends ContentProvider {
private static final int ATTACHMENT = ATTACHMENT_BASE;
private static final int ATTACHMENT_ID = ATTACHMENT_BASE + 1;
private static final int ATTACHMENTS_MESSAGE_ID = ATTACHMENT_BASE + 2;
private static final int ATTACHMENTS_CACHED_FILE_ACCESS = ATTACHMENT_BASE + 3;
private static final int HOSTAUTH_BASE = 0x4000;
private static final int HOSTAUTH = HOSTAUTH_BASE;
@ -1095,6 +1099,8 @@ public class EmailProvider extends ContentProvider {
// The attachments of a specific message (query only) (insert & delete TBD)
matcher.addURI(EmailContent.AUTHORITY, "attachment/message/#",
ATTACHMENTS_MESSAGE_ID);
matcher.addURI(EmailContent.AUTHORITY, "attachment/cachedFile",
ATTACHMENTS_CACHED_FILE_ACCESS);
// All mail bodies
matcher.addURI(EmailContent.AUTHORITY, "body", BODY);
@ -1891,6 +1897,39 @@ outer:
return result;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
if (LogUtils.isLoggable(TAG, LogUtils.DEBUG)) {
LogUtils.d(TAG, "EmailProvider.openFile: %s", LogUtils.contentUriToString(TAG, uri));
}
final int match = findMatch(uri, "openFile");
switch (match) {
case ATTACHMENTS_CACHED_FILE_ACCESS:
// Parse the cache file path out from the uri
final String cachedFilePath =
uri.getQueryParameter(EmailContent.Attachment.CACHED_FILE_QUERY_PARAM);
if (cachedFilePath != null) {
// clearCallingIdentity means that the download manager will
// check our permissions rather than the permissions of whatever
// code is calling us.
long binderToken = Binder.clearCallingIdentity();
try {
LogUtils.d(TAG, "Opening attachment %s", cachedFilePath);
return ParcelFileDescriptor.open(
new File(cachedFilePath), ParcelFileDescriptor.MODE_READ_ONLY);
} finally {
Binder.restoreCallingIdentity(binderToken);
}
}
break;
}
throw new FileNotFoundException("unable to open file");
}
/**
* Returns the base notification URI for the given content type.
*
@ -3473,7 +3512,15 @@ outer:
com.android.mail.providers.Attachment uiAtt, String cachedFile) {
final Attachment att = new Attachment();
att.setContentUri(uiAtt.contentUri.toString());
att.setCachedFilePath(cachedFile);
if (!TextUtils.isEmpty(cachedFile)) {
// Generate the content provider uri for this cached file
final Uri.Builder cachedFileBuilder = Uri.parse(
"content://" + EmailContent.AUTHORITY + "/attachment/cachedFile").buildUpon();
cachedFileBuilder.appendQueryParameter(Attachment.CACHED_FILE_QUERY_PARAM, cachedFile);
att.setCachedFileUri(cachedFileBuilder.build().toString());
}
att.mFileName = uiAtt.getName();
att.mMimeType = uiAtt.getContentType();
att.mSize = uiAtt.size;