Crash trying to save a draft with a picture from the gallery
Bug 7374081
Change the persister api's to accept a HashMap of opened inputStreams
for the parts. The inputStreams are opened on the UI thread, but the
actual persisting takes place on a non-UI thread.
Change-Id: I5b886b8d12dd06f2a9e63232f7f7560815338673
diff --git a/src/java/com/google/android/mms/pdu/PduPersister.java b/src/java/com/google/android/mms/pdu/PduPersister.java
index 162d036..61b80aa 100644
--- a/src/java/com/google/android/mms/pdu/PduPersister.java
+++ b/src/java/com/google/android/mms/pdu/PduPersister.java
@@ -697,7 +697,7 @@
return part.getContentType() == null ? null : toIsoString(part.getContentType());
}
- public Uri persistPart(PduPart part, long msgId)
+ public Uri persistPart(PduPart part, long msgId, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
Uri uri = Uri.parse("content://mms/" + msgId + "/part");
ContentValues values = new ContentValues(8);
@@ -755,7 +755,7 @@
throw new MmsException("Failed to persist part, return null.");
}
- persistData(part, res, contentType);
+ persistData(part, res, contentType, preOpenedFiles);
// After successfully store the data, we should update
// the dataUri of the part.
part.setDataUri(res);
@@ -773,11 +773,12 @@
* @param part The PDU part which contains data to be saved.
* @param uri The URI of the part.
* @param contentType The MIME type of the part.
+ * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
* @throws MmsException Cannot find source data or error occurred
* while saving the data.
*/
private void persistData(PduPart part, Uri uri,
- String contentType)
+ String contentType, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
OutputStream os = null;
InputStream is = null;
@@ -825,6 +826,8 @@
" can not be converted.");
}
}
+ // uri can look like:
+ // content://mms/part/98
os = mContentResolver.openOutputStream(uri);
if (data == null) {
dataUri = part.getDataUri();
@@ -832,7 +835,14 @@
Log.w(TAG, "Can't find data for this part.");
return;
}
- is = mContentResolver.openInputStream(dataUri);
+ // dataUri can look like:
+ // content://com.google.android.gallery3d.provider/picasa/item/5720646660183715586
+ if (preOpenedFiles != null && preOpenedFiles.containsKey(dataUri)) {
+ is = preOpenedFiles.get(dataUri);
+ }
+ if (is == null) {
+ is = mContentResolver.openInputStream(dataUri);
+ }
if (LOCAL_LOGV) {
Log.v(TAG, "Saving data to: " + uri);
@@ -1072,7 +1082,8 @@
SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
}
- private void updatePart(Uri uri, PduPart part) throws MmsException {
+ private void updatePart(Uri uri, PduPart part, HashMap<Uri, InputStream> preOpenedFiles)
+ throws MmsException {
ContentValues values = new ContentValues(7);
int charset = part.getCharset();
@@ -1121,7 +1132,7 @@
// 2. The Uri of the part is different from the current one.
if ((part.getData() != null)
|| (uri != part.getDataUri())) {
- persistData(part, uri, contentType);
+ persistData(part, uri, contentType, preOpenedFiles);
}
}
@@ -1130,9 +1141,10 @@
*
* @param uri The PDU which need to be updated.
* @param body New message body of the PDU.
+ * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
* @throws MmsException Bad URI or updating failed.
*/
- public void updateParts(Uri uri, PduBody body)
+ public void updateParts(Uri uri, PduBody body, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
try {
PduCacheEntry cacheEntry;
@@ -1191,12 +1203,12 @@
// Create new parts which didn't exist before.
for (PduPart part : toBeCreated) {
- persistPart(part, msgId);
+ persistPart(part, msgId, preOpenedFiles);
}
// Update the modified parts.
for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
- updatePart(e.getKey(), e.getValue());
+ updatePart(e.getKey(), e.getValue(), preOpenedFiles);
}
} finally {
synchronized(PDU_CACHE_INSTANCE) {
@@ -1215,10 +1227,12 @@
* @param groupMmsEnabled if true, all of the recipients addressed in the PDU will be used
* to create the associated thread. When false, only the sender will be used in finding or
* creating the appropriate thread or conversation.
+ * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
* @return A Uri which can be used to access the stored PDU.
*/
- public Uri persist(GenericPdu pdu, Uri uri, boolean createThreadId, boolean groupMmsEnabled)
+ public Uri persist(GenericPdu pdu, Uri uri, boolean createThreadId, boolean groupMmsEnabled,
+ HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
if (uri == null) {
throw new MmsException("Uri may not be null.");
@@ -1370,7 +1384,7 @@
}
for (int i = 0; i < partsNum; i++) {
PduPart part = body.getPart(i);
- persistPart(part, dummyId);
+ persistPart(part, dummyId, preOpenedFiles);
// If we've got anything besides text/plain or SMIL part, then we've got
// an mms message with some other type of attachment.