GsmSMSDispatcher.java revision 0d4bcdf379842af4b6304809156971e926f374f0
1/* 2 * Copyright (C) 2006 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.gsm; 18 19import android.app.Activity; 20import android.app.PendingIntent; 21import android.app.PendingIntent.CanceledException; 22import android.content.Intent; 23import android.os.AsyncResult; 24import android.os.Message; 25import android.provider.Telephony.Sms; 26import android.provider.Telephony.Sms.Intents; 27import android.telephony.Rlog; 28 29import com.android.internal.telephony.GsmAlphabet; 30import com.android.internal.telephony.PhoneBase; 31import com.android.internal.telephony.SMSDispatcher; 32import com.android.internal.telephony.SmsConstants; 33import com.android.internal.telephony.SmsHeader; 34import com.android.internal.telephony.SmsUsageMonitor; 35import com.android.internal.telephony.uicc.IccUtils; 36 37import java.util.HashMap; 38 39public final class GsmSMSDispatcher extends SMSDispatcher { 40 private static final String TAG = "GsmSMSDispatcher"; 41 42 /** Status report received */ 43 private static final int EVENT_NEW_SMS_STATUS_REPORT = 100; 44 45 public GsmSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor) { 46 super(phone, usageMonitor); 47 mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); 48 } 49 50 @Override 51 public void dispose() { 52 super.dispose(); 53 mCi.unSetOnSmsStatus(this); 54 } 55 56 @Override 57 protected String getFormat() { 58 return SmsConstants.FORMAT_3GPP; 59 } 60 61 /** 62 * Handles 3GPP format-specific events coming from the phone stack. 63 * Other events are handled by {@link SMSDispatcher#handleMessage}. 64 * 65 * @param msg the message to handle 66 */ 67 @Override 68 public void handleMessage(Message msg) { 69 switch (msg.what) { 70 case EVENT_NEW_SMS_STATUS_REPORT: 71 handleStatusReport((AsyncResult) msg.obj); 72 break; 73 74 default: 75 super.handleMessage(msg); 76 } 77 } 78 79 /** 80 * Called when a status report is received. This should correspond to 81 * a previously successful SEND. 82 * 83 * @param ar AsyncResult passed into the message handler. ar.result should 84 * be a String representing the status report PDU, as ASCII hex. 85 */ 86 private void handleStatusReport(AsyncResult ar) { 87 String pduString = (String) ar.result; 88 SmsMessage sms = SmsMessage.newFromCDS(pduString); 89 90 if (sms != null) { 91 int tpStatus = sms.getStatus(); 92 int messageRef = sms.mMessageRef; 93 for (int i = 0, count = deliveryPendingList.size(); i < count; i++) { 94 SmsTracker tracker = deliveryPendingList.get(i); 95 if (tracker.mMessageRef == messageRef) { 96 // Found it. Remove from list and broadcast. 97 if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) { 98 deliveryPendingList.remove(i); 99 } 100 PendingIntent intent = tracker.mDeliveryIntent; 101 Intent fillIn = new Intent(); 102 fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString)); 103 fillIn.putExtra("format", SmsConstants.FORMAT_3GPP); 104 try { 105 intent.send(mContext, Activity.RESULT_OK, fillIn); 106 } catch (CanceledException ex) {} 107 108 // Only expect to see one tracker matching this messageref 109 break; 110 } 111 } 112 } 113 mCi.acknowledgeLastIncomingGsmSms(true, Intents.RESULT_SMS_HANDLED, null); 114 } 115 116 /** {@inheritDoc} */ 117 @Override 118 protected void sendData(String destAddr, String scAddr, int destPort, 119 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 120 SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 121 scAddr, destAddr, destPort, data, (deliveryIntent != null)); 122 if (pdu != null) { 123 sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 124 destAddr); 125 } else { 126 Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null"); 127 } 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 protected void sendText(String destAddr, String scAddr, String text, 133 PendingIntent sentIntent, PendingIntent deliveryIntent) { 134 SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 135 scAddr, destAddr, text, (deliveryIntent != null)); 136 if (pdu != null) { 137 sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 138 destAddr); 139 } else { 140 Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null"); 141 } 142 } 143 144 /** {@inheritDoc} */ 145 @Override 146 protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody, 147 boolean use7bitOnly) { 148 return SmsMessage.calculateLength(messageBody, use7bitOnly); 149 } 150 151 /** {@inheritDoc} */ 152 @Override 153 protected void sendNewSubmitPdu(String destinationAddress, String scAddress, 154 String message, SmsHeader smsHeader, int encoding, 155 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) { 156 SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress, 157 message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader), 158 encoding, smsHeader.languageTable, smsHeader.languageShiftTable); 159 if (pdu != null) { 160 sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 161 destinationAddress); 162 } else { 163 Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null"); 164 } 165 } 166 167 /** {@inheritDoc} */ 168 @Override 169 protected void sendSms(SmsTracker tracker) { 170 HashMap<String, Object> map = tracker.mData; 171 172 byte smsc[] = (byte[]) map.get("smsc"); 173 byte pdu[] = (byte[]) map.get("pdu"); 174 175 Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 176 177 if (tracker.mRetryCount > 0) { 178 Rlog.d(TAG, "sendSms: " 179 + " mRetryCount=" + tracker.mRetryCount 180 + " mMessageRef=" + tracker.mMessageRef 181 + " SS=" + mPhone.getServiceState().getState()); 182 183 // per TS 23.040 Section 9.2.3.6: If TP-MTI SMS-SUBMIT (0x01) type 184 // TP-RD (bit 2) is 1 for retry 185 // and TP-MR is set to previously failed sms TP-MR 186 if (((0x01 & pdu[0]) == 0x01)) { 187 pdu[0] |= 0x04; // TP-RD 188 pdu[1] = (byte) tracker.mMessageRef; // TP-MR 189 } 190 } 191 mCi.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); 192 } 193} 194