CdmaSMSDispatcher.java revision 63418bbd2a9d7cc88ae24cc5ae776c01d688fc3a
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 17package com.android.internal.telephony.cdma; 18 19import android.app.Activity; 20import android.app.PendingIntent; 21import android.app.PendingIntent.CanceledException; 22import android.content.Intent; 23import android.os.Message; 24import android.os.SystemProperties; 25import android.provider.Telephony.Sms; 26import android.telephony.Rlog; 27import android.telephony.SmsManager; 28 29import com.android.internal.telephony.GsmAlphabet; 30import com.android.internal.telephony.ImsSMSDispatcher; 31import com.android.internal.telephony.PhoneBase; 32import com.android.internal.telephony.SMSDispatcher; 33import com.android.internal.telephony.SmsConstants; 34import com.android.internal.telephony.SmsHeader; 35import com.android.internal.telephony.SmsUsageMonitor; 36import com.android.internal.telephony.TelephonyProperties; 37import com.android.internal.telephony.cdma.sms.UserData; 38 39import java.util.HashMap; 40 41public 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 void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) { 127 throw new IllegalStateException("This method must be called only on ImsSMSDispatcher"); 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody, 133 boolean use7bitOnly) { 134 return SmsMessage.calculateLength(messageBody, use7bitOnly); 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 protected void sendNewSubmitPdu(String destinationAddress, String scAddress, 140 String message, SmsHeader smsHeader, int encoding, 141 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) { 142 UserData uData = new UserData(); 143 uData.payloadStr = message; 144 uData.userDataHeader = smsHeader; 145 if (encoding == SmsConstants.ENCODING_7BIT) { 146 uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET; 147 } else { // assume UTF-16 148 uData.msgEncoding = UserData.ENCODING_UNICODE_16; 149 } 150 uData.msgEncodingSet = true; 151 152 /* By setting the statusReportRequested bit only for the 153 * last message fragment, this will result in only one 154 * callback to the sender when that last fragment delivery 155 * has been acknowledged. */ 156 SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress, 157 uData, (deliveryIntent != null) && lastPart); 158 159 HashMap map = getSmsTrackerMap(destinationAddress, scAddress, 160 message, submitPdu); 161 SmsTracker tracker = getSmsTracker(map, sentIntent, 162 deliveryIntent, getFormat()); 163 sendSubmitPdu(tracker); 164 } 165 166 protected void sendSubmitPdu(SmsTracker tracker) { 167 if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) { 168 if (tracker.mSentIntent != null) { 169 try { 170 tracker.mSentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE); 171 } catch (CanceledException ex) {} 172 } 173 if (VDBG) { 174 Rlog.d(TAG, "Block SMS in Emergency Callback mode"); 175 } 176 return; 177 } 178 sendRawPdu(tracker); 179 } 180 181 /** {@inheritDoc} */ 182 @Override 183 protected void sendSms(SmsTracker tracker) { 184 HashMap<String, Object> map = tracker.mData; 185 186 // byte[] smsc = (byte[]) map.get("smsc"); // unused for CDMA 187 byte[] pdu = (byte[]) map.get("pdu"); 188 189 Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 190 191 Rlog.d(TAG, "sendSms: " 192 +" isIms()="+isIms() 193 +" mRetryCount="+tracker.mRetryCount 194 +" mImsRetry="+tracker.mImsRetry 195 +" mMessageRef="+tracker.mMessageRef 196 +" SS=" +mPhone.getServiceState().getState()); 197 198 // sms over cdma is used: 199 // if sms over IMS is not supported AND 200 // this is not a retry case after sms over IMS failed 201 // indicated by mImsRetry > 0 202 if (0 == tracker.mImsRetry && !isIms()) { 203 mCi.sendCdmaSms(pdu, reply); 204 } else { 205 mCi.sendImsCdmaSms(pdu, tracker.mImsRetry, tracker.mMessageRef, reply); 206 // increment it here, so in case of SMS_FAIL_RETRY over IMS 207 // next retry will be sent using IMS request again. 208 tracker.mImsRetry++; 209 } 210 } 211} 212