Home | History | Annotate | Download | only in transaction
      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 
     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 
     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 
     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      */
    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 
    150     private void log(String msg) {
    151         Log.d(LogTag.TAG, "[SmsMsgSender] " + msg);
    152     }
    153 }
    154