Home | History | Annotate | Download | only in cdma
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.cdma;
     18 
     19 import android.app.Activity;
     20 import android.app.PendingIntent;
     21 import android.app.PendingIntent.CanceledException;
     22 import android.content.Intent;
     23 import android.os.Message;
     24 import android.os.SystemProperties;
     25 import android.provider.Telephony.Sms;
     26 import android.telephony.Rlog;
     27 import android.telephony.SmsManager;
     28 
     29 import com.android.internal.telephony.GsmAlphabet;
     30 import com.android.internal.telephony.ImsSMSDispatcher;
     31 import com.android.internal.telephony.PhoneBase;
     32 import com.android.internal.telephony.SMSDispatcher;
     33 import com.android.internal.telephony.SmsConstants;
     34 import com.android.internal.telephony.SmsHeader;
     35 import com.android.internal.telephony.SmsUsageMonitor;
     36 import com.android.internal.telephony.TelephonyProperties;
     37 import com.android.internal.telephony.cdma.sms.UserData;
     38 
     39 import java.util.HashMap;
     40 
     41 public class CdmaSMSDispatcher extends SMSDispatcher {
     42     private static final String TAG = "CdmaSMSDispatcher";
     43     private static final boolean VDBG = false;
     44 
     45     public CdmaSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
     46             ImsSMSDispatcher imsSMSDispatcher) {
     47         super(phone, usageMonitor, imsSMSDispatcher);
     48         Rlog.d(TAG, "CdmaSMSDispatcher created");
     49     }
     50 
     51     @Override
     52     protected String getFormat() {
     53         return SmsConstants.FORMAT_3GPP2;
     54     }
     55 
     56     /**
     57      * Send the SMS status report to the dispatcher thread to process.
     58      * @param sms the CDMA SMS message containing the status report
     59      */
     60     void sendStatusReportMessage(SmsMessage sms) {
     61         if (VDBG) Rlog.d(TAG, "sending EVENT_HANDLE_STATUS_REPORT message");
     62         sendMessage(obtainMessage(EVENT_HANDLE_STATUS_REPORT, sms));
     63     }
     64 
     65     @Override
     66     protected void handleStatusReport(Object o) {
     67         if (o instanceof SmsMessage) {
     68             if (VDBG) Rlog.d(TAG, "calling handleCdmaStatusReport()");
     69             handleCdmaStatusReport((SmsMessage) o);
     70         } else {
     71             Rlog.e(TAG, "handleStatusReport() called for object type " + o.getClass().getName());
     72         }
     73     }
     74 
     75     /**
     76      * Called from parent class to handle status report from {@code CdmaInboundSmsHandler}.
     77      * @param sms the CDMA SMS message to process
     78      */
     79     void handleCdmaStatusReport(SmsMessage sms) {
     80         for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
     81             SmsTracker tracker = deliveryPendingList.get(i);
     82             if (tracker.mMessageRef == sms.mMessageRef) {
     83                 // Found it.  Remove from list and broadcast.
     84                 deliveryPendingList.remove(i);
     85                 // Update the message status (COMPLETE)
     86                 tracker.updateSentMessageStatus(mContext, Sms.STATUS_COMPLETE);
     87 
     88                 PendingIntent intent = tracker.mDeliveryIntent;
     89                 Intent fillIn = new Intent();
     90                 fillIn.putExtra("pdu", sms.getPdu());
     91                 fillIn.putExtra("format", getFormat());
     92                 try {
     93                     intent.send(mContext, Activity.RESULT_OK, fillIn);
     94                 } catch (CanceledException ex) {}
     95                 break;  // Only expect to see one tracker matching this message.
     96             }
     97         }
     98     }
     99 
    100     /** {@inheritDoc} */
    101     @Override
    102     protected void sendData(String destAddr, String scAddr, int destPort,
    103             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
    104         SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
    105                 scAddr, destAddr, destPort, data, (deliveryIntent != null));
    106         HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
    107         SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
    108                 getFormat());
    109         sendSubmitPdu(tracker);
    110     }
    111 
    112     /** {@inheritDoc} */
    113     @Override
    114     protected void sendText(String destAddr, String scAddr, String text,
    115             PendingIntent sentIntent, PendingIntent deliveryIntent) {
    116         SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
    117                 scAddr, destAddr, text, (deliveryIntent != null), null);
    118         HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
    119         SmsTracker tracker = getSmsTracker(map, sentIntent,
    120                 deliveryIntent, getFormat());
    121         sendSubmitPdu(tracker);
    122     }
    123 
    124     /** {@inheritDoc} */
    125     @Override
    126     protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
    127             boolean use7bitOnly) {
    128         return SmsMessage.calculateLength(messageBody, use7bitOnly);
    129     }
    130 
    131     /** {@inheritDoc} */
    132     @Override
    133     protected void sendNewSubmitPdu(String destinationAddress, String scAddress,
    134             String message, SmsHeader smsHeader, int encoding,
    135             PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) {
    136         UserData uData = new UserData();
    137         uData.payloadStr = message;
    138         uData.userDataHeader = smsHeader;
    139         if (encoding == SmsConstants.ENCODING_7BIT) {
    140             uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
    141         } else { // assume UTF-16
    142             uData.msgEncoding = UserData.ENCODING_UNICODE_16;
    143         }
    144         uData.msgEncodingSet = true;
    145 
    146         /* By setting the statusReportRequested bit only for the
    147          * last message fragment, this will result in only one
    148          * callback to the sender when that last fragment delivery
    149          * has been acknowledged. */
    150         SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress,
    151                 uData, (deliveryIntent != null) && lastPart);
    152 
    153         HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
    154                 message, submitPdu);
    155         SmsTracker tracker = getSmsTracker(map, sentIntent,
    156                 deliveryIntent, getFormat());
    157         sendSubmitPdu(tracker);
    158     }
    159 
    160     protected void sendSubmitPdu(SmsTracker tracker) {
    161         if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
    162             if (tracker.mSentIntent != null) {
    163                 try {
    164                     tracker.mSentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
    165                 } catch (CanceledException ex) {}
    166             }
    167             if (VDBG) {
    168                 Rlog.d(TAG, "Block SMS in Emergency Callback mode");
    169             }
    170             return;
    171         }
    172         sendRawPdu(tracker);
    173     }
    174 
    175     /** {@inheritDoc} */
    176     @Override
    177     protected void sendSms(SmsTracker tracker) {
    178         HashMap<String, Object> map = tracker.mData;
    179 
    180         // byte[] smsc = (byte[]) map.get("smsc");  // unused for CDMA
    181         byte[] pdu = (byte[]) map.get("pdu");
    182 
    183         Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
    184 
    185         Rlog.d(TAG, "sendSms: "
    186                 +" isIms()="+isIms()
    187                 +" mRetryCount="+tracker.mRetryCount
    188                 +" mImsRetry="+tracker.mImsRetry
    189                 +" mMessageRef="+tracker.mMessageRef
    190                 +" SS=" +mPhone.getServiceState().getState());
    191 
    192         // sms over cdma is used:
    193         //   if sms over IMS is not supported AND
    194         //   this is not a retry case after sms over IMS failed
    195         //     indicated by mImsRetry > 0
    196         if (0 == tracker.mImsRetry && !isIms()) {
    197             mCi.sendCdmaSms(pdu, reply);
    198         } else {
    199             mCi.sendImsCdmaSms(pdu, tracker.mImsRetry, tracker.mMessageRef, reply);
    200             // increment it here, so in case of SMS_FAIL_RETRY over IMS
    201             // next retry will be sent using IMS request again.
    202             tracker.mImsRetry++;
    203         }
    204     }
    205 }
    206