• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Context;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.database.Cursor;
24 import android.database.sqlite.SQLiteException;
25 import android.database.sqlite.SqliteWrapper;
26 import android.net.Uri;
27 import android.preference.PreferenceManager;
28 import android.provider.Telephony.Sms;
29 import android.provider.Telephony.Sms.Inbox;
30 import android.util.Log;
31 
32 import com.android.mms.LogTag;
33 import com.android.mms.ui.MessagingPreferenceActivity;
34 import com.google.android.mms.MmsException;
35 
36 public class SmsMessageSender implements MessageSender {
37     protected final Context mContext;
38     protected final int mNumberOfDests;
39     private final String[] mDests;
40     protected final String mMessageText;
41     protected final String mServiceCenter;
42     protected final long mThreadId;
43     protected long mTimestamp;
44     private static final String TAG = "SmsMessageSender";
45 
46     // Default preference values
47     private static final boolean DEFAULT_DELIVERY_REPORT_MODE  = false;
48 
49     private static final String[] SERVICE_CENTER_PROJECTION = new String[] {
50         Sms.Conversations.REPLY_PATH_PRESENT,
51         Sms.Conversations.SERVICE_CENTER,
52     };
53 
54     private static final int COLUMN_REPLY_PATH_PRESENT = 0;
55     private static final int COLUMN_SERVICE_CENTER     = 1;
56 
SmsMessageSender(Context context, String[] dests, String msgText, long threadId)57     public SmsMessageSender(Context context, String[] dests, String msgText, long threadId) {
58         mContext = context;
59         mMessageText = msgText;
60         if (dests != null) {
61             mNumberOfDests = dests.length;
62             mDests = new String[mNumberOfDests];
63             System.arraycopy(dests, 0, mDests, 0, mNumberOfDests);
64         } else {
65             mNumberOfDests = 0;
66             mDests = null;
67         }
68         mTimestamp = System.currentTimeMillis();
69         mThreadId = threadId;
70         mServiceCenter = getOutgoingServiceCenter(mThreadId);
71     }
72 
sendMessage(long token)73     public boolean sendMessage(long token) throws MmsException {
74         // In order to send the message one by one, instead of sending now, the message will split,
75         // and be put into the queue along with each destinations
76         return queueMessage(token);
77     }
78 
queueMessage(long token)79     private boolean queueMessage(long token) throws MmsException {
80         if ((mMessageText == null) || (mNumberOfDests == 0)) {
81             // Don't try to send an empty message.
82             throw new MmsException("Null message body or dest.");
83         }
84 
85         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
86         boolean requestDeliveryReport = prefs.getBoolean(
87                 MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE,
88                 DEFAULT_DELIVERY_REPORT_MODE);
89 
90         for (int i = 0; i < mNumberOfDests; i++) {
91             try {
92                 if (LogTag.DEBUG_SEND) {
93                     Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId);
94                 }
95                 Sms.addMessageToUri(mContext.getContentResolver(),
96                         Uri.parse("content://sms/queued"), mDests[i],
97                         mMessageText, null, mTimestamp,
98                         true /* read */,
99                         requestDeliveryReport,
100                         mThreadId);
101             } catch (SQLiteException e) {
102                 if (LogTag.DEBUG_SEND) {
103                     Log.e(TAG, "queueMessage SQLiteException", e);
104                 }
105                 SqliteWrapper.checkSQLiteException(mContext, e);
106             }
107         }
108         // Notify the SmsReceiverService to send the message out
109         mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
110                 null,
111                 mContext,
112                 SmsReceiver.class));
113         return false;
114     }
115 
116     /**
117      * Get the service center to use for a reply.
118      *
119      * The rule from TS 23.040 D.6 is that we send reply messages to
120      * the service center of the message to which we're replying, but
121      * only if we haven't already replied to that message and only if
122      * <code>TP-Reply-Path</code> was set in that message.
123      *
124      * Therefore, return the service center from the most recent
125      * message in the conversation, but only if it is a message from
126      * the other party, and only if <code>TP-Reply-Path</code> is set.
127      * Otherwise, return null.
128      */
getOutgoingServiceCenter(long threadId)129     private String getOutgoingServiceCenter(long threadId) {
130         Cursor cursor = null;
131 
132         try {
133             cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
134                             Inbox.CONTENT_URI, SERVICE_CENTER_PROJECTION,
135                             "thread_id = " + threadId, null, "date DESC");
136 
137             if ((cursor == null) || !cursor.moveToFirst()) {
138                 return null;
139             }
140 
141             boolean replyPathPresent = (1 == cursor.getInt(COLUMN_REPLY_PATH_PRESENT));
142             return replyPathPresent ? cursor.getString(COLUMN_SERVICE_CENTER) : null;
143         } finally {
144             if (cursor != null) {
145                 cursor.close();
146             }
147         }
148     }
149 
log(String msg)150     private void log(String msg) {
151         Log.d(LogTag.TAG, "[SmsMsgSender] " + msg);
152     }
153 }
154