summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/datamodel/action/InsertNewMessageAction.java')
-rw-r--r--src/com/android/messaging/datamodel/action/InsertNewMessageAction.java480
1 files changed, 0 insertions, 480 deletions
diff --git a/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java b/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java
deleted file mode 100644
index 2567ca9..0000000
--- a/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.messaging.datamodel.action;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.Telephony;
-import android.text.TextUtils;
-
-import com.android.messaging.Factory;
-import com.android.messaging.datamodel.BugleDatabaseOperations;
-import com.android.messaging.datamodel.DataModel;
-import com.android.messaging.datamodel.DatabaseWrapper;
-import com.android.messaging.datamodel.MessagingContentProvider;
-import com.android.messaging.datamodel.SyncManager;
-import com.android.messaging.datamodel.data.ConversationListItemData;
-import com.android.messaging.datamodel.data.MessageData;
-import com.android.messaging.datamodel.data.MessagePartData;
-import com.android.messaging.datamodel.data.ParticipantData;
-import com.android.messaging.sms.MmsUtils;
-import com.android.messaging.util.Assert;
-import com.android.messaging.util.LogUtil;
-import com.android.messaging.util.OsUtil;
-import com.android.messaging.util.PhoneUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Action used to convert a draft message to an outgoing message. Its writes SMS messages to
- * the telephony db, but {@link SendMessageAction} is responsible for inserting MMS message into
- * the telephony DB. The latter also does the actual sending of the message in the background.
- * The latter is also responsible for re-sending a failed message.
- */
-public class InsertNewMessageAction extends Action implements Parcelable {
- private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
-
- private static long sLastSentMessageTimestamp = -1;
-
- /**
- * Insert message (no listener)
- */
- public static void insertNewMessage(final MessageData message) {
- final InsertNewMessageAction action = new InsertNewMessageAction(message);
- action.start();
- }
-
- /**
- * Insert message (no listener) with a given non-default subId.
- */
- public static void insertNewMessage(final MessageData message, final int subId) {
- Assert.isFalse(subId == ParticipantData.DEFAULT_SELF_SUB_ID);
- final InsertNewMessageAction action = new InsertNewMessageAction(message, subId);
- action.start();
- }
-
- /**
- * Insert message (no listener)
- */
- public static void insertNewMessage(final int subId, final String recipients,
- final String messageText, final String subject) {
- final InsertNewMessageAction action = new InsertNewMessageAction(
- subId, recipients, messageText, subject);
- action.start();
- }
-
- public static long getLastSentMessageTimestamp() {
- return sLastSentMessageTimestamp;
- }
-
- private static final String KEY_SUB_ID = "sub_id";
- private static final String KEY_MESSAGE = "message";
- private static final String KEY_RECIPIENTS = "recipients";
- private static final String KEY_MESSAGE_TEXT = "message_text";
- private static final String KEY_SUBJECT_TEXT = "subject_text";
-
- private InsertNewMessageAction(final MessageData message) {
- this(message, ParticipantData.DEFAULT_SELF_SUB_ID);
- actionParameters.putParcelable(KEY_MESSAGE, message);
- }
-
- private InsertNewMessageAction(final MessageData message, final int subId) {
- super();
- actionParameters.putParcelable(KEY_MESSAGE, message);
- actionParameters.putInt(KEY_SUB_ID, subId);
- }
-
- private InsertNewMessageAction(final int subId, final String recipients,
- final String messageText, final String subject) {
- super();
- if (TextUtils.isEmpty(recipients) || TextUtils.isEmpty(messageText)) {
- Assert.fail("InsertNewMessageAction: Can't have empty recipients or message");
- }
- actionParameters.putInt(KEY_SUB_ID, subId);
- actionParameters.putString(KEY_RECIPIENTS, recipients);
- actionParameters.putString(KEY_MESSAGE_TEXT, messageText);
- actionParameters.putString(KEY_SUBJECT_TEXT, subject);
- }
-
- /**
- * Add message to database in pending state and queue actual sending
- */
- @Override
- protected Object executeAction() {
- LogUtil.i(TAG, "InsertNewMessageAction: inserting new message");
- MessageData message = actionParameters.getParcelable(KEY_MESSAGE);
- if (message == null) {
- LogUtil.i(TAG, "InsertNewMessageAction: Creating MessageData with provided data");
- message = createMessage();
- if (message == null) {
- LogUtil.w(TAG, "InsertNewMessageAction: Could not create MessageData");
- return null;
- }
- }
- final DatabaseWrapper db = DataModel.get().getDatabase();
- final String conversationId = message.getConversationId();
-
- final ParticipantData self = getSelf(db, conversationId, message);
- if (self == null) {
- return null;
- }
- message.bindSelfId(self.getId());
- // If the user taps the Send button before the conversation draft is created/loaded by
- // ReadDraftDataAction (maybe the action service thread was busy), the MessageData may not
- // have the participant id set. It should be equal to the self id, so we'll use that.
- if (message.getParticipantId() == null) {
- message.bindParticipantId(self.getId());
- }
-
- final long timestamp = System.currentTimeMillis();
- final ArrayList<String> recipients =
- BugleDatabaseOperations.getRecipientsForConversation(db, conversationId);
- if (recipients.size() < 1) {
- LogUtil.w(TAG, "InsertNewMessageAction: message recipients is empty");
- return null;
- }
- final int subId = self.getSubId();
-
- // TODO: Work out whether to send with SMS or MMS (taking into account recipients)?
- final boolean isSms = (message.getProtocol() == MessageData.PROTOCOL_SMS);
- if (isSms) {
- String sendingConversationId = conversationId;
- if (recipients.size() > 1) {
- // Broadcast SMS - put message in "fake conversation" before farming out to real 1:1
- final long laterTimestamp = timestamp + 1;
- // Send a single message
- insertBroadcastSmsMessage(conversationId, message, subId,
- laterTimestamp, recipients);
-
- sendingConversationId = null;
- }
-
- for (final String recipient : recipients) {
- // Start actual sending
- insertSendingSmsMessage(message, subId, recipient,
- timestamp, sendingConversationId);
- }
-
- // Can now clear draft from conversation (deleting attachments if necessary)
- BugleDatabaseOperations.updateDraftMessageData(db, conversationId,
- null /* message */, BugleDatabaseOperations.UPDATE_MODE_CLEAR_DRAFT);
- } else {
- final long timestampRoundedToSecond = 1000 * ((timestamp + 500) / 1000);
- // Write place holder message directly referencing parts from the draft
- final MessageData messageToSend = insertSendingMmsMessage(conversationId,
- message, timestampRoundedToSecond);
-
- // Can now clear draft from conversation (preserving attachments which are now
- // referenced by messageToSend)
- BugleDatabaseOperations.updateDraftMessageData(db, conversationId,
- messageToSend, BugleDatabaseOperations.UPDATE_MODE_CLEAR_DRAFT);
- }
- MessagingContentProvider.notifyConversationListChanged();
- ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
-
- return message;
- }
-
- private ParticipantData getSelf(
- final DatabaseWrapper db, final String conversationId, final MessageData message) {
- ParticipantData self;
- // Check if we are asked to bind to a non-default subId. This is directly passed in from
- // the UI thread so that the sub id may be locked as soon as the user clicks on the Send
- // button.
- final int requestedSubId = actionParameters.getInt(
- KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
- if (requestedSubId != ParticipantData.DEFAULT_SELF_SUB_ID) {
- self = BugleDatabaseOperations.getOrCreateSelf(db, requestedSubId);
- } else {
- String selfId = message.getSelfId();
- if (selfId == null) {
- // The conversation draft provides no self id hint, meaning that 1) conversation
- // self id was not loaded AND 2) the user didn't pick a SIM from the SIM selector.
- // In this case, use the conversation's self id.
- final ConversationListItemData conversation =
- ConversationListItemData.getExistingConversation(db, conversationId);
- if (conversation != null) {
- selfId = conversation.getSelfId();
- } else {
- LogUtil.w(LogUtil.BUGLE_DATAMODEL_TAG, "Conversation " + conversationId +
- "already deleted before sending draft message " +
- message.getMessageId() + ". Aborting InsertNewMessageAction.");
- return null;
- }
- }
-
- // We do not use SubscriptionManager.DEFAULT_SUB_ID for sending a message, so we need
- // to bind the message to the system default subscription if it's unbound.
- final ParticipantData unboundSelf = BugleDatabaseOperations.getExistingParticipant(
- db, selfId);
- if (unboundSelf.getSubId() == ParticipantData.DEFAULT_SELF_SUB_ID
- && OsUtil.isAtLeastL_MR1()) {
- final int defaultSubId = PhoneUtils.getDefault().getDefaultSmsSubscriptionId();
- self = BugleDatabaseOperations.getOrCreateSelf(db, defaultSubId);
- } else {
- self = unboundSelf;
- }
- }
- return self;
- }
-
- /** Create MessageData using KEY_RECIPIENTS, KEY_MESSAGE_TEXT and KEY_SUBJECT */
- private MessageData createMessage() {
- // First find the thread id for this list of participants.
- final String recipientsList = actionParameters.getString(KEY_RECIPIENTS);
- final String messageText = actionParameters.getString(KEY_MESSAGE_TEXT);
- final String subjectText = actionParameters.getString(KEY_SUBJECT_TEXT);
- final int subId = actionParameters.getInt(
- KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
-
- final ArrayList<ParticipantData> participants = new ArrayList<>();
- for (final String recipient : recipientsList.split(",")) {
- participants.add(ParticipantData.getFromRawPhoneBySimLocale(recipient, subId));
- }
- if (participants.size() == 0) {
- Assert.fail("InsertNewMessage: Empty participants");
- return null;
- }
-
- final DatabaseWrapper db = DataModel.get().getDatabase();
- BugleDatabaseOperations.sanitizeConversationParticipants(participants);
- final ArrayList<String> recipients =
- BugleDatabaseOperations.getRecipientsFromConversationParticipants(participants);
- if (recipients.size() == 0) {
- Assert.fail("InsertNewMessage: Empty recipients");
- return null;
- }
-
- final long threadId = MmsUtils.getOrCreateThreadId(Factory.get().getApplicationContext(),
- recipients);
-
- if (threadId < 0) {
- Assert.fail("InsertNewMessage: Couldn't get threadId in SMS db for these recipients: "
- + recipients.toString());
- // TODO: How do we fail the action?
- return null;
- }
-
- final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
- false, participants, false, false, null);
-
- final ParticipantData self = BugleDatabaseOperations.getOrCreateSelf(db, subId);
-
- if (TextUtils.isEmpty(subjectText)) {
- return MessageData.createDraftSmsMessage(conversationId, self.getId(), messageText);
- } else {
- return MessageData.createDraftMmsMessage(conversationId, self.getId(), messageText,
- subjectText);
- }
- }
-
- private void insertBroadcastSmsMessage(final String conversationId,
- final MessageData message, final int subId, final long laterTimestamp,
- final ArrayList<String> recipients) {
- if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
- LogUtil.v(TAG, "InsertNewMessageAction: Inserting broadcast SMS message "
- + message.getMessageId());
- }
- final Context context = Factory.get().getApplicationContext();
- final DatabaseWrapper db = DataModel.get().getDatabase();
-
- // Inform sync that message is being added at timestamp
- final SyncManager syncManager = DataModel.get().getSyncManager();
- syncManager.onNewMessageInserted(laterTimestamp);
-
- final long threadId = BugleDatabaseOperations.getThreadId(db, conversationId);
- final String address = TextUtils.join(" ", recipients);
-
- final String messageText = message.getMessageText();
- // Insert message into telephony database sms message table
- final Uri messageUri = MmsUtils.insertSmsMessage(context,
- Telephony.Sms.CONTENT_URI,
- subId,
- address,
- messageText,
- laterTimestamp,
- Telephony.Sms.STATUS_COMPLETE,
- Telephony.Sms.MESSAGE_TYPE_SENT, threadId);
- if (messageUri != null && !TextUtils.isEmpty(messageUri.toString())) {
- db.beginTransaction();
- try {
- message.updateSendingMessage(conversationId, messageUri, laterTimestamp);
- message.markMessageSent(laterTimestamp);
-
- BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
-
- BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
- conversationId, message.getMessageId(), laterTimestamp,
- false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
-
- if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
- LogUtil.d(TAG, "InsertNewMessageAction: Inserted broadcast SMS message "
- + message.getMessageId() + ", uri = " + message.getSmsMessageUri());
- }
- MessagingContentProvider.notifyMessagesChanged(conversationId);
- MessagingContentProvider.notifyPartsChanged();
- } else {
- // Ignore error as we only really care about the individual messages?
- LogUtil.e(TAG,
- "InsertNewMessageAction: No uri for broadcast SMS " + message.getMessageId()
- + " inserted into telephony DB");
- }
- }
-
- /**
- * Insert SMS messaging into our database and telephony db.
- */
- private MessageData insertSendingSmsMessage(final MessageData content, final int subId,
- final String recipient, final long timestamp, final String sendingConversationId) {
- sLastSentMessageTimestamp = timestamp;
-
- final Context context = Factory.get().getApplicationContext();
-
- // Inform sync that message is being added at timestamp
- final SyncManager syncManager = DataModel.get().getSyncManager();
- syncManager.onNewMessageInserted(timestamp);
-
- final DatabaseWrapper db = DataModel.get().getDatabase();
-
- // Send a single message
- long threadId;
- String conversationId;
- if (sendingConversationId == null) {
- // For 1:1 message generated sending broadcast need to look up threadId+conversationId
- threadId = MmsUtils.getOrCreateSmsThreadId(context, recipient);
- conversationId = BugleDatabaseOperations.getOrCreateConversationFromRecipient(
- db, threadId, false /* sender blocked */,
- ParticipantData.getFromRawPhoneBySimLocale(recipient, subId));
- } else {
- // Otherwise just look up threadId
- threadId = BugleDatabaseOperations.getThreadId(db, sendingConversationId);
- conversationId = sendingConversationId;
- }
-
- final String messageText = content.getMessageText();
-
- // Insert message into telephony database sms message table
- final Uri messageUri = MmsUtils.insertSmsMessage(context,
- Telephony.Sms.CONTENT_URI,
- subId,
- recipient,
- messageText,
- timestamp,
- Telephony.Sms.STATUS_NONE,
- Telephony.Sms.MESSAGE_TYPE_SENT, threadId);
-
- MessageData message = null;
- if (messageUri != null && !TextUtils.isEmpty(messageUri.toString())) {
- db.beginTransaction();
- try {
- message = MessageData.createDraftSmsMessage(conversationId,
- content.getSelfId(), messageText);
- message.updateSendingMessage(conversationId, messageUri, timestamp);
-
- BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
-
- // Do not update the conversation summary to reflect autogenerated 1:1 messages
- if (sendingConversationId != null) {
- BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
- conversationId, message.getMessageId(), timestamp,
- false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
-
- if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
- LogUtil.d(TAG, "InsertNewMessageAction: Inserted SMS message "
- + message.getMessageId() + " (uri = " + message.getSmsMessageUri()
- + ", timestamp = " + message.getReceivedTimeStamp() + ")");
- }
- MessagingContentProvider.notifyMessagesChanged(conversationId);
- MessagingContentProvider.notifyPartsChanged();
- } else {
- LogUtil.e(TAG, "InsertNewMessageAction: No uri for SMS inserted into telephony DB");
- }
-
- return message;
- }
-
- /**
- * Insert MMS messaging into our database.
- */
- private MessageData insertSendingMmsMessage(final String conversationId,
- final MessageData message, final long timestamp) {
- final DatabaseWrapper db = DataModel.get().getDatabase();
- db.beginTransaction();
- final List<MessagePartData> attachmentsUpdated = new ArrayList<>();
- try {
- sLastSentMessageTimestamp = timestamp;
-
- // Insert "draft" message as placeholder until the final message is written to
- // the telephony db
- message.updateSendingMessage(conversationId, null/*messageUri*/, timestamp);
-
- // No need to inform SyncManager as message currently has no Uri...
- BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
-
- BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
- conversationId, message.getMessageId(), timestamp,
- false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
-
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
-
- if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
- LogUtil.d(TAG, "InsertNewMessageAction: Inserted MMS message "
- + message.getMessageId() + " (timestamp = " + timestamp + ")");
- }
- MessagingContentProvider.notifyMessagesChanged(conversationId);
- MessagingContentProvider.notifyPartsChanged();
-
- return message;
- }
-
- private InsertNewMessageAction(final Parcel in) {
- super(in);
- }
-
- public static final Parcelable.Creator<InsertNewMessageAction> CREATOR
- = new Parcelable.Creator<InsertNewMessageAction>() {
- @Override
- public InsertNewMessageAction createFromParcel(final Parcel in) {
- return new InsertNewMessageAction(in);
- }
-
- @Override
- public InsertNewMessageAction[] newArray(final int size) {
- return new InsertNewMessageAction[size];
- }
- };
-
- @Override
- public void writeToParcel(final Parcel parcel, final int flags) {
- writeActionToParcel(parcel, flags);
- }
-}