1b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /* 2b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Copyright (C) 2009 The Android Open Source Project 3b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * 4b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Licensed under the Apache License, Version 2.0 (the "License"); 5b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * you may not use this file except in compliance with the License. 6b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * You may obtain a copy of the License at 7b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * 8b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * http://www.apache.org/licenses/LICENSE-2.0 9b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * 10b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Unless required by applicable law or agreed to in writing, software 11b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * distributed under the License is distributed on an "AS IS" BASIS, 12b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * See the License for the specific language governing permissions and 14b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * limitations under the License. 15b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 16b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 17b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickpackage com.android.mms.data; 18b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 19469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylorimport java.io.IOException; 20469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylorimport java.io.InputStream; 215e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylorimport java.util.ArrayList; 225e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylorimport java.util.Arrays; 23469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylorimport java.util.HashMap; 24e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylorimport java.util.Iterator; 251d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrickimport java.util.List; 26469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylorimport java.util.Set; 271d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 2872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylorimport android.app.Activity; 29b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.content.ContentResolver; 30b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.content.ContentUris; 31b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.content.ContentValues; 32b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.content.Context; 33b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.database.Cursor; 34f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.database.sqlite.SqliteWrapper; 35b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.net.Uri; 3608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylorimport android.os.AsyncTask; 37b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.os.Bundle; 38f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms; 390d4645de339b4681d18198ba7451e7b8807116f9Tom Taylorimport android.provider.Telephony.MmsSms; 40f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.MmsSms.PendingMessages; 4151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorimport android.provider.Telephony.Sms; 42cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddomimport android.telephony.SmsMessage; 43b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.text.TextUtils; 44b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickimport android.util.Log; 4508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylorimport android.util.Pair; 46b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 475e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylorimport com.android.common.contacts.DataUsageStatUpdater; 48f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.common.userhappiness.UserHappinessSignals; 49d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ContentRestrictionException; 50f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.ExceedMessageSizeException; 51f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.LogTag; 52e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylorimport com.android.mms.MmsApp; 53f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.MmsConfig; 54f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.ResolutionException; 55f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.UnsupportContentTypeException; 56f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.model.ImageModel; 57f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.model.SlideModel; 58f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.model.SlideshowModel; 59f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.model.TextModel; 60f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.transaction.MessageSender; 61f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.transaction.MmsMessageSender; 62f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.transaction.SmsMessageSender; 63f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.ui.ComposeMessageActivity; 64f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.ui.MessageUtils; 659889006f9d29d0509c1c036987ce028de43ac96eTom Taylorimport com.android.mms.ui.MessagingPreferenceActivity; 66f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.ui.SlideshowEditor; 675fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylorimport com.android.mms.util.DraftCache; 68f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.mms.util.Recycler; 69e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylorimport com.android.mms.util.ThumbnailManager; 70c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylorimport com.android.mms.widget.MmsWidgetProvider; 71f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.ContentType; 72f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.MmsException; 73f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.EncodedStringValue; 74f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduBody; 75c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylorimport com.google.android.mms.pdu.PduHeaders; 76f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduPersister; 77f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.SendReq; 78f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylor 79b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick/** 80b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Contains all state related to a message being edited by the user. 81b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 82b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrickpublic class WorkingMessage { 83b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final String TAG = "WorkingMessage"; 84b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final boolean DEBUG = false; 85b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 86feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor // Public intents 87feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor public static final String ACTION_SENDING_SMS = "android.intent.action.SENDING_SMS"; 88feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor 89feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor // Intent extras 90feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor public static final String EXTRA_SMS_MESSAGE = "android.mms.extra.MESSAGE"; 91feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor public static final String EXTRA_SMS_RECIPIENTS = "android.mms.extra.RECIPIENTS"; 92feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor public static final String EXTRA_SMS_THREAD_ID = "android.mms.extra.THREAD_ID"; 93feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor 94b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Database access stuff 9572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor private final Activity mActivity; 96b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private final ContentResolver mContentResolver; 97b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 98b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // States that can require us to save or send a message as MMS. 99b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final int RECIPIENTS_REQUIRE_MMS = (1 << 0); // 1 100b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final int HAS_SUBJECT = (1 << 1); // 2 101b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final int HAS_ATTACHMENT = (1 << 2); // 4 102b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final int LENGTH_REQUIRES_MMS = (1 << 3); // 8 103b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final int FORCE_MMS = (1 << 4); // 16 104c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor private static final int MULTIPLE_RECIPIENTS = (1 << 5); // 32 105b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 106b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // A bitmap of the above indicating different properties of the message; 107b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // any bit set will require the message to be sent via MMS. 108b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private int mMmsState; 1091d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 110b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Errors from setAttachment() 111b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int OK = 0; 112b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int UNKNOWN_ERROR = -1; 113b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int MESSAGE_SIZE_EXCEEDED = -2; 114b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int UNSUPPORTED_TYPE = -3; 115b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int IMAGE_TOO_LARGE = -4; 1161d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 117b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Attachment types 118b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int TEXT = 0; 119b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int IMAGE = 1; 120b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int VIDEO = 2; 121b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int AUDIO = 3; 122b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static final int SLIDESHOW = 4; 1231d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 124b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Current attachment type of the message; one of the above values. 125b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private int mAttachmentType; 1261d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 127ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick // Conversation this message is targeting. 128ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick private Conversation mConversation; 1291d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 130b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Text of the message. 131b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private CharSequence mText; 132b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Slideshow for this message, if applicable. If it's a simple attachment, 133b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // i.e. not SLIDESHOW, it will contain only one slide. 134b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private SlideshowModel mSlideshow; 135b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Data URI of an MMS message if we have had to save it. 136b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private Uri mMessageUri; 137b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // MMS subject line for this message 138b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private CharSequence mSubject; 1391d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 140b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Set to true if this message has been discarded. 141b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private boolean mDiscarded = false; 1421d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 143dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor // Track whether we have drafts 144dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor private volatile boolean mHasMmsDraft; 145dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor private volatile boolean mHasSmsDraft; 146dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor 1471d95d8928940553e9e99f34ad075865b9b34781cTom Taylor // Cached value of mms enabled flag 1481d95d8928940553e9e99f34ad075865b9b34781cTom Taylor private static boolean sMmsEnabled = MmsConfig.getMmsEnabled(); 1491d95d8928940553e9e99f34ad075865b9b34781cTom Taylor 150b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Our callback interface 151b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private final MessageStatusListener mStatusListener; 1521d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick private List<String> mWorkingRecipients; 153d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor 154692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor // Message sizes in Outbox 155692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor private static final String[] MMS_OUTBOX_PROJECTION = { 156692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor Mms._ID, // 0 157692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor Mms.MESSAGE_SIZE // 1 158692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor }; 159692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor 160692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor private static final int MMS_MESSAGE_SIZE_INDEX = 1; 161692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor 162b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 163b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Callback interface for communicating important state changes back to 164b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * ComposeMessageActivity. 165b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 166b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public interface MessageStatusListener { 167b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 168b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Called when the protocol for sending the message changes from SMS 169b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * to MMS, and vice versa. 1701d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * 171b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @param mms If true, it changed to MMS. If false, to SMS. 172b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 173b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick void onProtocolChanged(boolean mms); 1741d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 175b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 176b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Called when an attachment on the message has changed. 177b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 178b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick void onAttachmentChanged(); 1791d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 180b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 181c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor * Called just before the process of sending a message. 182c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor */ 183c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor void onPreMessageSent(); 184c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor 185c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor /** 186b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Called once the process of sending a message, triggered by 187b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * {@link send} has completed. This doesn't mean the send succeeded, 188b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * just that it has been dispatched to the network. 189b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 190ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick void onMessageSent(); 191c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor 192c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor /** 193c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor * Called if there are too many unsent messages in the queue and we're not allowing 194c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor * any more Mms's to be sent. 195c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor */ 196c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor void onMaxPendingMessagesReached(); 19710eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor 19810eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor /** 19910eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor * Called if there's an attachment error while resizing the images just before sending. 20010eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor */ 20110eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor void onAttachmentError(int error); 202b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2031d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 204b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private WorkingMessage(ComposeMessageActivity activity) { 20572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor mActivity = activity; 20672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor mContentResolver = mActivity.getContentResolver(); 207b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mStatusListener = activity; 208b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = TEXT; 209b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mText = ""; 210b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 211b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 212b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 213b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Creates a new working message. 214b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 215b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static WorkingMessage createEmpty(ComposeMessageActivity activity) { 216b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Make a new empty working message. 217b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick WorkingMessage msg = new WorkingMessage(activity); 218b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return msg; 219b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 220b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 221b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 222b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Create a new WorkingMessage from the specified data URI, which typically 223b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * contains an MMS message. 224b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 225b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public static WorkingMessage load(ComposeMessageActivity activity, Uri uri) { 226b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If the message is not already in the draft box, move it there. 227b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (!uri.toString().startsWith(Mms.Draft.CONTENT_URI.toString())) { 228b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick PduPersister persister = PduPersister.getPduPersister(activity); 229d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 230d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.debug("load: moving %s to drafts", uri); 231d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 232b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 233b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick uri = persister.move(uri, Mms.Draft.CONTENT_URI); 234b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } catch (MmsException e) { 235d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.error("Can't move %s to drafts", uri); 236b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return null; 237b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 238b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2391d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 240b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick WorkingMessage msg = new WorkingMessage(activity); 241b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (msg.loadFromUri(uri)) { 2424cab16e396f9f5381e14121011d55a7c12e3c317Tom Taylor msg.mHasMmsDraft = true; 243b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return msg; 244b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2451d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 246b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return null; 247b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2481d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 2493d00f75be4178a8b9e9ce099221e2e256bcab850Tom Taylor private void correctAttachmentState(boolean showToast) { 2503882a23e3ac0a8ef39853e16b79e8ec17c4bb3dbFicus Kirkpatrick int slideCount = mSlideshow.size(); 2511d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 2523882a23e3ac0a8ef39853e16b79e8ec17c4bb3dbFicus Kirkpatrick // If we get an empty slideshow, tear down all MMS 2533882a23e3ac0a8ef39853e16b79e8ec17c4bb3dbFicus Kirkpatrick // state and discard the unnecessary message Uri. 2543882a23e3ac0a8ef39853e16b79e8ec17c4bb3dbFicus Kirkpatrick if (slideCount == 0) { 255c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor removeAttachment(false); 2563882a23e3ac0a8ef39853e16b79e8ec17c4bb3dbFicus Kirkpatrick } else if (slideCount > 1) { 257b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = SLIDESHOW; 258b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else { 259b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SlideModel slide = mSlideshow.get(0); 260b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (slide.hasImage()) { 261b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = IMAGE; 262b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else if (slide.hasVideo()) { 263b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = VIDEO; 264b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else if (slide.hasAudio()) { 265b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = AUDIO; 266b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 267b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2681d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 2693d00f75be4178a8b9e9ce099221e2e256bcab850Tom Taylor updateState(HAS_ATTACHMENT, hasAttachment(), showToast); 270b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 271b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 272b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private boolean loadFromUri(Uri uri) { 273d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) LogTag.debug("loadFromUri %s", uri); 274b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 27572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor mSlideshow = SlideshowModel.createFromMessageUri(mActivity, uri); 276b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } catch (MmsException e) { 277d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.error("Couldn't load URI %s", uri); 278b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return false; 279b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 280b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 281b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mMessageUri = uri; 282b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 283b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Make sure all our state is as expected. 284b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick syncTextFromSlideshow(); 2853d00f75be4178a8b9e9ce099221e2e256bcab850Tom Taylor correctAttachmentState(false); 286b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 287b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return true; 288b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 2891d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 290b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 291ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick * Load the draft message for the specified conversation, or a new empty message if 292b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * none exists. 293b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 294ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick public static WorkingMessage loadDraft(ComposeMessageActivity activity, 29508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor final Conversation conv, 29608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor final Runnable onDraftLoaded) { 29708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) LogTag.debug("loadDraft %s", conv); 29808712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor 29908712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor final WorkingMessage msg = createEmpty(activity); 30008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (conv.getThreadId() <= 0) { 30108712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (onDraftLoaded != null) { 30208712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor onDraftLoaded.run(); 30308712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 304b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return msg; 305ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick } 3061d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 30708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor new AsyncTask<Void, Void, Pair<String, String>>() { 30808712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor 30908712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // Return a Pair where: 31008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // first - non-empty String representing the text of an SMS draft 31108712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // second - non-null String representing the text of an MMS subject 312be8c4cdb145e2919e1b5916355e5a92978e013f7Todor Kalaydjiev @Override 31308712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor protected Pair<String, String> doInBackground(Void... none) { 31408712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // Look for an SMS draft first. 31508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor String draftText = msg.readDraftSmsMessage(conv); 31608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor String subject = null; 31708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor 31808712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (TextUtils.isEmpty(draftText)) { 31908712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // No SMS draft so look for an MMS draft. 32008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor StringBuilder sb = new StringBuilder(); 32108712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor Uri uri = readDraftMmsMessage(msg.mActivity, conv, sb); 32208712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (uri != null) { 32308712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (msg.loadFromUri(uri)) { 32408712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // If there was an MMS message, readDraftMmsMessage 32508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor // will put the subject in our supplied StringBuilder. 32608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor subject = sb.toString(); 32708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 32808712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 32908712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 33008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor Pair<String, String> result = new Pair<String, String>(draftText, subject); 33108712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor return result; 33208712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 333b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 334be8c4cdb145e2919e1b5916355e5a92978e013f7Todor Kalaydjiev @Override 33508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor protected void onPostExecute(Pair<String, String> result) { 33608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (!TextUtils.isEmpty(result.first)) { 33708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor msg.mHasSmsDraft = true; 33808712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor msg.setText(result.first); 33908712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 34008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (result.second != null) { 34108712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor msg.mHasMmsDraft = true; 34208712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (!TextUtils.isEmpty(result.second)) { 34308712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor msg.setSubject(result.second, false); 34408712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 34508712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor } 34608712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor if (onDraftLoaded != null) { 34708712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor onDraftLoaded.run(); 348b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 349b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 35008712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor }.execute(); 3511d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 35208712ce9d30d4f28476436b218f2b76c7bdfb89cTom Taylor return msg; 353b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 354b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 355b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 356b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Sets the text of the message to the specified CharSequence. 357b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 358b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public void setText(CharSequence s) { 359b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mText = s; 360b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 361b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 362b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 363b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns the current message text. 364b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 365b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public CharSequence getText() { 366b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return mText; 367b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 368b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 369b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 370be8c4cdb145e2919e1b5916355e5a92978e013f7Todor Kalaydjiev * @return True if the message has any text. A message with just whitespace is not considered 371b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor * to have text. 372b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 373b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean hasText() { 374b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor return mText != null && TextUtils.getTrimmedLength(mText) > 0; 375b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 3761d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 377c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor public void removeAttachment(boolean notify) { 378e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor removeThumbnailsFromCache(mSlideshow); 379c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor mAttachmentType = TEXT; 380c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor mSlideshow = null; 381c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor if (mMessageUri != null) { 382c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor asyncDelete(mMessageUri, null, null); 383c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor mMessageUri = null; 384c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor } 385c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor // mark this message as no longer having an attachment 386c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor updateState(HAS_ATTACHMENT, false, notify); 387c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor if (notify) { 388c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor // Tell ComposeMessageActivity (or other listener) that the attachment has changed. 389c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor // In the case of ComposeMessageActivity, it will remove its attachment panel because 390c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor // this working message no longer has an attachment. 391c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor mStatusListener.onAttachmentChanged(); 392c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor } 393c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor } 394c1342c003f027f564b44b4f4f93d6a6e780aa1c7Tom Taylor 395e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor public static void removeThumbnailsFromCache(SlideshowModel slideshow) { 396e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor if (slideshow != null) { 397e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor ThumbnailManager thumbnailManager = MmsApp.getApplication().getThumbnailManager(); 398e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor boolean removedSomething = false; 399e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor Iterator<SlideModel> iterator = slideshow.iterator(); 400e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor while (iterator.hasNext()) { 401e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor SlideModel slideModel = iterator.next(); 402e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor if (slideModel.hasImage()) { 403e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor thumbnailManager.removeThumbnail(slideModel.getImage().getUri()); 404e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor removedSomething = true; 405e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } else if (slideModel.hasVideo()) { 406e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor thumbnailManager.removeThumbnail(slideModel.getVideo().getUri()); 407e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor removedSomething = true; 408e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } 409e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } 410e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor if (removedSomething) { 411e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor // HACK: the keys to the thumbnail cache are the part uris, such as mms/part/3 412e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor // Because the part table doesn't have auto-increment ids, the part ids are reused 413e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor // when a message or thread is deleted. For now, we're clearing the whole thumbnail 414e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor // cache so we don't retrieve stale images when part ids are reused. This will be 415e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor // fixed in the next release in the mms provider. 416e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor MmsApp.getApplication().getThumbnailManager().clearBackingStore(); 417e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } 418e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } 419e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor } 420e5486018e640aa2c36f68f56d19682a8fd614291Tom Taylor 421b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 422b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Adds an attachment to the message, replacing an old one if it existed. 423b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @param type Type of this attachment, such as {@link IMAGE} 424b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @param dataUri Uri containing the attachment data (or null for {@link TEXT}) 425edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor * @param append true if we should add the attachment to a new slide 426b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @return An error code such as {@link UNKNOWN_ERROR} or {@link OK} if successful 427b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 428edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor public int setAttachment(int type, Uri dataUri, boolean append) { 429d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 430d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.debug("setAttachment type=%d uri %s", type, dataUri); 431d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 432b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick int result = OK; 4339abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor SlideshowEditor slideShowEditor = new SlideshowEditor(mActivity, mSlideshow); 434b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 435b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // Special case for deleting a slideshow. When ComposeMessageActivity gets told to 436b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // remove an attachment (search for AttachmentEditor.MSG_REMOVE_ATTACHMENT), it calls 437b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // this function setAttachment with a type of TEXT and a null uri. Basically, it's turning 438b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // the working message from an MMS back to a simple SMS. The various attachment types 439b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // use slide[0] as a special case. The call to ensureSlideshow below makes sure there's 440b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // a slide zero. In the case of an already attached slideshow, ensureSlideshow will do 441b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // nothing and the slideshow will remain such that if a user adds a slideshow again, they'll 442b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor // see their old slideshow they previously deleted. Here we really delete the slideshow. 443b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor if (type == TEXT && mAttachmentType == SLIDESHOW && mSlideshow != null && dataUri == null 444b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor && !append) { 445b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor slideShowEditor.removeAllSlides(); 446b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor } 447b85cfae9dc792a11296edd3c58747c1e140f6852Tom Taylor 448b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Make sure mSlideshow is set up and has a slide. 4499abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor ensureSlideshow(); // mSlideshow can be null before this call, won't be afterwards 4509abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.setSlideshow(mSlideshow); 4511d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 4529abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor // Change the attachment 4539abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = append ? appendMedia(type, dataUri, slideShowEditor) 4549abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor : changeMedia(type, dataUri, slideShowEditor); 455b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 456b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If we were successful, update mAttachmentType and notify 457b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // the listener than there was a change. 458b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (result == OK) { 459b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mAttachmentType = type; 460b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 4613d00f75be4178a8b9e9ce099221e2e256bcab850Tom Taylor correctAttachmentState(true); // this can remove the slideshow if there are no attachments 4629abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor 46324149983964b1de6a98bcefeb5e6ebfa2d0d7953Tom Taylor if (mSlideshow != null && type == IMAGE) { 46440e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev // Prime the image's cache; helps A LOT when the image is coming from the network 46540e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev // (e.g. Picasa album). See b/5445690. 46640e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev int numSlides = mSlideshow.size(); 46740e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev if (numSlides > 0) { 46840e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev ImageModel imgModel = mSlideshow.get(numSlides - 1).getImage(); 4690ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor if (imgModel != null) { 47051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor cancelThumbnailLoading(); 47151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor imgModel.loadThumbnailBitmap(null); 47240e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev } 47340e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev } 47440e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev } 47540e9f8b3728339f5d0f0f16d84a05ccb0dda7636Todor Kalaydjiev 476332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor mStatusListener.onAttachmentChanged(); // have to call whether succeeded or failed, 477332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor // because a replace that fails, removes the slide 478b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 479364d926784135e4889d74c570868db046a67ccebTom Taylor if (!append && mAttachmentType == TEXT && type == TEXT) { 480364d926784135e4889d74c570868db046a67ccebTom Taylor int[] params = SmsMessage.calculateLength(getText(), false); 481364d926784135e4889d74c570868db046a67ccebTom Taylor /* SmsMessage.calculateLength returns an int[4] with: 482364d926784135e4889d74c570868db046a67ccebTom Taylor * int[0] being the number of SMS's required, 483364d926784135e4889d74c570868db046a67ccebTom Taylor * int[1] the number of code units used, 484364d926784135e4889d74c570868db046a67ccebTom Taylor * int[2] is the number of code units remaining until the next message. 485364d926784135e4889d74c570868db046a67ccebTom Taylor * int[3] is the encoding type that should be used for the message. 486364d926784135e4889d74c570868db046a67ccebTom Taylor */ 487364d926784135e4889d74c570868db046a67ccebTom Taylor int smsSegmentCount = params[0]; 488364d926784135e4889d74c570868db046a67ccebTom Taylor 489364d926784135e4889d74c570868db046a67ccebTom Taylor if (!MmsConfig.getMultipartSmsEnabled()) { 490364d926784135e4889d74c570868db046a67ccebTom Taylor // The provider doesn't support multi-part sms's so as soon as the user types 491364d926784135e4889d74c570868db046a67ccebTom Taylor // an sms longer than one segment, we have to turn the message into an mms. 492364d926784135e4889d74c570868db046a67ccebTom Taylor setLengthRequiresMms(smsSegmentCount > 1, false); 493c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin } else { 494364d926784135e4889d74c570868db046a67ccebTom Taylor int threshold = MmsConfig.getSmsToMmsTextThreshold(); 495364d926784135e4889d74c570868db046a67ccebTom Taylor setLengthRequiresMms(threshold > 0 && smsSegmentCount > threshold, false); 496c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin } 497c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin } 498b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return result; 499b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 5001d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 501b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 502b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns true if this message contains anything worth saving. 503b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 504b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean isWorthSaving() { 505b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If it actually contains anything, it's of course not empty. 506b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (hasText() || hasSubject() || hasAttachment() || hasSlideshow()) { 507b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return true; 508b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 5091d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 510b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // When saveAsMms() has been called, we set FORCE_MMS to represent 511b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // sort of an "invisible attachment" so that the message isn't thrown 512b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // away when we are shipping it off to other activities. 513c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor if (isFakeMmsForDraft()) { 514b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return true; 515b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 5161d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 517b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return false; 518b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 5191d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 52051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor private void cancelThumbnailLoading() { 52151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor int numSlides = mSlideshow != null ? mSlideshow.size() : 0; 52251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor if (numSlides > 0) { 52351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor ImageModel imgModel = mSlideshow.get(numSlides - 1).getImage(); 52451e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor if (imgModel != null) { 52551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor imgModel.cancelThumbnailLoading(); 52651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 52751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 52851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 52951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 530b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 531c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor * Returns true if FORCE_MMS is set. 532c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor * When saveAsMms() has been called, we set FORCE_MMS to represent 533c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor * sort of an "invisible attachment" so that the message isn't thrown 534c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor * away when we are shipping it off to other activities. 535c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor */ 536c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor public boolean isFakeMmsForDraft() { 537c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor return (mMmsState & FORCE_MMS) > 0; 538c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor } 539c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor 540c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor /** 541b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Makes sure mSlideshow is set up. 542b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 543b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void ensureSlideshow() { 544b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mSlideshow != null) { 545b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 546b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 5471d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 54872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SlideshowModel slideshow = SlideshowModel.createNew(mActivity); 549b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SlideModel slide = new SlideModel(slideshow); 550b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick slideshow.add(slide); 5511d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 552b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mSlideshow = slideshow; 553b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 554b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 555b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 556b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Change the message's attachment to the data in the specified Uri. 5579abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor * Used only for single-slide ("attachment mode") messages. If the attachment fails to 5589abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor * attach, restore the slide to its original state. 559b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 5609abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor private int changeMedia(int type, Uri uri, SlideshowEditor slideShowEditor) { 5619abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor SlideModel originalSlide = mSlideshow.get(0); 5629abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor if (originalSlide != null) { 5639abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.removeSlide(0); // remove the original slide 5649abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } 5659abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.addNewSlide(0); 5669abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor SlideModel slide = mSlideshow.get(0); // get the new empty slide 5679abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor int result = OK; 5681d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 5694ee7aa9aec45dd564c0e82928fa5a8378e856dcfWei Huang if (slide == null) { 5704ee7aa9aec45dd564c0e82928fa5a8378e856dcfWei Huang Log.w(LogTag.TAG, "[WorkingMessage] changeMedia: no slides!"); 5719abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 5724ee7aa9aec45dd564c0e82928fa5a8378e856dcfWei Huang } 5734ee7aa9aec45dd564c0e82928fa5a8378e856dcfWei Huang 574332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor // Clear the attachment type since we removed all the attachments. If this isn't cleared 575332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor // and the slide.add fails (for instance, a selected video could be too big), we'll be 576332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor // left in a state where we think we have an attachment, but it's been removed from the 577332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor // slide. 578332967fe883b88229780670bbc0beee0af46d3e6Tom Taylor mAttachmentType = TEXT; 5791d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 580b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If we're changing to text, just bail out. 581b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (type == TEXT) { 5829abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 583edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 584edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor 5859abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = internalChangeMedia(type, uri, 0, slideShowEditor); 5869abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor if (result != OK) { 5879abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.removeSlide(0); // remove the failed slide 5889abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor if (originalSlide != null) { 5899abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.addSlide(0, originalSlide); // restore the original slide. 5909abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } 591edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 5929abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 593edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 594edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor 595edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor /** 596edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor * Add the message's attachment to the data in the specified Uri to a new slide. 597edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor */ 5989abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor private int appendMedia(int type, Uri uri, SlideshowEditor slideShowEditor) { 5999abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor int result = OK; 600edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor 601edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // If we're changing to text, just bail out. 602edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor if (type == TEXT) { 6039abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 604edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 605edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor 606edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // The first time this method is called, mSlideshow.size() is going to be 607edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // one (a newly initialized slideshow has one empty slide). The first time we 608edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // attach the picture/video to that first empty slide. From then on when this 609edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // function is called, we've got to create a new slide and add the picture/video 610edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor // to that new slide. 611edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor boolean addNewSlide = true; 612edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor if (mSlideshow.size() == 1 && !mSlideshow.isSimple()) { 613edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor addNewSlide = false; 614edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 615edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor if (addNewSlide) { 616edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor if (!slideShowEditor.addNewSlide()) { 6179abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 618edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 619edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor } 6209abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor int slideNum = mSlideshow.size() - 1; 6219abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = internalChangeMedia(type, uri, slideNum, slideShowEditor); 6229abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor if (result != OK) { 6239abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor // We added a new slide and what we attempted to insert on the slide failed. 6249abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor // Delete that slide, otherwise we could end up with a bunch of blank slides. 6259abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor // It's ok that we're removing the slide even if we didn't add it (because it was 6269abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor // the first default slide). If adding the first slide fails, we want to remove it. 6279abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.removeSlide(slideNum); 628b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 6299abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 6309abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } 6311d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 6329abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor private int internalChangeMedia(int type, Uri uri, int slideNum, 6339abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor SlideshowEditor slideShowEditor) { 6349abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor int result = OK; 6359abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor try { 6369abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor if (type == IMAGE) { 6379abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.changeImage(slideNum, uri); 6389abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } else if (type == VIDEO) { 6399abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.changeVideo(slideNum, uri); 6409abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } else if (type == AUDIO) { 6419abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor slideShowEditor.changeAudio(slideNum, uri); 6429abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } else { 6439abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = UNSUPPORTED_TYPE; 6449abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } 6459abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } catch (MmsException e) { 646271b5212603ba1424ea2b95732932ab7c2368d14Tom Taylor Log.e(TAG, "internalChangeMedia:", e); 6479abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = UNKNOWN_ERROR; 6489abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } catch (UnsupportContentTypeException e) { 649271b5212603ba1424ea2b95732932ab7c2368d14Tom Taylor Log.e(TAG, "internalChangeMedia:", e); 6509abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = UNSUPPORTED_TYPE; 6519abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } catch (ExceedMessageSizeException e) { 652271b5212603ba1424ea2b95732932ab7c2368d14Tom Taylor Log.e(TAG, "internalChangeMedia:", e); 6539abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = MESSAGE_SIZE_EXCEEDED; 6549abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor } catch (ResolutionException e) { 655271b5212603ba1424ea2b95732932ab7c2368d14Tom Taylor Log.e(TAG, "internalChangeMedia:", e); 6569abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor result = IMAGE_TOO_LARGE; 657b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 6589abae049669b8525b28ec4f4adb2e14372b4d931Tom Taylor return result; 659b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 6601d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 661b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 662b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns true if the message has an attachment (including slideshows). 663b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 664b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean hasAttachment() { 665b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return (mAttachmentType > TEXT); 666b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 667b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 668b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 669b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns the slideshow associated with this message. 670b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 671b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public SlideshowModel getSlideshow() { 672b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return mSlideshow; 673b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 674b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 675b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 676b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns true if the message has a real slideshow, as opposed to just 677b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * one image attachment, for example. 678b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 679b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean hasSlideshow() { 680b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return (mAttachmentType == SLIDESHOW); 681b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 682b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 683b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 684b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Sets the MMS subject of the message. Passing null indicates that there 685b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * is no subject. Passing "" will result in an empty subject being added 686b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * to the message, possibly triggering a conversion to MMS. This extra 687b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * bit of state is needed to support ComposeMessageActivity converting to 688b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * MMS when the user adds a subject. An empty subject will be removed 689b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * before saving to disk or sending, however. 690b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 691396a06af4e393f5aab3864c43392a67c60715d38Tom Taylor public void setSubject(CharSequence s, boolean notify) { 692b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mSubject = s; 693396a06af4e393f5aab3864c43392a67c60715d38Tom Taylor updateState(HAS_SUBJECT, (s != null), notify); 694b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 6951d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 696b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 697b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns the MMS subject of the message. 698b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 699b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public CharSequence getSubject() { 700b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return mSubject; 701b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7021d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 703b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 704b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor * Returns true if this message has an MMS subject. A subject has to be more than just 705b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor * whitespace. 706b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @return 707b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 708b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean hasSubject() { 709b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor return mSubject != null && TextUtils.getTrimmedLength(mSubject) > 0; 710b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7111d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 712b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 713b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Moves the message text into the slideshow. Should be called any time 714b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * the message is about to be sent or written to disk. 715b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 716b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void syncTextToSlideshow() { 717b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mSlideshow == null || mSlideshow.size() != 1) 718b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 7191d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 720b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SlideModel slide = mSlideshow.get(0); 721b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick TextModel text; 722b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (!slide.hasText()) { 723b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Add a TextModel to slide 0 if one doesn't already exist 72472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor text = new TextModel(mActivity, ContentType.TEXT_PLAIN, "text_0.txt", 725b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mSlideshow.getLayout().getTextRegion()); 726b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick slide.add(text); 727b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else { 728b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Otherwise just reuse the existing one. 729b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick text = slide.getText(); 730b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 731b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick text.setText(mText); 732b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7331d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 734b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 735b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Sets the message text out of the slideshow. Should be called any time 736b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * a slideshow is loaded from disk. 737b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 738b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void syncTextFromSlideshow() { 739b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Don't sync text for real slideshows. 740b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mSlideshow.size() != 1) { 741b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 742b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 743b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 744b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SlideModel slide = mSlideshow.get(0); 7454ee7aa9aec45dd564c0e82928fa5a8378e856dcfWei Huang if (slide == null || !slide.hasText()) { 746b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 747b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7481d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 749b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mText = slide.getText().getText(); 750b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 751b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 752b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 753b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Removes the subject if it is empty, possibly converting back to SMS. 754b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 75570262ed72605a86706b3a63810d34adbfd0868a7Wei Huang private void removeSubjectIfEmpty(boolean notify) { 756b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (!hasSubject()) { 75770262ed72605a86706b3a63810d34adbfd0868a7Wei Huang setSubject(null, notify); 758b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 759b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7601d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 761b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 762b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Gets internal message state ready for storage. Should be called any 763b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * time the message is about to be sent or written to disk. 764b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 76570262ed72605a86706b3a63810d34adbfd0868a7Wei Huang private void prepareForSave(boolean notify) { 7661d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick // Make sure our working set of recipients is resolved 7671d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick // to first-class Contact objects before we save. 7681d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick syncWorkingRecipients(); 7691d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 7708cc338d324dc4c92b686029064882147e9054f17Tom Taylor if (hasMmsContentToSave()) { 771b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick ensureSlideshow(); 772b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick syncTextToSlideshow(); 773b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 774b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 7751d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 7761d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick /** 7771d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * Resolve the temporary working set of recipients to a ContactList. 7781d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick */ 779d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor public void syncWorkingRecipients() { 7801d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick if (mWorkingRecipients != null) { 7811d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick ContactList recipients = ContactList.getByNumbers(mWorkingRecipients, false); 782ca8c3f609566ac750fdbd2b01d8983b299faf5d6Tom Taylor mConversation.setRecipients(recipients); // resets the threadId to zero 783c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor setHasMultipleRecipients(recipients.size() > 1, true); 7841d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick mWorkingRecipients = null; 7851d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 7861d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 7871d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 78872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor public String getWorkingRecipients() { 78972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor // this function is used for DEBUG only 79072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor if (mWorkingRecipients == null) { 79172ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor return null; 79272ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 79372ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor ContactList recipients = ContactList.getByNumbers(mWorkingRecipients, false); 79472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor return recipients.serialize(); 79572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 79672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor 797c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor // Call when we've returned from adding an attachment. We're no longer forcing the message 798c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor // into a Mms message. At this point we either have the goods to make the message a Mms 799c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor // or we don't. No longer fake it. 800c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor public void removeFakeMmsForDraft() { 801c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor updateState(FORCE_MMS, false, false); 802c7b4497d1129fbfc1a69ee3c5a30e28153afd3e8Tom Taylor } 8031d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 804b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 805b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Force the message to be saved as MMS and return the Uri of the message. 806b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Typically used when handing a message off to another activity. 807b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 80816f98e62c279550854e665e25c212ea0b04a6b6bTom Taylor public Uri saveAsMms(boolean notify) { 8093877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor if (DEBUG) LogTag.debug("saveAsMms mConversation=%s", mConversation); 8101d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 8113877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor // If we have discarded the message, just bail out. 812b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mDiscarded) { 8133877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor LogTag.warn("saveAsMms mDiscarded: true mConversation: " + mConversation + 8143877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor " returning NULL uri and bailing"); 8153877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor return null; 816b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 8171d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 818b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // FORCE_MMS behaves as sort of an "invisible attachment", making 819b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // the message seem non-empty (and thus not discarded). This bit 820b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // is sticky until the last other MMS bit is removed, at which 821b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // point the message will fall back to SMS. 82216f98e62c279550854e665e25c212ea0b04a6b6bTom Taylor updateState(FORCE_MMS, true, notify); 8231d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 824b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Collect our state to be written to disk. 82570262ed72605a86706b3a63810d34adbfd0868a7Wei Huang prepareForSave(true /* notify */); 8261d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 8275fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor try { 8285fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Make sure we are saving to the correct thread ID. 8295fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(true); 830cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (!mConversation.getRecipients().isEmpty()) { 831cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor mConversation.ensureThreadId(); 832cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 8335fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor mConversation.setDraftState(true); 8345fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor 8355fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor PduPersister persister = PduPersister.getPduPersister(mActivity); 8367268272e8d1099b00172d379628a33ca341025c9Tom Taylor SendReq sendReq = makeSendReq(mConversation, mSubject); 8375fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor 8385fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // If we don't already have a Uri lying around, make a new one. If we do 8395fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // have one already, make sure it is synced to disk. 8405fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor if (mMessageUri == null) { 8419889006f9d29d0509c1c036987ce028de43ac96eTom Taylor mMessageUri = createDraftMmsMessage(persister, sendReq, mSlideshow, null, 842469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor mActivity, null); 8435fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } else { 844469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor updateDraftMmsMessage(mMessageUri, persister, mSlideshow, sendReq, null); 8455fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 8465fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor mHasMmsDraft = true; 8475fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } finally { 8485fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(false); 8491d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 850b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return mMessageUri; 851b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 8521d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 853b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 854b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Save this message as a draft in the conversation previously specified 855b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * to {@link setConversation}. 856b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 8575fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor public void saveDraft(final boolean isStopping) { 858b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If we have discarded the message, just bail out. 859b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mDiscarded) { 8603877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor LogTag.warn("saveDraft mDiscarded: true mConversation: " + mConversation + 8613877692b0f782ca321ce3a857b4168f771cf2ab6Tom Taylor " skipping saving draft and bailing"); 862b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 863b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 8641d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 865b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Make sure setConversation was called. 866ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick if (mConversation == null) { 867ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick throw new IllegalStateException("saveDraft() called with no conversation"); 868b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 869b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 870858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang if (LogTag.VERBOSE || Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 871858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang LogTag.debug("saveDraft for mConversation " + mConversation); 872858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang } 873858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang 87470262ed72605a86706b3a63810d34adbfd0868a7Wei Huang // Get ready to write to disk. But don't notify message status when saving draft 87570262ed72605a86706b3a63810d34adbfd0868a7Wei Huang prepareForSave(false /* notify */); 876b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 877b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (requiresMms()) { 8788cc338d324dc4c92b686029064882147e9054f17Tom Taylor if (hasMmsContentToSave()) { 8798cc338d324dc4c92b686029064882147e9054f17Tom Taylor asyncUpdateDraftMmsMessage(mConversation, isStopping); 8808cc338d324dc4c92b686029064882147e9054f17Tom Taylor mHasMmsDraft = true; 8818cc338d324dc4c92b686029064882147e9054f17Tom Taylor } 882b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else { 8834f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang String content = mText.toString(); 8844f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang 8854f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // bug 2169583: don't bother creating a thread id only to delete the thread 8864f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // because the content is empty. When we delete the thread in updateDraftSmsMessage, 8874f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // we didn't nullify conv.mThreadId, causing a temperary situation where conv 8884f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // is holding onto a thread id that isn't in the database. If a new message arrives 8894f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // and takes that thread id (because it's the next thread id to be assigned), the 8904f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang // new message will be merged with the draft message thread, causing confusion! 8914f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang if (!TextUtils.isEmpty(content)) { 8926fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen asyncUpdateDraftSmsMessage(mConversation, content, isStopping); 893dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor mHasSmsDraft = true; 8943d22f559d76a8697a472ad1e1f5a44d339dc7f46Tom Taylor } else { 8953d22f559d76a8697a472ad1e1f5a44d339dc7f46Tom Taylor // When there's no associated text message, we have to handle the case where there 8963d22f559d76a8697a472ad1e1f5a44d339dc7f46Tom Taylor // might have been a previous mms draft for this message. This can happen when a 8973d22f559d76a8697a472ad1e1f5a44d339dc7f46Tom Taylor // user turns an mms back into a sms, such as creating an mms draft with a picture, 8983d22f559d76a8697a472ad1e1f5a44d339dc7f46Tom Taylor // then removing the picture. 899dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor asyncDeleteDraftMmsMessage(mConversation); 900bb576861100138c4180438ec82c31be0dce44fc8Tom Taylor mMessageUri = null; 9014f485ea3aabce679b3d749ba843fee5134ebf118Wei Huang } 902b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 903b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 904b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 905cec2a0065dbbdce52c2de5ff994dd4417af4ee7fTom Taylor synchronized public void discard() { 906858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang if (LogTag.VERBOSE || Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 907858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang LogTag.debug("[WorkingMessage] discard"); 908812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang } 909b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 910b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mDiscarded == true) { 911cec2a0065dbbdce52c2de5ff994dd4417af4ee7fTom Taylor return; 912b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 9131d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 914b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Mark this message as discarded in order to make saveDraft() no-op. 915b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mDiscarded = true; 9161d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 91751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor cancelThumbnailLoading(); 91851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 919307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor // Delete any associated drafts if there are any. 920307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor if (mHasMmsDraft) { 921307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor asyncDeleteDraftMmsMessage(mConversation); 922307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor } 923307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor if (mHasSmsDraft) { 924307aea97f34a1d872470d9a584464a037cb039b2Tom Taylor asyncDeleteDraftSmsMessage(mConversation); 9251d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 926df041b7b2d335c21947c7264b304b4b8d5a17080Tom Taylor clearConversation(mConversation, true); 927b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 9281d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 9295cbf11ad39767245f1a9ef467963d270f19a5fabTom Taylor public void unDiscard() { 930d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (DEBUG) LogTag.debug("unDiscard"); 9315cbf11ad39767245f1a9ef467963d270f19a5fabTom Taylor 9325cbf11ad39767245f1a9ef467963d270f19a5fabTom Taylor mDiscarded = false; 9335cbf11ad39767245f1a9ef467963d270f19a5fabTom Taylor } 9345cbf11ad39767245f1a9ef467963d270f19a5fabTom Taylor 935b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 936b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns true if discard() has been called on this message. 937b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 938b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean isDiscarded() { 939b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return mDiscarded; 940b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 9411d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 942b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 943a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * To be called from our Activity's onSaveInstanceState() to give us a chance 944a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * to stow our state away for later retrieval. 945a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * 946a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * @param bundle The Bundle passed in to onSaveInstanceState 947a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor */ 948a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor public void writeStateToBundle(Bundle bundle) { 949a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor if (hasSubject()) { 950a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor bundle.putString("subject", mSubject.toString()); 951a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 952a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor 953a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor if (mMessageUri != null) { 954a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor bundle.putParcelable("msg_uri", mMessageUri); 955a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } else if (hasText()) { 956a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor bundle.putString("sms_body", mText.toString()); 957a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 958a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 959a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor 960a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor /** 961a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * To be called from our Activity's onCreate() if the activity manager 962a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * has given it a Bundle to reinflate 963a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor * @param bundle The Bundle passed in to onCreate 964a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor */ 965a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor public void readStateFromBundle(Bundle bundle) { 966a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor if (bundle == null) { 967a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor return; 968a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 969a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor 970a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor String subject = bundle.getString("subject"); 971a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor setSubject(subject, false); 972a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor 973a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor Uri uri = (Uri)bundle.getParcelable("msg_uri"); 974a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor if (uri != null) { 975a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor loadFromUri(uri); 976a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor return; 977a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } else { 978a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor String body = bundle.getString("sms_body"); 979a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor mText = body; 980a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 981a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor } 982a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor 983a95e267c5e123139f4551758586b1f44ef02f9d2Tom Taylor /** 9841d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * Update the temporary list of recipients, used when setting up a 9851d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * new conversation. Will be converted to a ContactList on any 9861d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * save event (send, save draft, etc.) 9871d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick */ 9881d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick public void setWorkingRecipients(List<String> numbers) { 9891d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick mWorkingRecipients = numbers; 990b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor String s = null; 991b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor if (numbers != null) { 992b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor int size = numbers.size(); 993b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor switch (size) { 994b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor case 1: 995b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor s = numbers.get(0); 996b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor break; 997b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor case 0: 998b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor s = "empty"; 999b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor break; 1000b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor default: 1001b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor s = "{...} len=" + size; 1002b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor } 1003b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor } 100472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 100572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor 100672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor private void dumpWorkingRecipients() { 100772ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Log.i(TAG, "-- mWorkingRecipients:"); 100872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor 100972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor if (mWorkingRecipients != null) { 101072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor int count = mWorkingRecipients.size(); 101172ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor for (int i=0; i<count; i++) { 101272ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Log.i(TAG, " [" + i + "] " + mWorkingRecipients.get(i)); 101372ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 101472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Log.i(TAG, ""); 101572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 101672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 101772ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor 101872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor public void dump() { 101972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Log.i(TAG, "WorkingMessage:"); 102072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor dumpWorkingRecipients(); 102172ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor if (mConversation != null) { 102272ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Log.i(TAG, "mConversation: " + mConversation.toString()); 102372ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor } 10241d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 10251d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1026b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 1027b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Set the conversation associated with this message. 1028b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 1029ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick public void setConversation(Conversation conv) { 1030d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (DEBUG) LogTag.debug("setConversation %s -> %s", mConversation, conv); 1031ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick 1032ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick mConversation = conv; 10331d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1034b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Convert to MMS if there are any email addresses in the recipient list. 1035c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor ContactList contactList = conv.getRecipients(); 1036c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor setHasEmail(contactList.containsEmail(), false); 1037c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor setHasMultipleRecipients(contactList.size() > 1, false); 10381d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick } 10391d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1040b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor public Conversation getConversation() { 1041b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor return mConversation; 1042b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor } 1043b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor 10441d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick /** 10451d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * Hint whether or not this message will be delivered to an 10461d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * an email address. 10471d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick */ 1048200d37d90dd7640aa909edca6a2b55961faa5824Tom Taylor public void setHasEmail(boolean hasEmail, boolean notify) { 1049cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom if (MmsConfig.getEmailGateway() != null) { 1050200d37d90dd7640aa909edca6a2b55961faa5824Tom Taylor updateState(RECIPIENTS_REQUIRE_MMS, false, notify); 1051cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } else { 1052200d37d90dd7640aa909edca6a2b55961faa5824Tom Taylor updateState(RECIPIENTS_REQUIRE_MMS, hasEmail, notify); 1053cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1054b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1055c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor /** 1056c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor * Set whether this message will be sent to multiple recipients. This is a hint whether the 1057c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor * message needs to be sent as an mms or not. If MmsConfig.getGroupMmsEnabled is false, then 1058c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor * the fact that the message is sent to multiple recipients is not a factor in determining 1059c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor * whether the message is sent as an mms, but the other factors (such as, "has a picture 1060c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor * attachment") still hold true. 1061c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor */ 1062c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor public void setHasMultipleRecipients(boolean hasMultipleRecipients, boolean notify) { 10639889006f9d29d0509c1c036987ce028de43ac96eTom Taylor updateState(MULTIPLE_RECIPIENTS, 10649889006f9d29d0509c1c036987ce028de43ac96eTom Taylor hasMultipleRecipients && 10659889006f9d29d0509c1c036987ce028de43ac96eTom Taylor MessagingPreferenceActivity.getIsGroupMmsEnabled(mActivity), 1066c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor notify); 1067c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor } 1068b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1069b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 1070b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Returns true if this message would require MMS to send. 1071b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 1072b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public boolean requiresMms() { 1073b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return (mMmsState > 0); 1074b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 10751d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 10769aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin /** 10778cc338d324dc4c92b686029064882147e9054f17Tom Taylor * Returns true if this message has been turned into an mms because it has a subject or 10788cc338d324dc4c92b686029064882147e9054f17Tom Taylor * an attachment, but not just because it has multiple recipients. 10798cc338d324dc4c92b686029064882147e9054f17Tom Taylor */ 10808cc338d324dc4c92b686029064882147e9054f17Tom Taylor private boolean hasMmsContentToSave() { 10818cc338d324dc4c92b686029064882147e9054f17Tom Taylor if (mMmsState == 0) { 10828cc338d324dc4c92b686029064882147e9054f17Tom Taylor return false; 10838cc338d324dc4c92b686029064882147e9054f17Tom Taylor } 10848cc338d324dc4c92b686029064882147e9054f17Tom Taylor if (mMmsState == MULTIPLE_RECIPIENTS && !hasText()) { 10858cc338d324dc4c92b686029064882147e9054f17Tom Taylor // If this message is only mms because of multiple recipients and there's no text 10868cc338d324dc4c92b686029064882147e9054f17Tom Taylor // to save, don't bother saving. 10878cc338d324dc4c92b686029064882147e9054f17Tom Taylor return false; 10888cc338d324dc4c92b686029064882147e9054f17Tom Taylor } 10898cc338d324dc4c92b686029064882147e9054f17Tom Taylor return true; 10908cc338d324dc4c92b686029064882147e9054f17Tom Taylor } 10918cc338d324dc4c92b686029064882147e9054f17Tom Taylor 10928cc338d324dc4c92b686029064882147e9054f17Tom Taylor /** 10939aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin * Set whether or not we want to send this message via MMS in order to 10949aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin * avoid sending an excessive number of concatenated SMS messages. 1095c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin * @param: mmsRequired is the value for the LENGTH_REQUIRES_MMS bit. 1096c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin * @param: notify Whether or not to notify the user. 10979aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin */ 1098c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin public void setLengthRequiresMms(boolean mmsRequired, boolean notify) { 1099c8859ed1e7b47996762dcb34f160521f276dccdfSoojung Shin updateState(LENGTH_REQUIRES_MMS, mmsRequired, notify); 11009aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin } 11019aed641d68fafdec88f83d9c4f949ca9ab6fdb0eSoojung Shin 1102b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static String stateString(int state) { 1103b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (state == 0) 1104b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return "<none>"; 11051d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1106b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick StringBuilder sb = new StringBuilder(); 1107b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if ((state & RECIPIENTS_REQUIRE_MMS) > 0) 1108b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append("RECIPIENTS_REQUIRE_MMS | "); 1109b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if ((state & HAS_SUBJECT) > 0) 1110b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append("HAS_SUBJECT | "); 1111b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if ((state & HAS_ATTACHMENT) > 0) 1112b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append("HAS_ATTACHMENT | "); 1113b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if ((state & LENGTH_REQUIRES_MMS) > 0) 1114b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append("LENGTH_REQUIRES_MMS | "); 1115b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if ((state & FORCE_MMS) > 0) 1116b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append("FORCE_MMS | "); 1117c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor if ((state & MULTIPLE_RECIPIENTS) > 0) 1118c1f03822994dc09939060c41e0ce9cb37175b054Tom Taylor sb.append("MULTIPLE_RECIPIENTS | "); 1119b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1120b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.delete(sb.length() - 3, sb.length()); 1121b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return sb.toString(); 1122b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1123b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1124b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 1125b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Sets the current state of our various "MMS required" bits. 11261d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * 1127b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @param state The bit to change, such as {@link HAS_ATTACHMENT} 1128b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @param on If true, set it; if false, clear it 11291d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick * @param notify Whether or not to notify the user 1130b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 1131b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void updateState(int state, boolean on, boolean notify) { 11321d95d8928940553e9e99f34ad075865b9b34781cTom Taylor if (!sMmsEnabled) { 11331d95d8928940553e9e99f34ad075865b9b34781cTom Taylor // If Mms isn't enabled, the rest of the Messaging UI should not be using any 11341d95d8928940553e9e99f34ad075865b9b34781cTom Taylor // feature that would cause us to to turn on any Mms flag and show the 11351d95d8928940553e9e99f34ad075865b9b34781cTom Taylor // "Converting to multimedia..." message. 11361d95d8928940553e9e99f34ad075865b9b34781cTom Taylor return; 11371d95d8928940553e9e99f34ad075865b9b34781cTom Taylor } 1138b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick int oldState = mMmsState; 1139b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (on) { 1140b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mMmsState |= state; 1141b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else { 1142b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mMmsState &= ~state; 1143b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1144b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1145b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If we are clearing the last bit that is not FORCE_MMS, 1146b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // expire the FORCE_MMS bit. 1147b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (mMmsState == FORCE_MMS && ((oldState & ~FORCE_MMS) > 0)) { 1148b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mMmsState = 0; 1149b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 11501d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1151b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Notify the listener if we are moving from SMS to MMS 1152b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // or vice versa. 1153b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (notify) { 1154b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (oldState == 0 && mMmsState != 0) { 1155b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mStatusListener.onProtocolChanged(true); 1156b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else if (oldState != 0 && mMmsState == 0) { 1157b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mStatusListener.onProtocolChanged(false); 1158b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1159b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 11601d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1161b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (oldState != mMmsState) { 1162d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) LogTag.debug("updateState: %s%s = %s", 1163d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor on ? "+" : "-", 1164b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick stateString(state), stateString(mMmsState)); 1165b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1166b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1167b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1168b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 1169b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Send this message over the network. Will call back with onMessageSent() once 1170b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * it has been dispatched to the telephony stack. This WorkingMessage object is 1171b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * no longer useful after this method has been called. 117268e246906f9c02a52edf383440c379201b626306David Mailhot * 117368e246906f9c02a52edf383440c379201b626306David Mailhot * @throws ContentRestrictionException if sending an MMS and uaProfUrl is not defined 117468e246906f9c02a52edf383440c379201b626306David Mailhot * in mms_config.xml. 1175b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 117672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor public void send(final String recipientsInUI) { 1177cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor long origThreadId = mConversation.getThreadId(); 1178cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor 11790d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { 1180cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("send origThreadId: " + origThreadId); 11810d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang } 1182b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1183f89f24a7595ded1355da36d3c1229450a6157a0bTom Taylor removeSubjectIfEmpty(true /* notify */); 1184f89f24a7595ded1355da36d3c1229450a6157a0bTom Taylor 1185b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Get ready to write to disk. 118670262ed72605a86706b3a63810d34adbfd0868a7Wei Huang prepareForSave(true /* notify */); 11871d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1188b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // We need the recipient list for both SMS and MMS. 1189ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick final Conversation conv = mConversation; 1190cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom String msgTxt = mText.toString(); 1191b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1192cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) { 119368e246906f9c02a52edf383440c379201b626306David Mailhot // uaProfUrl setting in mms_config.xml must be present to send an MMS. 119468e246906f9c02a52edf383440c379201b626306David Mailhot // However, SMS service will still work in the absence of a uaProfUrl address. 119568e246906f9c02a52edf383440c379201b626306David Mailhot if (MmsConfig.getUaProfUrl() == null) { 119668e246906f9c02a52edf383440c379201b626306David Mailhot String err = "WorkingMessage.send MMS sending failure. mms_config.xml is " + 119768e246906f9c02a52edf383440c379201b626306David Mailhot "missing uaProfUrl setting. uaProfUrl is required for MMS service, " + 119868e246906f9c02a52edf383440c379201b626306David Mailhot "but can be absent for SMS."; 11990ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor RuntimeException ex = new NullPointerException(err); 120068e246906f9c02a52edf383440c379201b626306David Mailhot Log.e(TAG, err, ex); 120168e246906f9c02a52edf383440c379201b626306David Mailhot // now, let's just crash. 120268e246906f9c02a52edf383440c379201b626306David Mailhot throw ex; 120368e246906f9c02a52edf383440c379201b626306David Mailhot } 120468e246906f9c02a52edf383440c379201b626306David Mailhot 1205b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Make local copies of the bits we need for sending a message, 1206b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // because we will be doing it off of the main thread, which will 1207b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // immediately continue on to resetting some of this state. 1208b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick final Uri mmsUri = mMessageUri; 120972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor final PduPersister persister = PduPersister.getPduPersister(mActivity); 1210b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1211b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick final SlideshowModel slideshow = mSlideshow; 1212b736686638eca62aa89cb15184711ef38413cb3eTom Taylor final CharSequence subject = mSubject; 1213c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor final boolean textOnly = mAttachmentType == TEXT; 12141d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1215cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { 1216cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("Send mmsUri: " + mmsUri); 1217cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 1218cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor 1219963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang // Do the dirty work of sending the message off of the main UI thread. 1220963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang new Thread(new Runnable() { 1221ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev @Override 1222963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang public void run() { 12237268272e8d1099b00172d379628a33ca341025c9Tom Taylor final SendReq sendReq = makeSendReq(conv, subject); 1224b736686638eca62aa89cb15184711ef38413cb3eTom Taylor 122510eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor // Make sure the text in slide 0 is no longer holding onto a reference to 122610eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor // the text in the message text box. 122710eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor slideshow.prepareForSend(); 1228c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq, textOnly); 12295e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor 12305e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor updateSendStats(conv); 1231963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang } 1232ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "WorkingMessage.send MMS").start(); 1233b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } else { 1234b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Same rules apply as above. 1235b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick final String msgText = mText.toString(); 1236b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick new Thread(new Runnable() { 1237ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev @Override 1238b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public void run() { 123972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor preSendSmsWorker(conv, msgText, recipientsInUI); 12405e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor 12415e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor updateSendStats(conv); 1242b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1243ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "WorkingMessage.send SMS").start(); 1244b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 12451d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1246431e11d429783c07eca6e789de0518d17b42fb74Wei Huang // update the Recipient cache with the new to address, if it's different 1247431e11d429783c07eca6e789de0518d17b42fb74Wei Huang RecipientIdCache.updateNumbers(conv.getThreadId(), conv.getRecipients()); 1248431e11d429783c07eca6e789de0518d17b42fb74Wei Huang 1249b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Mark the message as discarded because it is "off the market" after being sent. 1250b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick mDiscarded = true; 1251b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1252b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 12535e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor // Be sure to only call this on a background thread. 12545e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor private void updateSendStats(final Conversation conv) { 12555e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor String[] dests = conv.getRecipients().getNumbers(); 12565e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor final ArrayList<String> phoneNumbers = new ArrayList<String>(Arrays.asList(dests)); 12575e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor 12585e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor DataUsageStatUpdater updater = new DataUsageStatUpdater(mActivity); 12595e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor updater.updateWithPhoneNumber(phoneNumbers); 12605e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor } 12615e1c97e1f90901c48bfde61a1ddb5fbc7e0a0c39Tom Taylor 1262cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom private boolean addressContainsEmailToMms(Conversation conv, String text) { 1263cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom if (MmsConfig.getEmailGateway() != null) { 1264cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom String[] dests = conv.getRecipients().getNumbers(); 1265cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom int length = dests.length; 1266cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom for (int i = 0; i < length; i++) { 1267817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom if (Mms.isEmailAddress(dests[i]) || MessageUtils.isAlias(dests[i])) { 1268cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom String mtext = dests[i] + " " + text; 1269cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom int[] params = SmsMessage.calculateLength(mtext, false); 1270cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom if (params[0] > 1) { 1271cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom updateState(RECIPIENTS_REQUIRE_MMS, true, true); 12728b8512311239cfd2b086827a406de636c6f0e197Satish Roddom ensureSlideshow(); 12738b8512311239cfd2b086827a406de636c6f0e197Satish Roddom syncTextToSlideshow(); 1274cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom return true; 1275cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1276cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1277cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1278cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1279cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom return false; 1280cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom } 1281cea16acf02be8943133bc5048b1d64286bfef1d8Satish Roddom 1282b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Message sending stuff 12831d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 128472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI) { 12854cd245dd6fc1b9e45d774fbccc54a69a3a765861Maryam Garrett // If user tries to send the message, it's a signal the inputted text is what they wanted. 128672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor UserHappinessSignals.userAcceptedImeText(mActivity); 12870d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor 1288c44a89a040956a7b9635de4a9bcf1d7230692750Tom Taylor mStatusListener.onPreMessageSent(); 1289feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor 1290b6e4518a7b3740e48fd03f3803cc8696f15bbcc7Tom Taylor long origThreadId = conv.getThreadId(); 1291b6e4518a7b3740e48fd03f3803cc8696f15bbcc7Tom Taylor 1292858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang // Make sure we are still using the correct thread ID for our recipient set. 1293ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick long threadId = conv.ensureThreadId(); 12941d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1295b736686638eca62aa89cb15184711ef38413cb3eTom Taylor String semiSepRecipients = conv.getRecipients().serialize(); 1296feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor 129772ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor // recipientsInUI can be empty when the user types in a number and hits send 129872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor if (LogTag.SEVERE_WARNING && ((origThreadId != 0 && origThreadId != threadId) || 129972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor (!semiSepRecipients.equals(recipientsInUI) && !TextUtils.isEmpty(recipientsInUI)))) { 130072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor String msg = origThreadId != 0 && origThreadId != threadId ? 130172ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor "WorkingMessage.preSendSmsWorker threadId changed or " + 130272ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor "recipients changed. origThreadId: " + 130372ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor origThreadId + " new threadId: " + threadId + 130472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor " also mConversation.getThreadId(): " + 130572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor mConversation.getThreadId() 130672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor : 130772ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor "Recipients in window: \"" + 130872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor recipientsInUI + "\" differ from recipients from conv: \"" + 130972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor semiSepRecipients + "\""; 131072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor 13111be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen // Just interrupt the process of sending message if recipient mismatch 131272ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor LogTag.warnPossibleRecipientMismatch(msg, mActivity); 13131be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen }else { 13141be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen // just do a regular send. We're already on a non-ui thread so no need to fire 13151be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen // off another thread to do this work. 13161be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen sendSmsWorker(msgText, semiSepRecipients, threadId); 13176a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor 13181be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen // Be paranoid and clean any draft SMS up. 13191be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen deleteDraftSmsMessage(threadId); 13201be333235a1ef5dbc09f50c71aa2341507d6f978Roger Chen } 1321feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor } 1322feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor 1323feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor private void sendSmsWorker(String msgText, String semiSepRecipients, long threadId) { 1324feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor String[] dests = TextUtils.split(semiSepRecipients, ";"); 1325858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang if (LogTag.VERBOSE || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { 13265a9381876ce766cc761c3e6ed2ea9a67e19bd716Tom Taylor Log.d(LogTag.TRANSACTION, "sendSmsWorker sending message: recipients=" + 13275a9381876ce766cc761c3e6ed2ea9a67e19bd716Tom Taylor semiSepRecipients + ", threadId=" + threadId); 1328feb1aab54eabc98a04349af52e19ff9fbcd7c169Tom Taylor } 132972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId); 1330b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 1331b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sender.sendMessage(threadId); 133207ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor 13333239889e9a417617b755d4cde22070843e5c070bTom Taylor // Make sure this thread isn't over the limits in message count 133472ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId); 133510eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor } catch (Exception e) { 1336b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e); 1337b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 13381d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1339ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick mStatusListener.onMessageSent(); 1340c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor MmsWidgetProvider.notifyDatasetChanged(mActivity); 1341b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1342b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1343ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick private void sendMmsWorker(Conversation conv, Uri mmsUri, PduPersister persister, 1344c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor SlideshowModel slideshow, SendReq sendReq, boolean textOnly) { 13455fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor long threadId = 0; 1346c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor Cursor cursor = null; 1347c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor boolean newMessage = false; 13485fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor try { 1349c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor // Put a placeholder message in the database first 13505fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(true); 1351c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor mStatusListener.onPreMessageSent(); 1352b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 13535fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Make sure we are still using the correct thread ID for our 13545fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // recipient set. 13555fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor threadId = conv.ensureThreadId(); 1356b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 13575fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1358cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("sendMmsWorker: update draft MMS message " + mmsUri + 1359cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor " threadId: " + threadId); 13605fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 13611d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 13627268272e8d1099b00172d379628a33ca341025c9Tom Taylor // One last check to verify the address of the recipient. 13637268272e8d1099b00172d379628a33ca341025c9Tom Taylor String[] dests = conv.getRecipients().getNumbers(true /* scrub for MMS address */); 13647268272e8d1099b00172d379628a33ca341025c9Tom Taylor if (dests.length == 1) { 13657268272e8d1099b00172d379628a33ca341025c9Tom Taylor // verify the single address matches what's in the database. If we get a different 13667268272e8d1099b00172d379628a33ca341025c9Tom Taylor // address back, jam the new value back into the SendReq. 13677268272e8d1099b00172d379628a33ca341025c9Tom Taylor String newAddress = 13687268272e8d1099b00172d379628a33ca341025c9Tom Taylor Conversation.verifySingleRecipient(mActivity, conv.getThreadId(), dests[0]); 13697268272e8d1099b00172d379628a33ca341025c9Tom Taylor 1370cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1371cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("sendMmsWorker: newAddress " + newAddress + 1372cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor " dests[0]: " + dests[0]); 1373cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 1374cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor 13757268272e8d1099b00172d379628a33ca341025c9Tom Taylor if (!newAddress.equals(dests[0])) { 13767268272e8d1099b00172d379628a33ca341025c9Tom Taylor dests[0] = newAddress; 13777268272e8d1099b00172d379628a33ca341025c9Tom Taylor EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(dests); 13787268272e8d1099b00172d379628a33ca341025c9Tom Taylor if (encodedNumbers != null) { 1379cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1380cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("sendMmsWorker: REPLACING number!!!"); 1381cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 13827268272e8d1099b00172d379628a33ca341025c9Tom Taylor sendReq.setTo(encodedNumbers); 13837268272e8d1099b00172d379628a33ca341025c9Tom Taylor } 13847268272e8d1099b00172d379628a33ca341025c9Tom Taylor } 13857268272e8d1099b00172d379628a33ca341025c9Tom Taylor } 1386c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor newMessage = mmsUri == null; 1387c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor if (newMessage) { 1388c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor // Write something in the database so the new message will appear as sending 1389c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor ContentValues values = new ContentValues(); 1390c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor values.put(Mms.MESSAGE_BOX, Mms.MESSAGE_BOX_OUTBOX); 1391c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor values.put(Mms.THREAD_ID, threadId); 1392c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor values.put(Mms.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ); 1393c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor if (textOnly) { 1394c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor values.put(Mms.TEXT_ONLY, 1); 1395c6501ab9f1882d802ef7805967d936ecce52fbbfTom Taylor } 1396c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor mmsUri = SqliteWrapper.insert(mActivity, mContentResolver, Mms.Outbox.CONTENT_URI, 1397c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor values); 1398c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1399c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor mStatusListener.onMessageSent(); 1400c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor 1401c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor // If user tries to send the message, it's a signal the inputted text is 1402c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor // what they wanted. 1403c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor UserHappinessSignals.userAcceptedImeText(mActivity); 14047268272e8d1099b00172d379628a33ca341025c9Tom Taylor 1405c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor // First make sure we don't have too many outstanding unsent message. 1406c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor cursor = SqliteWrapper.query(mActivity, mContentResolver, 1407c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor Mms.Outbox.CONTENT_URI, MMS_OUTBOX_PROJECTION, null, null, null); 1408c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor if (cursor != null) { 1409c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor long maxMessageSize = MmsConfig.getMaxSizeScaleForPendingMmsAllowed() * 1410c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor MmsConfig.getMaxMessageSize(); 1411c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor long totalPendingSize = 0; 1412c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor while (cursor.moveToNext()) { 1413c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor totalPendingSize += cursor.getLong(MMS_MESSAGE_SIZE_INDEX); 1414c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1415c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor if (totalPendingSize >= maxMessageSize) { 1416c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor unDiscard(); // it wasn't successfully sent. Allow it to be saved as a draft. 1417c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor mStatusListener.onMaxPendingMessagesReached(); 1418c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor markMmsMessageWithError(mmsUri); 1419c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor return; 1420c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1421c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1422c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } finally { 1423c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor if (cursor != null) { 1424c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor cursor.close(); 1425c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1426c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor } 1427c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor 1428c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor try { 1429c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor if (newMessage) { 14305fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Create a new MMS message if one hasn't been made yet. 1431469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor mmsUri = createDraftMmsMessage(persister, sendReq, slideshow, mmsUri, 1432469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor mActivity, null); 14335fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } else { 14345fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Otherwise, sync the MMS message in progress to disk. 1435469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq, null); 14365fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 1437c7797433b1641be0cb77e02541b8bfed94c48835Tom Taylor 14385fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Be paranoid and clean any draft SMS up. 14395fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor deleteDraftSmsMessage(threadId); 14405fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } finally { 14415fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(false); 14425fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 14431d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 144410eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor // Resize all the resizeable attachments (e.g. pictures) to fit 144510eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor // in the remaining space in the slideshow. 144610eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor int error = 0; 144710eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor try { 144810eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor slideshow.finalResize(mmsUri); 144910eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor } catch (ExceedMessageSizeException e1) { 145010eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor error = MESSAGE_SIZE_EXCEEDED; 145110eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor } catch (MmsException e1) { 145210eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor error = UNKNOWN_ERROR; 145310eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor } 145410eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor if (error != 0) { 14550d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor markMmsMessageWithError(mmsUri); 145610eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor mStatusListener.onAttachmentError(error); 145710eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor return; 145810eed0e3020e3eb0612747fe39e0f6117222dd95Tom Taylor } 145972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor MessageSender sender = new MmsMessageSender(mActivity, mmsUri, 1460692636241c9858b6b535c876a79be2f04d8201b5Tom Taylor slideshow.getCurrentMessageSize()); 1461b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 1462b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (!sender.sendMessage(threadId)) { 1463b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // The message was sent through SMS protocol, we should 1464b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // delete the copy which was previously saved in MMS drafts. 146572ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SqliteWrapper.delete(mActivity, mContentResolver, mmsUri, null, null); 1466b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 146707ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor 146823da10700b189ccca64b8e729631763572a0f15fTom Taylor // Make sure this thread isn't over the limits in message count 146972ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId); 1470b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } catch (Exception e) { 1471b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Log.e(TAG, "Failed to send message: " + mmsUri + ", threadId=" + threadId, e); 1472b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1473c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor MmsWidgetProvider.notifyDatasetChanged(mActivity); 1474b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 14751d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 14760d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor private void markMmsMessageWithError(Uri mmsUri) { 14770d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor try { 147872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor PduPersister p = PduPersister.getPduPersister(mActivity); 14790d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor // Move the message into MMS Outbox. A trigger will create an entry in 14800d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor // the "pending_msgs" table. 14810d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor p.move(mmsUri, Mms.Outbox.CONTENT_URI); 14820d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor 14830d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor // Now update the pending_msgs table with an error for that new item. 14840d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor ContentValues values = new ContentValues(1); 14850d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor values.put(PendingMessages.ERROR_TYPE, MmsSms.ERR_TYPE_GENERIC_PERMANENT); 14860d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor long msgId = ContentUris.parseId(mmsUri); 148772ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SqliteWrapper.update(mActivity, mContentResolver, 14880d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor PendingMessages.CONTENT_URI, 14891db5a0d573c462a5be6f8da636b4a7db18a7bf08Tom Taylor values, PendingMessages.MSG_ID + "=" + msgId, null); 14900d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor } catch (MmsException e) { 14910d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor // Not much we can do here. If the p.move throws an exception, we'll just 14920d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor // leave the message in the draft box. 14930d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor Log.e(TAG, "Failed to move message to outbox and mark as error: " + mmsUri, e); 14940d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor } 14950d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor } 14960d4645de339b4681d18198ba7451e7b8807116f9Tom Taylor 1497b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // Draft message stuff 14981d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1499b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final String[] MMS_DRAFT_PROJECTION = { 1500da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor Mms._ID, // 0 1501da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor Mms.SUBJECT, // 1 1502da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor Mms.SUBJECT_CHARSET // 2 1503b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick }; 1504b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1505da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor private static final int MMS_ID_INDEX = 0; 1506da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor private static final int MMS_SUBJECT_INDEX = 1; 1507da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor private static final int MMS_SUBJECT_CS_INDEX = 2; 1508b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1509fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor private static Uri readDraftMmsMessage(Context context, Conversation conv, StringBuilder sb) { 1510d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1511fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor LogTag.debug("readDraftMmsMessage conv: " + conv); 1512d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 1513b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Cursor cursor; 1514b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick ContentResolver cr = context.getContentResolver(); 15151d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1516fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor final String selection = Mms.THREAD_ID + " = " + conv.getThreadId(); 1517b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick cursor = SqliteWrapper.query(context, cr, 1518b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Mms.Draft.CONTENT_URI, MMS_DRAFT_PROJECTION, 1519b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick selection, null, null); 15207d0bdc14482c047c75046d63627da8d35f1dc95eMarcel Bokhorst if (cursor == null) { 15217d0bdc14482c047c75046d63627da8d35f1dc95eMarcel Bokhorst return null; 15227d0bdc14482c047c75046d63627da8d35f1dc95eMarcel Bokhorst } 1523b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1524b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Uri uri; 1525b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 1526b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (cursor.moveToFirst()) { 1527b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick uri = ContentUris.withAppendedId(Mms.Draft.CONTENT_URI, 1528b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick cursor.getLong(MMS_ID_INDEX)); 1529da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor String subject = MessageUtils.extractEncStrFromCursor(cursor, MMS_SUBJECT_INDEX, 1530da45ea49883b2b0e2aad4ce2c738a61bf4e59b9fTom Taylor MMS_SUBJECT_CS_INDEX); 1531b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (subject != null) { 1532b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sb.append(subject); 1533b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1534fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1535fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor LogTag.debug("readDraftMmsMessage uri: ", uri); 1536fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor } 1537b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return uri; 1538b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1539b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } finally { 1540b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick cursor.close(); 1541b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1542b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1543b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return null; 1544b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1545b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1546963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang /** 1547963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang * makeSendReq should always return a non-null SendReq, whether the dest addresses are 1548b259ebbdef366c08711fd6fd0f6122bcacdcfdebTom Taylor * valid or not. 1549963f4a964e227d62eddbe2e1f6fb0721f665f4d2Wei Huang */ 15507268272e8d1099b00172d379628a33ca341025c9Tom Taylor private static SendReq makeSendReq(Conversation conv, CharSequence subject) { 155178f81825431c8c52cad57bc4a363747533a701abWei Huang String[] dests = conv.getRecipients().getNumbers(true /* scrub for MMS address */); 155278f81825431c8c52cad57bc4a363747533a701abWei Huang 1553b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SendReq req = new SendReq(); 1554b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(dests); 1555b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (encodedNumbers != null) { 1556b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick req.setTo(encodedNumbers); 1557b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 15581d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1559b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (!TextUtils.isEmpty(subject)) { 1560b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick req.setSubject(new EncodedStringValue(subject.toString())); 1561b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 15621d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1563b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick req.setDate(System.currentTimeMillis() / 1000L); 1564b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1565b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return req; 1566b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 15671d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1568b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static Uri createDraftMmsMessage(PduPersister persister, SendReq sendReq, 1569469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor SlideshowModel slideshow, Uri preUri, Context context, 1570469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor HashMap<Uri, InputStream> preOpenedFiles) { 1571402b4a84df9426e0079739621b8926dfb8731923Tom Taylor if (slideshow == null) { 1572402b4a84df9426e0079739621b8926dfb8731923Tom Taylor return null; 1573402b4a84df9426e0079739621b8926dfb8731923Tom Taylor } 1574b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 1575b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick PduBody pb = slideshow.toPduBody(); 1576b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick sendReq.setBody(pb); 15779889006f9d29d0509c1c036987ce028de43ac96eTom Taylor Uri res = persister.persist(sendReq, preUri == null ? Mms.Draft.CONTENT_URI : preUri, 1578469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor true, MessagingPreferenceActivity.getIsGroupMmsEnabled(context), 1579469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor preOpenedFiles); 1580b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick slideshow.sync(pb); 1581b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return res; 1582b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } catch (MmsException e) { 1583b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return null; 1584b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1585b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1586b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 15875fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor private void asyncUpdateDraftMmsMessage(final Conversation conv, final boolean isStopping) { 1588812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1589d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.debug("asyncUpdateDraftMmsMessage conv=%s mMessageUri=%s", conv, mMessageUri); 1590812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang } 1591469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor final HashMap<Uri, InputStream> preOpenedFiles = 1592469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor mSlideshow.openPartFiles(mContentResolver); 15931d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1594b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick new Thread(new Runnable() { 1595ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev @Override 1596b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public void run() { 15975fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor try { 15985fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(true); 1599cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor 16005fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor final PduPersister persister = PduPersister.getPduPersister(mActivity); 16017268272e8d1099b00172d379628a33ca341025c9Tom Taylor final SendReq sendReq = makeSendReq(conv, mSubject); 16025fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor 16035fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor if (mMessageUri == null) { 16049889006f9d29d0509c1c036987ce028de43ac96eTom Taylor mMessageUri = createDraftMmsMessage(persister, sendReq, mSlideshow, null, 1605469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor mActivity, preOpenedFiles); 16065fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } else { 1607469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor updateDraftMmsMessage(mMessageUri, persister, mSlideshow, sendReq, 1608469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor preOpenedFiles); 16095fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 16106fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen ensureThreadIdIfNeeded(conv, isStopping); 16115fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor conv.setDraftState(true); 16125fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 16135fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor LogTag.debug("asyncUpdateDraftMmsMessage conv: " + conv + 16145fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor " uri: " + mMessageUri); 16155fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 161646bf2f57d3b88e90dc40527e1cae6f8032d27fccTom Taylor 16175fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // Be paranoid and delete any SMS drafts that might be lying around. Must do 16185fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor // this after ensureThreadId so conv has the correct thread id. 16195fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor asyncDeleteDraftSmsMessage(conv); 16205fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } finally { 16215fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(false); 1622469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor closePreOpenedFiles(preOpenedFiles); 16235fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 1624b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1625ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "WorkingMessage.asyncUpdateDraftMmsMessage").start(); 1626b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 16271d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1628b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static void updateDraftMmsMessage(Uri uri, PduPersister persister, 1629469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor SlideshowModel slideshow, SendReq sendReq, HashMap<Uri, InputStream> preOpenedFiles) { 1630d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1631d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.debug("updateDraftMmsMessage uri=%s", uri); 1632d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 1633782238c8102fc32f96359f6fc5a01715806d4f77Tom Taylor if (uri == null) { 1634782238c8102fc32f96359f6fc5a01715806d4f77Tom Taylor Log.e(TAG, "updateDraftMmsMessage null uri"); 1635782238c8102fc32f96359f6fc5a01715806d4f77Tom Taylor return; 1636782238c8102fc32f96359f6fc5a01715806d4f77Tom Taylor } 1637b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick persister.updateHeaders(uri, sendReq); 1638cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor 1639b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick final PduBody pb = slideshow.toPduBody(); 1640b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1641b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick try { 1642469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor persister.updateParts(uri, pb, preOpenedFiles); 1643b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } catch (MmsException e) { 1644b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Log.e(TAG, "updateDraftMmsMessage: cannot update message " + uri); 1645b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1646b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1647b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick slideshow.sync(pb); 1648b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1649b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1650469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor private static void closePreOpenedFiles(HashMap<Uri, InputStream> preOpenedFiles) { 1651469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor if (preOpenedFiles == null) { 1652469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor return; 1653469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } 1654469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor Set<Uri> uris = preOpenedFiles.keySet(); 1655469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor for (Uri uri : uris) { 1656469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor InputStream is = preOpenedFiles.get(uri); 1657469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor if (is != null) { 1658469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor try { 1659469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor is.close(); 1660469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } catch (IOException e) { 1661469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } 1662469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } 1663469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } 1664469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor } 1665469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor 1666b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private static final String SMS_DRAFT_WHERE = Sms.TYPE + "=" + Sms.MESSAGE_TYPE_DRAFT; 16671d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick private static final String[] SMS_BODY_PROJECTION = { Sms.BODY }; 16681d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick private static final int SMS_BODY_INDEX = 0; 16691d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1670b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick /** 1671b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * Reads a draft message for the given thread ID from the database, 1672b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * if there is one, deletes it from the database, and returns it. 1673b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick * @return The draft message or an empty string. 1674b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick */ 16756a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor private String readDraftSmsMessage(Conversation conv) { 16766a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor long thread_id = conv.getThreadId(); 1677d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 16785a9381876ce766cc761c3e6ed2ea9a67e19bd716Tom Taylor Log.d(TAG, "readDraftSmsMessage conv: " + conv); 1679d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 16806a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor // If it's an invalid thread or we know there's no draft, don't bother. 16816a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor if (thread_id <= 0 || !conv.hasDraft()) { 1682b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return ""; 1683b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1684b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1685b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick Uri thread_uri = ContentUris.withAppendedId(Sms.Conversations.CONTENT_URI, thread_id); 1686b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick String body = ""; 1687b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 168872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor Cursor c = SqliteWrapper.query(mActivity, mContentResolver, 1689b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick thread_uri, SMS_BODY_PROJECTION, SMS_DRAFT_WHERE, null, null); 1690436042159134e8ecbc57097340a5bd81f2912574Tom Taylor boolean haveDraft = false; 16916a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor if (c != null) { 16926a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor try { 16936a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor if (c.moveToFirst()) { 16946a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor body = c.getString(SMS_BODY_INDEX); 16956a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor haveDraft = true; 16966a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor } 16976a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor } finally { 16986a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor c.close(); 1699b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1700b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1701b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 17026a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor // We found a draft, and if there are no messages in the conversation, 17036a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor // that means we deleted the thread, too. Must reset the thread id 17046a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor // so we'll eventually create a new thread. 17056a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor if (haveDraft && conv.getMessageCount() == 0) { 1706209ac103a11f5fb7aa3ebd266cf4ec74af42aa97Tom Taylor asyncDeleteDraftSmsMessage(conv); 1707209ac103a11f5fb7aa3ebd266cf4ec74af42aa97Tom Taylor 1708436042159134e8ecbc57097340a5bd81f2912574Tom Taylor // Clean out drafts for this thread -- if the recipient set changes, 1709436042159134e8ecbc57097340a5bd81f2912574Tom Taylor // we will lose track of the original draft and be unable to delete 1710436042159134e8ecbc57097340a5bd81f2912574Tom Taylor // it later. The message will be re-saved if necessary upon exit of 1711436042159134e8ecbc57097340a5bd81f2912574Tom Taylor // the activity. 1712df041b7b2d335c21947c7264b304b4b8d5a17080Tom Taylor clearConversation(conv, true); 17138c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor } 1714fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1715fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor LogTag.debug("readDraftSmsMessage haveDraft: ", !TextUtils.isEmpty(body)); 1716fcca7b38fcc90a781f1507a0a135a64e3ae8f6d8Tom Taylor } 17176a78e60e584cb440c63198b87f8aba6b4c07f8caTom Taylor 17188c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor return body; 17198c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor } 17208c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor 1721df041b7b2d335c21947c7264b304b4b8d5a17080Tom Taylor public void clearConversation(final Conversation conv, boolean resetThreadId) { 1722df041b7b2d335c21947c7264b304b4b8d5a17080Tom Taylor if (resetThreadId && conv.getMessageCount() == 0) { 17238c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor if (DEBUG) LogTag.debug("clearConversation calling clearThreadId"); 17248c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor conv.clearThreadId(); 172507ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor } 172607ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor 17278c9d1ba7193db210cf3930f8814b4a320f2d6188Tom Taylor conv.setDraftState(false); 1728b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 17291d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 17306fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen private void asyncUpdateDraftSmsMessage(final Conversation conv, final String contents, 17316fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen final boolean isStopping) { 1732b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick new Thread(new Runnable() { 1733ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev @Override 1734b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public void run() { 17355fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor try { 17365fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(true); 1737cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (conv.getRecipients().isEmpty()) { 1738cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1739cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor LogTag.debug("asyncUpdateDraftSmsMessage no recipients, not saving"); 1740cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 1741cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor return; 1742cdbd2dedafb1fe786ae9bf21ea0f8185b358172aTom Taylor } 17436fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen ensureThreadIdIfNeeded(conv, isStopping); 17445fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor conv.setDraftState(true); 17455fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor updateDraftSmsMessage(conv, contents); 17465fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } finally { 17475fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor DraftCache.getInstance().setSavingDraft(false); 17485fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor } 1749b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1750ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "WorkingMessage.asyncUpdateDraftSmsMessage").start(); 1751b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1752b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1753dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor private void updateDraftSmsMessage(final Conversation conv, String contents) { 1754dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor final long threadId = conv.getThreadId(); 1755d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1756dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor LogTag.debug("updateDraftSmsMessage tid=%d, contents=\"%s\"", threadId, contents); 1757d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor } 17581d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 1759b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick // If we don't have a valid thread, there's nothing to do. 1760dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor if (threadId <= 0) { 1761b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick return; 1762b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 17631d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick 176417688d9a397234f35ba5519e46135ea268ed6d89Ficus Kirkpatrick ContentValues values = new ContentValues(3); 1765dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor values.put(Sms.THREAD_ID, threadId); 176617688d9a397234f35ba5519e46135ea268ed6d89Ficus Kirkpatrick values.put(Sms.BODY, contents); 176717688d9a397234f35ba5519e46135ea268ed6d89Ficus Kirkpatrick values.put(Sms.TYPE, Sms.MESSAGE_TYPE_DRAFT); 176872ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SqliteWrapper.insert(mActivity, mContentResolver, Sms.CONTENT_URI, values); 1769dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor asyncDeleteDraftMmsMessage(conv); 1770bb576861100138c4180438ec82c31be0dce44fc8Tom Taylor mMessageUri = null; 1771b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1772b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1773b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void asyncDelete(final Uri uri, final String selection, final String[] selectionArgs) { 1774812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 1775d62ef06699b3ca5048c5642bd50300e9a2eb04a1Tom Taylor LogTag.debug("asyncDelete %s where %s", uri, selection); 1776812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang } 1777b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick new Thread(new Runnable() { 1778ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev @Override 1779b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick public void run() { 178072ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SqliteWrapper.delete(mActivity, mContentResolver, uri, selection, selectionArgs); 1781b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1782ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "WorkingMessage.asyncDelete").start(); 1783b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1784b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1785a6dd14dc0963aa8f30e625aa88e925e3fa0744f0Bai Tao public void asyncDeleteDraftSmsMessage(Conversation conv) { 1786dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor mHasSmsDraft = false; 1787dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor 1788dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor final long threadId = conv.getThreadId(); 1789b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick if (threadId > 0) { 1790b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick asyncDelete(ContentUris.withAppendedId(Sms.Conversations.CONTENT_URI, threadId), 1791b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SMS_DRAFT_WHERE, null); 1792b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1793b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1794b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1795b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick private void deleteDraftSmsMessage(long threadId) { 179672ab3ecfa3556866ee51b822f8ce5b1f2f117545Tom Taylor SqliteWrapper.delete(mActivity, mContentResolver, 1797b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick ContentUris.withAppendedId(Sms.Conversations.CONTENT_URI, threadId), 1798b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick SMS_DRAFT_WHERE, null); 1799b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 1800b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick 1801dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor private void asyncDeleteDraftMmsMessage(Conversation conv) { 1802dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor mHasMmsDraft = false; 1803dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor 1804dbb58454542a3f2a1da5379b889d0e3776881ae2Tom Taylor final long threadId = conv.getThreadId(); 18059b1488b9d20c5b79ddc0aa984bfd75844a0b0249Tom Taylor // If the thread id is < 1, then the thread_id in the pdu will be "" or NULL. We have 18069b1488b9d20c5b79ddc0aa984bfd75844a0b0249Tom Taylor // to clear those messages as well as ones with a valid thread id. 18079b1488b9d20c5b79ddc0aa984bfd75844a0b0249Tom Taylor final String where = Mms.THREAD_ID + (threadId > 0 ? " = " + threadId : " IS NULL"); 18089b1488b9d20c5b79ddc0aa984bfd75844a0b0249Tom Taylor asyncDelete(Mms.Draft.CONTENT_URI, where, null); 1809b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick } 18106fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen 18116fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen /** 18126fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen * Ensure the thread id in conversation if needed, when we try to save a draft with a orphaned 18136fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen * one. 18146fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen * @param conv The conversation we are in. 18156fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen * @param isStopping Whether we are saving the draft in CMA'a onStop 18166fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen */ 18176fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen private void ensureThreadIdIfNeeded(final Conversation conv, final boolean isStopping) { 18186fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen if (isStopping && conv.getMessageCount() == 0) { 18196fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // We need to save the drafts in an unorphaned thread id. When the user goes 18206fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // back to ConversationList while we're saving a draft from CMA's.onStop, 18216fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // ConversationList will delete all threads from the thread table that 18226fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // don't have associated sms or pdu entries. In case our thread got deleted, 18236fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // well call clearThreadId() so ensureThreadId will query the db for the new 18246fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen // thread. 18256fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen conv.clearThreadId(); // force us to get the updated thread id 18266fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen } 18276fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen if (!conv.getRecipients().isEmpty()) { 18286fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen conv.ensureThreadId(); 18296fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen } 18306fb06ef2242ee4167d2e9b9ee2a05bf46c124f19Roger Chen } 1831b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick} 1832