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