17b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira/** 27b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Copyright (c) 2011, Google Inc. 37b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 47b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 57b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * you may not use this file except in compliance with the License. 67b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * You may obtain a copy of the License at 77b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 87b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 97b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 107b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Unless required by applicable law or agreed to in writing, software 117b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 127b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * See the License for the specific language governing permissions and 147b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * limitations under the License. 157b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira */ 16bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 1730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.providers; 187b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 197434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport android.content.ContentResolver; 207434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport android.content.ContentValues; 217434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport android.content.Context; 2288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.database.Cursor; 2388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.net.Uri; 247aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcel; 257aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcelable; 26f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereiraimport android.text.TextUtils; 27f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 287434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.android.emailcommon.internet.MimeUtility; 297434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.android.emailcommon.mail.MessagingException; 307434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.android.emailcommon.mail.Part; 31bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Weiimport com.android.mail.browse.MessageAttachmentBar; 3288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentColumns; 3388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentDestination; 34479505d71969e26b0785d8e0e1b81108731cf827Mark Weiimport com.android.mail.providers.UIProvider.AttachmentRendition; 3588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentState; 36beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Weiimport com.android.mail.providers.UIProvider.AttachmentType; 37b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 38f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrookimport com.android.mail.utils.LogUtils; 39856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Weiimport com.android.mail.utils.MimeType; 404f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huangimport com.android.mail.utils.Utils; 417434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.google.common.base.Objects; 427434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.google.common.collect.Lists; 435a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 447434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport org.apache.commons.io.IOUtils; 455a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONArray; 465a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONException; 475a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONObject; 487b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 497434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport java.io.FileNotFoundException; 507434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport java.io.IOException; 517434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport java.io.InputStream; 527434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport java.io.OutputStream; 535a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.Collection; 545a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.List; 554401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira 567aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereirapublic class Attachment implements Parcelable { 57479505d71969e26b0785d8e0e1b81108731cf827Mark Wei public static final int MAX_ATTACHMENT_PREVIEWS = 2; 58b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook public static final String LOG_TAG = LogTag.getLogTag(); 597df813e56ba3a8620e934bd462527a2467fcae52Mark Wei /** 607df813e56ba3a8620e934bd462527a2467fcae52Mark Wei * Workaround for b/8070022 so that appending a null partId to the end of a 617df813e56ba3a8620e934bd462527a2467fcae52Mark Wei * uri wouldn't remove the trailing backslash 627df813e56ba3a8620e934bd462527a2467fcae52Mark Wei */ 637df813e56ba3a8620e934bd462527a2467fcae52Mark Wei public static final String EMPTY_PART_ID = "empty"; 645a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 65519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon // Indicates that this is a dummy placeholder attachment. 66519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon public static final int FLAG_DUMMY_ATTACHMENT = 1<<10; 67519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon 687aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 69bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * Part id of the attachment. 70bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei */ 71bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public String partId; 72bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 73bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei /** 74479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * Attachment file name. See {@link AttachmentColumns#NAME} Use {@link #setName(String)}. 757aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 768750066b10f80e2a8080016973b3296d76d18266Mark Wei private String name; 77f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 7888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 7988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang * Attachment size in bytes. See {@link AttachmentColumns#SIZE}. 8088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 8188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int size; 82f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 837aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 84bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * The provider-generated URI for this Attachment. Must be globally unique. 85bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * For local attachments generated by the Compose UI prior to send/save, 86bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * this field will be null. 875c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 88bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * @see AttachmentColumns#URI 897aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 9088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Uri uri; 9188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 927aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 93479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * MIME type of the file. Use {@link #getContentType()} and {@link #setContentType(String)}. 945c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 955c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#CONTENT_TYPE 967aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 978750066b10f80e2a8080016973b3296d76d18266Mark Wei private String contentType; 988750066b10f80e2a8080016973b3296d76d18266Mark Wei private String inferredContentType; 9988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 10088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 101beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * Use {@link #setState(int)} 102beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * 103beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * @see AttachmentColumns#STATE 10488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 10588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int state; 10688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 10788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 1085c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#DESTINATION 10988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 11088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int destination; 11188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1127aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 1135c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#DOWNLOADED_SIZE 1147aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 11588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int downloadedSize; 11688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 11788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 1183ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei * Shareable, openable uri for this attachment 119bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * <p> 1203ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei * content:// Gmail.getAttachmentDefaultUri() if origin is SERVER_ATTACHMENT 121bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * <p> 122bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * content:// uri pointing to the content to be uploaded if origin is 123bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * LOCAL_FILE 124bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * <p> 125bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * file:// uri pointing to an EXTERNAL apk file. The package manager only 126bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * handles file:// uris not content:// uris. We do the same workaround in 127bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * {@link MessageAttachmentBar#onClick(android.view.View)} and 128bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * UiProvider#getUiAttachmentsCursorForUIAttachments(). 129bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei * 1305c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#CONTENT_URI 13188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 1321eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang public Uri contentUri; 13388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 13488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 1355c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * Might be null. 1365c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 1375c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#THUMBNAIL_URI 13888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 13988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Uri thumbnailUri; 14088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 14188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 1425c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * Might be null. 1435c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 144bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * @see AttachmentColumns#PREVIEW_INTENT_URI 14588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 146d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook public Uri previewIntentUri; 14788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1487aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 149beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * The visibility type of this attachment. 150beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * 151beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei * @see AttachmentColumns#TYPE 152beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei */ 153beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei public int type; 154beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei 155519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon public int flags; 156519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon 157beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei /** 158bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * Might be null. JSON string. 159bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * 160bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * @see AttachmentColumns#PROVIDER_DATA 1617aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 162bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public String providerData; 1637b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 1644f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang private transient Uri mIdentifierUri; 1654f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang 1667434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein /** 1677434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * True if this attachment can be downloaded again. 1687434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein */ 1697434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein private boolean supportsDownloadAgain; 1707434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 171519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon 172bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public Attachment() { 173bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 174bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 1757aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public Attachment(Parcel in) { 1767aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira name = in.readString(); 17788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang size = in.readInt(); 17888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang uri = in.readParcelable(null); 1791eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentType = in.readString(); 18088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang state = in.readInt(); 18188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang destination = in.readInt(); 18288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang downloadedSize = in.readInt(); 1831eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentUri = in.readParcelable(null); 18488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang thumbnailUri = in.readParcelable(null); 185d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook previewIntentUri = in.readParcelable(null); 186bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei providerData = in.readString(); 1877434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein supportsDownloadAgain = in.readInt() == 1; 188beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei type = in.readInt(); 189519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon flags = in.readInt(); 1907aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 1917b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 19288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Attachment(Cursor cursor) { 19388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang if (cursor == null) { 19488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return; 19588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 19688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1974c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein name = cursor.getString(cursor.getColumnIndex(AttachmentColumns.NAME)); 1984c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein size = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.SIZE)); 1994c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein uri = Uri.parse(cursor.getString(cursor.getColumnIndex(AttachmentColumns.URI))); 2004c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein contentType = cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_TYPE)); 2014c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein state = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.STATE)); 2024c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein destination = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DESTINATION)); 2034c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein downloadedSize = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DOWNLOADED_SIZE)); 2044c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein contentUri = parseOptionalUri( 2054c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_URI))); 20688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang thumbnailUri = parseOptionalUri( 2074c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein cursor.getString(cursor.getColumnIndex(AttachmentColumns.THUMBNAIL_URI))); 208d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook previewIntentUri = parseOptionalUri( 209d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook cursor.getString(cursor.getColumnIndex(AttachmentColumns.PREVIEW_INTENT_URI))); 210bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei providerData = cursor.getString(cursor.getColumnIndex(AttachmentColumns.PROVIDER_DATA)); 2117434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein supportsDownloadAgain = cursor.getInt( 2127434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein cursor.getColumnIndex(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN)) == 1; 213beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei type = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.TYPE)); 214519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon flags = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.FLAGS)); 215bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 21688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 217bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public Attachment(JSONObject srcJson) { 218bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei name = srcJson.optString(AttachmentColumns.NAME, null); 219bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei size = srcJson.optInt(AttachmentColumns.SIZE); 220bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei uri = parseOptionalUri(srcJson, AttachmentColumns.URI); 221bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei contentType = srcJson.optString(AttachmentColumns.CONTENT_TYPE, null); 222bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei state = srcJson.optInt(AttachmentColumns.STATE); 2233ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei destination = srcJson.optInt(AttachmentColumns.DESTINATION); 2243ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei downloadedSize = srcJson.optInt(AttachmentColumns.DOWNLOADED_SIZE); 2253ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei contentUri = parseOptionalUri(srcJson, AttachmentColumns.CONTENT_URI); 2263ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei thumbnailUri = parseOptionalUri(srcJson, AttachmentColumns.THUMBNAIL_URI); 2273ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei previewIntentUri = parseOptionalUri(srcJson, AttachmentColumns.PREVIEW_INTENT_URI); 228bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei providerData = srcJson.optString(AttachmentColumns.PROVIDER_DATA); 2297434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein supportsDownloadAgain = srcJson.optBoolean(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN, true); 230beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei type = srcJson.optInt(AttachmentColumns.TYPE); 231519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon flags = srcJson.optInt(AttachmentColumns.FLAGS); 2327434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 2337434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 2347434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein /** 2357434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * Constructor for use when creating attachments in eml files. 2367434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein */ 2377434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein public Attachment(Context context, Part part, Uri emlFileUri, String messageId, String partId) { 2387434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein try { 2397434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein // Transfer fields from mime format to provider format 2407434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType()); 2417434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein name = MimeUtility.getHeaderParameter(contentTypeHeader, "name"); 2427434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein if (name == null) { 2437434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final String contentDisposition = 2447434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein MimeUtility.unfoldAndDecode(part.getDisposition()); 2457434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein name = MimeUtility.getHeaderParameter(contentDisposition, "filename"); 2467434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 2477434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 2487434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein contentType = MimeType.inferMimeType(name, part.getMimeType()); 2497434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein uri = EmlAttachmentProvider.getAttachmentUri(emlFileUri, messageId, partId); 2507434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein contentUri = uri; 2517434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein thumbnailUri = uri; 2527434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein previewIntentUri = null; 2537434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein state = AttachmentState.SAVED; 2547434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein providerData = null; 2557434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein supportsDownloadAgain = false; 2567434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein destination = AttachmentDestination.CACHE; 257beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei type = AttachmentType.STANDARD; 258519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon flags = 0; 2597434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 2607434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein // insert attachment into content provider so that we can open the file 2617434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final ContentResolver resolver = context.getContentResolver(); 2627434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein resolver.insert(uri, toContentValues()); 2637434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 2647434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein // save the file in the cache 2657434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein try { 2667434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final InputStream in = part.getBody().getInputStream(); 2677434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final OutputStream out = resolver.openOutputStream(uri, "rwt"); 2687434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein size = IOUtils.copy(in, out); 2697434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein downloadedSize = size; 2707434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein in.close(); 2717434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein out.close(); 2727434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } catch (FileNotFoundException e) { 2737434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein LogUtils.e(LOG_TAG, e, "Error in writing attachment to cache"); 2747434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } catch (IOException e) { 2757434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein LogUtils.e(LOG_TAG, e, "Error in writing attachment to cache"); 2767434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 2777434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein // perform a second insert to put the updated size and downloaded size values in 2787434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein resolver.insert(uri, toContentValues()); 2797434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } catch (MessagingException e) { 2807434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein LogUtils.e(LOG_TAG, e, "Error parsing eml attachment"); 2817434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 2827434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 2837434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 2847434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein /** 2857434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * Create an attachment from a {@link ContentValues} object. 2867434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * The keys should be {@link AttachmentColumns}. 2877434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein */ 2887434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein public Attachment(ContentValues values) { 2897434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein name = values.getAsString(AttachmentColumns.NAME); 2907434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein size = values.getAsInteger(AttachmentColumns.SIZE); 2917434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein uri = parseOptionalUri(values.getAsString(AttachmentColumns.URI)); 2927434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein contentType = values.getAsString(AttachmentColumns.CONTENT_TYPE); 2937434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein state = values.getAsInteger(AttachmentColumns.STATE); 2947434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein destination = values.getAsInteger(AttachmentColumns.DESTINATION); 2957434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein downloadedSize = values.getAsInteger(AttachmentColumns.DOWNLOADED_SIZE); 2967434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein contentUri = parseOptionalUri(values.getAsString(AttachmentColumns.CONTENT_URI)); 2977434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein thumbnailUri = parseOptionalUri(values.getAsString(AttachmentColumns.THUMBNAIL_URI)); 2987434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein previewIntentUri = 2997434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein parseOptionalUri(values.getAsString(AttachmentColumns.PREVIEW_INTENT_URI)); 3007434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein providerData = values.getAsString(AttachmentColumns.PROVIDER_DATA); 3017434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein supportsDownloadAgain = values.getAsBoolean(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN); 302beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei type = values.getAsInteger(AttachmentColumns.TYPE); 303519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon flags = values.getAsInteger(AttachmentColumns.FLAGS); 3047434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 3057434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 3067434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein /** 3077434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * Returns the various attachment fields in a {@link ContentValues} object. 3087434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein * The keys for each field should be {@link AttachmentColumns}. 3097434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein */ 3107434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein public ContentValues toContentValues() { 3117434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein final ContentValues values = new ContentValues(12); 3127434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 3137434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.NAME, name); 3147434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.SIZE, size); 3157434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.URI, uri.toString()); 3167434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.CONTENT_TYPE, contentType); 3177434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.STATE, state); 3187434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.DESTINATION, destination); 3197434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.DOWNLOADED_SIZE, downloadedSize); 3207434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.CONTENT_URI, contentUri.toString()); 3217434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.THUMBNAIL_URI, thumbnailUri.toString()); 3227434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.PREVIEW_INTENT_URI, 3237434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein previewIntentUri == null ? null : previewIntentUri.toString()); 3247434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.PROVIDER_DATA, providerData); 3257434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein values.put(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN, supportsDownloadAgain); 326beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei values.put(AttachmentColumns.TYPE, type); 327519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon values.put(AttachmentColumns.FLAGS, flags); 3287434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 3297434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein return values; 33088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 33188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 332bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei @Override 333bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public void writeToParcel(Parcel dest, int flags) { 334bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeString(name); 335bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeInt(size); 336bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeParcelable(uri, flags); 337bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeString(contentType); 338bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeInt(state); 339bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeInt(destination); 340bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeInt(downloadedSize); 341bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeParcelable(contentUri, flags); 342bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeParcelable(thumbnailUri, flags); 343bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeParcelable(previewIntentUri, flags); 344bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei dest.writeString(providerData); 3457434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein dest.writeInt(supportsDownloadAgain ? 1 : 0); 346beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei dest.writeInt(type); 347519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon dest.writeInt(flags); 348f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 349f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 350bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public JSONObject toJSON() throws JSONException { 351bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei final JSONObject result = new JSONObject(); 352bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 3538117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.NAME, name); 3548117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.SIZE, size); 3558117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.URI, stringify(uri)); 3568117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.CONTENT_TYPE, contentType); 3578117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.STATE, state); 3588117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.DESTINATION, destination); 3598117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.DOWNLOADED_SIZE, downloadedSize); 3608117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.CONTENT_URI, stringify(contentUri)); 3618117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.THUMBNAIL_URI, stringify(thumbnailUri)); 3628117871e95e8b5657e1588c8012d3edfc0204121Mark Wei result.put(AttachmentColumns.PREVIEW_INTENT_URI, stringify(previewIntentUri)); 363bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei result.put(AttachmentColumns.PROVIDER_DATA, providerData); 3647434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein result.put(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN, supportsDownloadAgain); 365beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result.put(AttachmentColumns.TYPE, type); 366519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon result.put(AttachmentColumns.FLAGS, flags); 367bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 368bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return result; 369bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 370bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 371f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook @Override 372f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook public String toString() { 373f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook try { 374b0f4a7da15313c9f1316ab72230bb44cc218ffd5Paul Westbrook final JSONObject jsonObject = toJSON(); 375b0f4a7da15313c9f1316ab72230bb44cc218ffd5Paul Westbrook // Add some additional fields that are helpful when debugging issues 3763ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei jsonObject.put("partId", partId); 3771e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook if (providerData != null) { 3781e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook try { 3791e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook // pretty print the provider data 3801e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook jsonObject.put(AttachmentColumns.PROVIDER_DATA, new JSONObject(providerData)); 3811e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook } catch (JSONException e) { 3821e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook LogUtils.e(LOG_TAG, e, "JSONException when adding provider data"); 3831e46bacc28f8cad65377559c1dfc089443498e8dPaul Westbrook } 3848117871e95e8b5657e1588c8012d3edfc0204121Mark Wei } 3858117871e95e8b5657e1588c8012d3edfc0204121Mark Wei return jsonObject.toString(4); 386f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook } catch (JSONException e) { 387f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook LogUtils.e(LOG_TAG, e, "JSONException in toString"); 388f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook return super.toString(); 389f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook } 390f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook } 391f467d10bb05a8df6ac3c8279f6fda24e89b87482Paul Westbrook 3923b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy private static String stringify(Object object) { 393bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return object != null ? object.toString() : null; 394bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 395bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 396bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei protected static Uri parseOptionalUri(String uriString) { 39788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return uriString == null ? null : Uri.parse(uriString); 39888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 39988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 400bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei protected static Uri parseOptionalUri(JSONObject srcJson, String key) { 401bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei final String uriStr = srcJson.optString(key, null); 402bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return uriStr == null ? null : Uri.parse(uriStr); 403bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 404bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 4057aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira @Override 4067aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public int describeContents() { 4077aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira return 0; 4087aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 4097b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 410bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public boolean isPresentLocally() { 411bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return state == AttachmentState.SAVED; 4127aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 4137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 414bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public boolean canSave() { 415c30808f28ba0a85ed8495a5e840e137306d2a0f0Mark Wei return !isSavedToExternal() && !isInstallable() && !MimeType.isBlocked(getContentType()); 416bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 417f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 418bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public boolean canShare() { 419bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return isPresentLocally() && contentUri != null; 42088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 421f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 42288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isDownloading() { 4237bed4bc31a49a2297a38eb9d7b595fba1fa1f849Mark Wei return state == AttachmentState.DOWNLOADING || state == AttachmentState.PAUSED; 424f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 425f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 42688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isSavedToExternal() { 42788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return state == AttachmentState.SAVED && destination == AttachmentDestination.EXTERNAL; 428f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 4294401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira 430856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei public boolean isInstallable() { 4318750066b10f80e2a8080016973b3296d76d18266Mark Wei return MimeType.isInstallable(getContentType()); 432856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei } 433856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei 4344cb51dbce9635f4bf68a6de88f759e2f86d20325Andrew Sapperstein public boolean shouldShowProgress() { 4357bed4bc31a49a2297a38eb9d7b595fba1fa1f849Mark Wei return (state == AttachmentState.DOWNLOADING || state == AttachmentState.PAUSED) 4360eb46cb4c18b91ee272caca7f62f4a15ec2668efMark Wei && size > 0 && downloadedSize > 0 && downloadedSize <= size; 437d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang } 438d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang 439bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public boolean isDownloadFailed() { 44014977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein return state == AttachmentState.FAILED; 44114977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein } 44214977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein 443bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public boolean isDownloadFinishedOrFailed() { 444bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return state == AttachmentState.FAILED || state == AttachmentState.SAVED; 445bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 446bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 4477434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein public boolean supportsDownloadAgain() { 4487434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein return supportsDownloadAgain; 4497434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein } 4507434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein 451d6318e56adadeff4106e9696b5330239175487b1Andrew Sapperstein public boolean canPreview() { 452d6318e56adadeff4106e9696b5330239175487b1Andrew Sapperstein return previewIntentUri != null; 453d6318e56adadeff4106e9696b5330239175487b1Andrew Sapperstein } 454d6318e56adadeff4106e9696b5330239175487b1Andrew Sapperstein 4554f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang /** 456bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * Returns a stable identifier URI for this attachment. TODO: make the uri 457bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * field stable, and put provider-specific opaque bits and bobs elsewhere 4584f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang */ 4594f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang public Uri getIdentifierUri() { 46010f8c4f1ca3619e761d4d1f874891f6d9259ac7bMark Wei if (Utils.isEmpty(mIdentifierUri)) { 4613ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei mIdentifierUri = Utils.isEmpty(uri) ? 4623ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei (Utils.isEmpty(contentUri) ? Uri.EMPTY : contentUri) 4633ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei : uri.buildUpon().clearQuery().build(); 4644f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang } 4654f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang return mIdentifierUri; 4664f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang } 4674f24bb48ab2c3e8fbda2af1e1d8fda79e8a458e7Andy Huang 4688750066b10f80e2a8080016973b3296d76d18266Mark Wei public String getContentType() { 4698750066b10f80e2a8080016973b3296d76d18266Mark Wei if (TextUtils.isEmpty(inferredContentType)) { 4708750066b10f80e2a8080016973b3296d76d18266Mark Wei inferredContentType = MimeType.inferMimeType(name, contentType); 4718750066b10f80e2a8080016973b3296d76d18266Mark Wei } 4728750066b10f80e2a8080016973b3296d76d18266Mark Wei return inferredContentType; 4738750066b10f80e2a8080016973b3296d76d18266Mark Wei } 47474db99555be46ccf44691805c359839268326d2eAndy Huang 47574db99555be46ccf44691805c359839268326d2eAndy Huang public Uri getUriForRendition(int rendition) { 47674db99555be46ccf44691805c359839268326d2eAndy Huang final Uri uri; 47774db99555be46ccf44691805c359839268326d2eAndy Huang switch (rendition) { 47874db99555be46ccf44691805c359839268326d2eAndy Huang case AttachmentRendition.BEST: 47974db99555be46ccf44691805c359839268326d2eAndy Huang uri = contentUri; 48074db99555be46ccf44691805c359839268326d2eAndy Huang break; 48174db99555be46ccf44691805c359839268326d2eAndy Huang case AttachmentRendition.SIMPLE: 48274db99555be46ccf44691805c359839268326d2eAndy Huang uri = thumbnailUri; 48374db99555be46ccf44691805c359839268326d2eAndy Huang break; 48474db99555be46ccf44691805c359839268326d2eAndy Huang default: 48574db99555be46ccf44691805c359839268326d2eAndy Huang throw new IllegalArgumentException("invalid rendition: " + rendition); 48674db99555be46ccf44691805c359839268326d2eAndy Huang } 48774db99555be46ccf44691805c359839268326d2eAndy Huang return uri; 48874db99555be46ccf44691805c359839268326d2eAndy Huang } 4898750066b10f80e2a8080016973b3296d76d18266Mark Wei 4908750066b10f80e2a8080016973b3296d76d18266Mark Wei public void setContentType(String contentType) { 4918750066b10f80e2a8080016973b3296d76d18266Mark Wei if (!TextUtils.equals(this.contentType, contentType)) { 4928750066b10f80e2a8080016973b3296d76d18266Mark Wei this.inferredContentType = null; 4938750066b10f80e2a8080016973b3296d76d18266Mark Wei this.contentType = contentType; 4948750066b10f80e2a8080016973b3296d76d18266Mark Wei } 4958750066b10f80e2a8080016973b3296d76d18266Mark Wei } 4968750066b10f80e2a8080016973b3296d76d18266Mark Wei 4978750066b10f80e2a8080016973b3296d76d18266Mark Wei public String getName() { 4988750066b10f80e2a8080016973b3296d76d18266Mark Wei return name; 4998750066b10f80e2a8080016973b3296d76d18266Mark Wei } 5008750066b10f80e2a8080016973b3296d76d18266Mark Wei 5018750066b10f80e2a8080016973b3296d76d18266Mark Wei public boolean setName(String name) { 5028750066b10f80e2a8080016973b3296d76d18266Mark Wei if (!TextUtils.equals(this.name, name)) { 5038750066b10f80e2a8080016973b3296d76d18266Mark Wei this.inferredContentType = null; 5048750066b10f80e2a8080016973b3296d76d18266Mark Wei this.name = name; 5058750066b10f80e2a8080016973b3296d76d18266Mark Wei return true; 5068750066b10f80e2a8080016973b3296d76d18266Mark Wei } 5078750066b10f80e2a8080016973b3296d76d18266Mark Wei return false; 5088750066b10f80e2a8080016973b3296d76d18266Mark Wei } 5098750066b10f80e2a8080016973b3296d76d18266Mark Wei 510bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei /** 511bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei * Sets the attachment state. Side effect: sets downloadedSize 512bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei */ 513bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public void setState(int state) { 514bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei this.state = state; 515bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei if (state == AttachmentState.FAILED || state == AttachmentState.NOT_SAVED) { 516bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei this.downloadedSize = 0; 5178081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook } 5185a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 5195a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 520bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei @Override 521beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei public boolean equals(final Object o) { 522beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (this == o) { 523bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return true; 5248081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook } 525beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (o == null || getClass() != o.getClass()) { 526beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 527beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 528bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 529beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei final Attachment that = (Attachment) o; 530beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei 531beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (destination != that.destination) { 532beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 533beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 534beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (downloadedSize != that.downloadedSize) { 535beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 536beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 537beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (size != that.size) { 538beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 539beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 540beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (state != that.state) { 541beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 542beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 543beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (supportsDownloadAgain != that.supportsDownloadAgain) { 544beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 545beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 546beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (type != that.type) { 547beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 548beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 549beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (contentType != null ? !contentType.equals(that.contentType) 550beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei : that.contentType != null) { 551beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 552beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 553beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (contentUri != null ? !contentUri.equals(that.contentUri) : that.contentUri != null) { 554beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 555beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 556beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (name != null ? !name.equals(that.name) : that.name != null) { 557beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 558beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 559beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (partId != null ? !partId.equals(that.partId) : that.partId != null) { 560beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 561beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 562beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (previewIntentUri != null ? !previewIntentUri.equals(that.previewIntentUri) 563beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei : that.previewIntentUri != null) { 564beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 565beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 566beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (providerData != null ? !providerData.equals(that.providerData) 567beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei : that.providerData != null) { 568beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 569beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 570beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (thumbnailUri != null ? !thumbnailUri.equals(that.thumbnailUri) 571beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei : that.thumbnailUri != null) { 572beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return false; 573beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei } 574beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei if (uri != null ? !uri.equals(that.uri) : that.uri != null) { 575bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return false; 576bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 577bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 578beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return true; 5795a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 5805a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 581bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei @Override 582bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public int hashCode() { 583beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei int result = partId != null ? partId.hashCode() : 0; 584beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (name != null ? name.hashCode() : 0); 585beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + size; 586beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (uri != null ? uri.hashCode() : 0); 587beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (contentType != null ? contentType.hashCode() : 0); 588beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + state; 589beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + destination; 590beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + downloadedSize; 591beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (contentUri != null ? contentUri.hashCode() : 0); 592beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (thumbnailUri != null ? thumbnailUri.hashCode() : 0); 593beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (previewIntentUri != null ? previewIntentUri.hashCode() : 0); 594beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + type; 595beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (providerData != null ? providerData.hashCode() : 0); 596beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei result = 31 * result + (supportsDownloadAgain ? 1 : 0); 597beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei return result; 5985a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 5995a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 600bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public static String toJSONArray(Collection<? extends Attachment> attachments) { 601bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei if (attachments == null) { 602bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return null; 603bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 6045a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final JSONArray result = new JSONArray(); 6055a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang try { 6065a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang for (Attachment attachment : attachments) { 6075a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.put(attachment.toJSON()); 6085a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 6095a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } catch (JSONException e) { 6105a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang throw new IllegalArgumentException(e); 6115a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 6125a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return result.toString(); 6135a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 6145a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 6155a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang public static List<Attachment> fromJSONArray(String jsonArrayStr) { 6165a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final List<Attachment> results = Lists.newArrayList(); 617bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei if (jsonArrayStr != null) { 618bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei try { 619bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei final JSONArray arr = new JSONArray(jsonArrayStr); 6205a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 621bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei for (int i = 0; i < arr.length(); i++) { 622bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei results.add(new Attachment(arr.getJSONObject(i))); 623bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 6245a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 625bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } catch (JSONException e) { 626bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei throw new IllegalArgumentException(e); 627bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 6285a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 6295a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return results; 6305a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 631bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 6323ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei private static final String SERVER_ATTACHMENT = "SERVER_ATTACHMENT"; 6333ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei private static final String LOCAL_FILE = "LOCAL_FILE"; 6343ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei 6353ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei public String toJoinedString() { 636479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return TextUtils.join(UIProvider.ATTACHMENT_INFO_DELIMITER, Lists.newArrayList( 6373ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei partId == null ? "" : partId, 638479505d71969e26b0785d8e0e1b81108731cf827Mark Wei name == null ? "" 639beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei : name.replaceAll("[" + UIProvider.ATTACHMENT_INFO_DELIMITER 640beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei + UIProvider.ATTACHMENT_INFO_SEPARATOR + "]", ""), 6418750066b10f80e2a8080016973b3296d76d18266Mark Wei getContentType(), 6423ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei String.valueOf(size), 6438750066b10f80e2a8080016973b3296d76d18266Mark Wei getContentType(), 6443ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei contentUri != null ? SERVER_ATTACHMENT : LOCAL_FILE, 645beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei contentUri != null ? contentUri.toString() : "", 646beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei "" /* cachedFileUri */, 647beaf1e4d14f89e7735ba94a0b2ff92233c6f928fMark Wei String.valueOf(type))); 6483ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei } 6493ca3bf8538bbabcaf9d86818e25c40f3a9d9b0c9Mark Wei 650479505d71969e26b0785d8e0e1b81108731cf827Mark Wei /** 651479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * For use with {@link UIProvider.ConversationColumns#ATTACHMENT_PREVIEW_STATES}. 652479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * 653479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param previewStates The packed int describing the states of multiple attachments. 654479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param attachmentIndex The index of the attachment to update. 655479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param rendition The rendition of that attachment to update. 656479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param downloaded Whether that specific rendition is downloaded. 657479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @return A packed int describing the updated downloaded states of the multiple attachments. 658479505d71969e26b0785d8e0e1b81108731cf827Mark Wei */ 659479505d71969e26b0785d8e0e1b81108731cf827Mark Wei public static int updatePreviewStates(int previewStates, int attachmentIndex, int rendition, 660479505d71969e26b0785d8e0e1b81108731cf827Mark Wei boolean downloaded) { 661479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // find the bit that describes that specific attachment index and rendition 662479505d71969e26b0785d8e0e1b81108731cf827Mark Wei int shift = attachmentIndex * 2 + rendition; 663479505d71969e26b0785d8e0e1b81108731cf827Mark Wei int mask = 1 << shift; 664479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // update the packed int at that bit 665479505d71969e26b0785d8e0e1b81108731cf827Mark Wei if (downloaded) { 666479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // turns that bit into a 1 667479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return previewStates | mask; 668479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } else { 669479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // turns that bit into a 0 670479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return previewStates & ~mask; 671479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 672479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 673479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 674479505d71969e26b0785d8e0e1b81108731cf827Mark Wei /** 675479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * For use with {@link UIProvider.ConversationColumns#ATTACHMENT_PREVIEW_STATES}. 676479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * 677479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param previewStates The packed int describing the states of multiple attachments. 678479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param attachmentIndex The index of the attachment. 679479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @param rendition The rendition of the attachment. 680479505d71969e26b0785d8e0e1b81108731cf827Mark Wei * @return The downloaded state of that particular rendition of that particular attachment. 681479505d71969e26b0785d8e0e1b81108731cf827Mark Wei */ 682479505d71969e26b0785d8e0e1b81108731cf827Mark Wei public static boolean getPreviewState(int previewStates, int attachmentIndex, int rendition) { 683479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // find the bit that describes that specific attachment index 684479505d71969e26b0785d8e0e1b81108731cf827Mark Wei int shift = attachmentIndex * 2; 685479505d71969e26b0785d8e0e1b81108731cf827Mark Wei int mask = 1 << shift; 686479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 687479505d71969e26b0785d8e0e1b81108731cf827Mark Wei if (rendition == AttachmentRendition.SIMPLE) { 688479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // implicit shift of 0 finds the SIMPLE rendition bit 689479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return (previewStates & mask) != 0; 690479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } else if (rendition == AttachmentRendition.BEST) { 691479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // shift of 1 finds the BEST rendition bit 692479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return (previewStates & (mask << 1)) != 0; 693479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } else { 694479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return false; 695479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 696479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 697479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 698bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public static final Creator<Attachment> CREATOR = new Creator<Attachment>() { 699bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei @Override 700bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public Attachment createFromParcel(Parcel source) { 701bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return new Attachment(source); 702bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 703bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 704bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei @Override 705bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei public Attachment[] newArray(int size) { 706bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei return new Attachment[size]; 707bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei } 708bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei }; 7097b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira} 710