1 /* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mms.transaction; 19 20 import android.content.ContentUris; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.SharedPreferences; 25 import android.net.Uri; 26 import android.preference.PreferenceManager; 27 import android.provider.Telephony.Mms; 28 import android.provider.Telephony.MmsSms; 29 import android.provider.Telephony.MmsSms.PendingMessages; 30 import android.util.Log; 31 32 import com.android.mms.LogTag; 33 import com.android.mms.ui.ComposeMessageActivity; 34 import com.android.mms.ui.MessagingPreferenceActivity; 35 import com.android.mms.util.SendingProgressTokenManager; 36 import com.google.android.mms.InvalidHeaderValueException; 37 import com.google.android.mms.MmsException; 38 import com.google.android.mms.pdu.EncodedStringValue; 39 import com.google.android.mms.pdu.GenericPdu; 40 import com.google.android.mms.pdu.PduHeaders; 41 import com.google.android.mms.pdu.PduPersister; 42 import com.google.android.mms.pdu.ReadRecInd; 43 import com.google.android.mms.pdu.SendReq; 44 import com.google.android.mms.util.SqliteWrapper; 45 46 public class MmsMessageSender implements MessageSender { 47 private static final String TAG = "MmsMessageSender"; 48 49 private final Context mContext; 50 private final Uri mMessageUri; 51 private final long mMessageSize; 52 53 // Default preference values 54 private static final boolean DEFAULT_DELIVERY_REPORT_MODE = false; 55 private static final boolean DEFAULT_READ_REPORT_MODE = false; 56 private static final long DEFAULT_EXPIRY_TIME = 7 * 24 * 60 * 60; 57 private static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL; 58 private static final String DEFAULT_MESSAGE_CLASS = PduHeaders.MESSAGE_CLASS_PERSONAL_STR; 59 60 public MmsMessageSender(Context context, Uri location, long messageSize) { 61 mContext = context; 62 mMessageUri = location; 63 mMessageSize = messageSize; 64 65 if (mMessageUri == null) { 66 throw new IllegalArgumentException("Null message URI."); 67 } 68 } 69 70 public boolean sendMessage(long token) throws MmsException { 71 // Load the MMS from the message uri 72 if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 73 LogTag.debug("sendMessage uri: " + mMessageUri); 74 } 75 PduPersister p = PduPersister.getPduPersister(mContext); 76 GenericPdu pdu = p.load(mMessageUri); 77 78 if (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_REQ) { 79 throw new MmsException("Invalid message: " + pdu.getMessageType()); 80 } 81 82 SendReq sendReq = (SendReq) pdu; 83 84 // Update headers. 85 updatePreferencesHeaders(sendReq); 86 87 // MessageClass. 88 sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes()); 89 90 // Update the 'date' field of the message before sending it. 91 sendReq.setDate(System.currentTimeMillis() / 1000L); 92 93 sendReq.setMessageSize(mMessageSize); 94 95 p.updateHeaders(mMessageUri, sendReq); 96 97 long messageId = ContentUris.parseId(mMessageUri); 98 99 // Move the message into MMS Outbox. 100 if (!mMessageUri.toString().startsWith(Mms.Draft.CONTENT_URI.toString())) { 101 // If the message is already in the outbox (most likely because we created a "primed" 102 // message in the outbox when the user hit send), then we have to manually put an 103 // entry in the pending_msgs table which is where TransacationService looks for 104 // messages to send. Normally, the entry in pending_msgs is created by the trigger: 105 // insert_mms_pending_on_update, when a message is moved from drafts to the outbox. 106 ContentValues values = new ContentValues(7); 107 108 values.put(PendingMessages.PROTO_TYPE, MmsSms.MMS_PROTO); 109 values.put(PendingMessages.MSG_ID, messageId); 110 values.put(PendingMessages.MSG_TYPE, pdu.getMessageType()); 111 values.put(PendingMessages.ERROR_TYPE, 0); 112 values.put(PendingMessages.ERROR_CODE, 0); 113 values.put(PendingMessages.RETRY_INDEX, 0); 114 values.put(PendingMessages.DUE_TIME, 0); 115 116 SqliteWrapper.insert(mContext, mContext.getContentResolver(), 117 PendingMessages.CONTENT_URI, values); 118 } else { 119 p.move(mMessageUri, Mms.Outbox.CONTENT_URI); 120 } 121 122 // Start MMS transaction service 123 SendingProgressTokenManager.put(messageId, token); 124 mContext.startService(new Intent(mContext, TransactionService.class)); 125 126 return true; 127 } 128 129 // Update the headers which are stored in SharedPreferences. 130 private void updatePreferencesHeaders(SendReq sendReq) throws MmsException { 131 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); 132 133 // Expiry. 134 sendReq.setExpiry(prefs.getLong( 135 MessagingPreferenceActivity.EXPIRY_TIME, DEFAULT_EXPIRY_TIME)); 136 137 // Priority. 138 sendReq.setPriority(prefs.getInt(MessagingPreferenceActivity.PRIORITY, DEFAULT_PRIORITY)); 139 140 // Delivery report. 141 boolean dr = prefs.getBoolean(MessagingPreferenceActivity.MMS_DELIVERY_REPORT_MODE, 142 DEFAULT_DELIVERY_REPORT_MODE); 143 sendReq.setDeliveryReport(dr?PduHeaders.VALUE_YES:PduHeaders.VALUE_NO); 144 145 // Read report. 146 boolean rr = prefs.getBoolean(MessagingPreferenceActivity.READ_REPORT_MODE, 147 DEFAULT_READ_REPORT_MODE); 148 sendReq.setReadReport(rr?PduHeaders.VALUE_YES:PduHeaders.VALUE_NO); 149 } 150 151 public static void sendReadRec(Context context, String to, String messageId, int status) { 152 EncodedStringValue[] sender = new EncodedStringValue[1]; 153 sender[0] = new EncodedStringValue(to); 154 155 try { 156 final ReadRecInd readRec = new ReadRecInd( 157 new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()), 158 messageId.getBytes(), 159 PduHeaders.CURRENT_MMS_VERSION, 160 status, 161 sender); 162 163 readRec.setDate(System.currentTimeMillis() / 1000); 164 165 PduPersister.getPduPersister(context).persist(readRec, Mms.Outbox.CONTENT_URI, true, 166 MessagingPreferenceActivity.getIsGroupMmsEnabled(context), null); 167 context.startService(new Intent(context, TransactionService.class)); 168 } catch (InvalidHeaderValueException e) { 169 Log.e(TAG, "Invalide header value", e); 170 } catch (MmsException e) { 171 Log.e(TAG, "Persist message failed", e); 172 } 173 } 174 } 175