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 com.android.mms.LogTag; 21 import com.android.mms.ui.MessagingPreferenceActivity; 22 import com.android.mms.util.SendingProgressTokenManager; 23 import com.google.android.mms.InvalidHeaderValueException; 24 import com.google.android.mms.MmsException; 25 import com.google.android.mms.pdu.EncodedStringValue; 26 import com.google.android.mms.pdu.GenericPdu; 27 import com.google.android.mms.pdu.PduHeaders; 28 import com.google.android.mms.pdu.PduPersister; 29 import com.google.android.mms.pdu.ReadRecInd; 30 import com.google.android.mms.pdu.SendReq; 31 import com.google.android.mms.util.SqliteWrapper; 32 33 import android.content.ContentUris; 34 import android.content.ContentValues; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.SharedPreferences; 38 import android.net.Uri; 39 import android.preference.PreferenceManager; 40 import android.provider.Telephony.Mms; 41 import android.provider.Telephony.MmsSms; 42 import android.provider.Telephony.Sms; 43 import android.provider.Telephony.Mms.Addr; 44 import android.provider.Telephony.MmsSms.PendingMessages; 45 import android.util.Log; 46 47 public class MmsMessageSender implements MessageSender { 48 private static final String TAG = "MmsMessageSender"; 49 50 private final Context mContext; 51 private final Uri mMessageUri; 52 private final long mMessageSize; 53 54 // Default preference values 55 private static final boolean DEFAULT_DELIVERY_REPORT_MODE = false; 56 private static final boolean DEFAULT_READ_REPORT_MODE = false; 57 private static final long DEFAULT_EXPIRY_TIME = 7 * 24 * 60 * 60; 58 private static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL; 59 private static final String DEFAULT_MESSAGE_CLASS = PduHeaders.MESSAGE_CLASS_PERSONAL_STR; 60 61 public MmsMessageSender(Context context, Uri location, long messageSize) { 62 mContext = context; 63 mMessageUri = location; 64 mMessageSize = messageSize; 65 66 if (mMessageUri == null) { 67 throw new IllegalArgumentException("Null message URI."); 68 } 69 } 70 71 public boolean sendMessage(long token) throws MmsException { 72 // Load the MMS from the message uri 73 if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 74 LogTag.debug("sendMessage uri: " + mMessageUri); 75 } 76 PduPersister p = PduPersister.getPduPersister(mContext); 77 GenericPdu pdu = p.load(mMessageUri); 78 79 if (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_REQ) { 80 throw new MmsException("Invalid message: " + pdu.getMessageType()); 81 } 82 83 SendReq sendReq = (SendReq) pdu; 84 85 // Update headers. 86 updatePreferencesHeaders(sendReq); 87 88 // MessageClass. 89 sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes()); 90 91 // Update the 'date' field of the message before sending it. 92 sendReq.setDate(System.currentTimeMillis() / 1000L); 93 94 sendReq.setMessageSize(mMessageSize); 95 96 p.updateHeaders(mMessageUri, sendReq); 97 98 long messageId = ContentUris.parseId(mMessageUri); 99 100 // Move the message into MMS Outbox. 101 if (!mMessageUri.toString().startsWith(Mms.Draft.CONTENT_URI.toString())) { 102 // If the message is already in the outbox (most likely because we created a "primed" 103 // message in the outbox when the user hit send), then we have to manually put an 104 // entry in the pending_msgs table which is where TransacationService looks for 105 // messages to send. Normally, the entry in pending_msgs is created by the trigger: 106 // insert_mms_pending_on_update, when a message is moved from drafts to the outbox. 107 ContentValues values = new ContentValues(7); 108 109 values.put(PendingMessages.PROTO_TYPE, MmsSms.MMS_PROTO); 110 values.put(PendingMessages.MSG_ID, messageId); 111 values.put(PendingMessages.MSG_TYPE, pdu.getMessageType()); 112 values.put(PendingMessages.ERROR_TYPE, 0); 113 values.put(PendingMessages.ERROR_CODE, 0); 114 values.put(PendingMessages.RETRY_INDEX, 0); 115 values.put(PendingMessages.DUE_TIME, 0); 116 117 SqliteWrapper.insert(mContext, mContext.getContentResolver(), 118 PendingMessages.CONTENT_URI, values); 119 } else { 120 p.move(mMessageUri, Mms.Outbox.CONTENT_URI); 121 } 122 123 // Start MMS transaction service 124 SendingProgressTokenManager.put(messageId, token); 125 mContext.startService(new Intent(mContext, TransactionService.class)); 126 127 return true; 128 } 129 130 // Update the headers which are stored in SharedPreferences. 131 private void updatePreferencesHeaders(SendReq sendReq) throws MmsException { 132 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); 133 134 // Expiry. 135 sendReq.setExpiry(prefs.getLong( 136 MessagingPreferenceActivity.EXPIRY_TIME, DEFAULT_EXPIRY_TIME)); 137 138 // Priority. 139 sendReq.setPriority(prefs.getInt(MessagingPreferenceActivity.PRIORITY, DEFAULT_PRIORITY)); 140 141 // Delivery report. 142 boolean dr = prefs.getBoolean(MessagingPreferenceActivity.MMS_DELIVERY_REPORT_MODE, 143 DEFAULT_DELIVERY_REPORT_MODE); 144 sendReq.setDeliveryReport(dr?PduHeaders.VALUE_YES:PduHeaders.VALUE_NO); 145 146 // Read report. 147 boolean rr = prefs.getBoolean(MessagingPreferenceActivity.READ_REPORT_MODE, 148 DEFAULT_READ_REPORT_MODE); 149 sendReq.setReadReport(rr?PduHeaders.VALUE_YES:PduHeaders.VALUE_NO); 150 } 151 152 public static void sendReadRec(Context context, String to, String messageId, int status) { 153 EncodedStringValue[] sender = new EncodedStringValue[1]; 154 sender[0] = new EncodedStringValue(to); 155 156 try { 157 final ReadRecInd readRec = new ReadRecInd( 158 new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()), 159 messageId.getBytes(), 160 PduHeaders.CURRENT_MMS_VERSION, 161 status, 162 sender); 163 164 readRec.setDate(System.currentTimeMillis() / 1000); 165 166 PduPersister.getPduPersister(context).persist(readRec, Mms.Outbox.CONTENT_URI); 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