diff --git a/emailcommon/src/com/android/emailcommon/internet/Rfc822Output.java b/emailcommon/src/com/android/emailcommon/internet/Rfc822Output.java index f77659cef..1a28cef0c 100644 --- a/emailcommon/src/com/android/emailcommon/internet/Rfc822Output.java +++ b/emailcommon/src/com/android/emailcommon/internet/Rfc822Output.java @@ -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; diff --git a/emailcommon/src/com/android/emailcommon/provider/EmailContent.java b/emailcommon/src/com/android/emailcommon/provider/EmailContent.java index 6ea6fa430..d8a9a174d 100755 --- a/emailcommon/src/com/android/emailcommon/provider/EmailContent.java +++ b/emailcommon/src/com/android/emailcommon/provider/EmailContent.java @@ -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 + "]"; diff --git a/emailcommon/src/com/android/emailcommon/utility/Utility.java b/emailcommon/src/com/android/emailcommon/utility/Utility.java index 2247e883e..b17fa9a98 100644 --- a/emailcommon/src/com/android/emailcommon/utility/Utility.java +++ b/emailcommon/src/com/android/emailcommon/utility/Utility.java @@ -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(); diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 88f9f2bd0..27126021d 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -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;