CdmaSMSDispatcher.java revision 767a662ecde33c3979bf02b793d392aca0403162
1767a662ecde33c3979bf02b793d392aca0403162Wink Saville/* 2767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Copyright (C) 2008 The Android Open Source Project 3767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 4767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5767a662ecde33c3979bf02b793d392aca0403162Wink Saville * you may not use this file except in compliance with the License. 6767a662ecde33c3979bf02b793d392aca0403162Wink Saville * You may obtain a copy of the License at 7767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 8767a662ecde33c3979bf02b793d392aca0403162Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 9767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 10767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Unless required by applicable law or agreed to in writing, software 11767a662ecde33c3979bf02b793d392aca0403162Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13767a662ecde33c3979bf02b793d392aca0403162Wink Saville * See the License for the specific language governing permissions and 14767a662ecde33c3979bf02b793d392aca0403162Wink Saville * limitations under the License. 15767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 16767a662ecde33c3979bf02b793d392aca0403162Wink Saville 17767a662ecde33c3979bf02b793d392aca0403162Wink Savillepackage com.android.internal.telephony.cdma; 18767a662ecde33c3979bf02b793d392aca0403162Wink Saville 19767a662ecde33c3979bf02b793d392aca0403162Wink Saville 20767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.app.PendingIntent; 21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.content.ContentValues; 22767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.Cursor; 23767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.SQLException; 24767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.AsyncResult; 25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Message; 26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Config; 27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log; 28767a662ecde33c3979bf02b793d392aca0403162Wink Saville 29767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader; 30767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase; 31767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SMSDispatcher; 32767a662ecde33c3979bf02b793d392aca0403162Wink Saville//import com.android.internal.telephony.SMSDispatcher.SmsTracker; 33767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.SmsMessage; 34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope; 35767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.util.HexDump; 36767a662ecde33c3979bf02b793d392aca0403162Wink Saville 37767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream; 38767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList; 39767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap; 40767a662ecde33c3979bf02b793d392aca0403162Wink Saville 41767a662ecde33c3979bf02b793d392aca0403162Wink Saville 42767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher { 43767a662ecde33c3979bf02b793d392aca0403162Wink Saville private static final String TAG = "CDMA"; 44767a662ecde33c3979bf02b793d392aca0403162Wink Saville 45767a662ecde33c3979bf02b793d392aca0403162Wink Saville CdmaSMSDispatcher(CDMAPhone phone) { 46767a662ecde33c3979bf02b793d392aca0403162Wink Saville super(phone); 47767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 48767a662ecde33c3979bf02b793d392aca0403162Wink Saville 49767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 50767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Called when a status report is received. This should correspond to 51767a662ecde33c3979bf02b793d392aca0403162Wink Saville * a previously successful SEND. 52767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Is a special GSM function, should never be called in CDMA!! 53767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 54767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param ar AsyncResult passed into the message handler. ar.result should 55767a662ecde33c3979bf02b793d392aca0403162Wink Saville * be a String representing the status report PDU, as ASCII hex. 56767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 57767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void handleStatusReport(AsyncResult ar) { 58767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!"); 59767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 60767a662ecde33c3979bf02b793d392aca0403162Wink Saville 61767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 62767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Dispatches an incoming SMS messages. 63767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 64767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param smsb the incoming message from the phone 65767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 66767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void dispatchMessage(SmsMessageBase smsb) { 67767a662ecde33c3979bf02b793d392aca0403162Wink Saville 68767a662ecde33c3979bf02b793d392aca0403162Wink Saville // If sms is null, means there was a parsing error. 69767a662ecde33c3979bf02b793d392aca0403162Wink Saville // TODO: Should NAK this. 70767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (smsb == null) { 71767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; 72767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 73767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage sms = (SmsMessage) smsb; 74767a662ecde33c3979bf02b793d392aca0403162Wink Saville int teleService; 75767a662ecde33c3979bf02b793d392aca0403162Wink Saville boolean handled = false; 76767a662ecde33c3979bf02b793d392aca0403162Wink Saville 77767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Decode BD stream and set sms variables. 78767a662ecde33c3979bf02b793d392aca0403162Wink Saville sms.parseSms(); 79767a662ecde33c3979bf02b793d392aca0403162Wink Saville teleService = sms.getTeleService(); 80767a662ecde33c3979bf02b793d392aca0403162Wink Saville 81767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Teleservices W(E)MT and VMN are handled together: 82767a662ecde33c3979bf02b793d392aca0403162Wink Saville if ((SmsEnvelope.TELESERVICE_WMT == teleService) 83767a662ecde33c3979bf02b793d392aca0403162Wink Saville ||(SmsEnvelope.TELESERVICE_WEMT == teleService) 84767a662ecde33c3979bf02b793d392aca0403162Wink Saville ||(SmsEnvelope.TELESERVICE_VMN == teleService)){ 85767a662ecde33c3979bf02b793d392aca0403162Wink Saville // From here on we need decoded BD. 86767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Special case the message waiting indicator messages 87767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (sms.isMWISetMessage()) { 88767a662ecde33c3979bf02b793d392aca0403162Wink Saville ((CDMAPhone) mPhone).updateMessageWaitingIndicator(true); 89767a662ecde33c3979bf02b793d392aca0403162Wink Saville 90767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (sms.isMwiDontStore()) { 91767a662ecde33c3979bf02b793d392aca0403162Wink Saville handled = true; 92767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 93767a662ecde33c3979bf02b793d392aca0403162Wink Saville 94767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) { 95767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, 96767a662ecde33c3979bf02b793d392aca0403162Wink Saville "Received voice mail indicator set SMS shouldStore=" + !handled); 97767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 98767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else if (sms.isMWIClearMessage()) { 99767a662ecde33c3979bf02b793d392aca0403162Wink Saville ((CDMAPhone) mPhone).updateMessageWaitingIndicator(false); 100767a662ecde33c3979bf02b793d392aca0403162Wink Saville 101767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (sms.isMwiDontStore()) { 102767a662ecde33c3979bf02b793d392aca0403162Wink Saville handled = true; 103767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 104767a662ecde33c3979bf02b793d392aca0403162Wink Saville 105767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) { 106767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, 107767a662ecde33c3979bf02b793d392aca0403162Wink Saville "Received voice mail indicator clear SMS shouldStore=" + !handled); 108767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 109767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 110767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 111767a662ecde33c3979bf02b793d392aca0403162Wink Saville 112767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (null == sms.getUserData()){ 113767a662ecde33c3979bf02b793d392aca0403162Wink Saville handled = true; 114767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) { 115767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "Received SMS without user data"); 116767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 117767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 118767a662ecde33c3979bf02b793d392aca0403162Wink Saville 119767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (handled) return; 120767a662ecde33c3979bf02b793d392aca0403162Wink Saville 121767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (SmsEnvelope.TELESERVICE_WAP == teleService){ 122767a662ecde33c3979bf02b793d392aca0403162Wink Saville processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress()); 123767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; 124767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 125767a662ecde33c3979bf02b793d392aca0403162Wink Saville 126767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Parse the headers to see if this is partial, or port addressed 127767a662ecde33c3979bf02b793d392aca0403162Wink Saville int referenceNumber = -1; 128767a662ecde33c3979bf02b793d392aca0403162Wink Saville int count = 0; 129767a662ecde33c3979bf02b793d392aca0403162Wink Saville int sequence = 0; 130767a662ecde33c3979bf02b793d392aca0403162Wink Saville int destPort = -1; 131767a662ecde33c3979bf02b793d392aca0403162Wink Saville // From here on we need BD distributed to SMS member variables. 132767a662ecde33c3979bf02b793d392aca0403162Wink Saville 133767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsHeader header = sms.getUserDataHeader(); 134767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (header != null) { 135767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (SmsHeader.Element element : header.getElements()) { 136767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 137767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (element.getID()) { 138767a662ecde33c3979bf02b793d392aca0403162Wink Saville case SmsHeader.CONCATENATED_8_BIT_REFERENCE: { 139767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] data = element.getData(); 140767a662ecde33c3979bf02b793d392aca0403162Wink Saville 141767a662ecde33c3979bf02b793d392aca0403162Wink Saville referenceNumber = data[0] & 0xff; 142767a662ecde33c3979bf02b793d392aca0403162Wink Saville count = data[1] & 0xff; 143767a662ecde33c3979bf02b793d392aca0403162Wink Saville sequence = data[2] & 0xff; 144767a662ecde33c3979bf02b793d392aca0403162Wink Saville 145767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence 146767a662ecde33c3979bf02b793d392aca0403162Wink Saville // is zero, or sequence > count, ignore the entire element 147767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (count == 0 || sequence == 0 || sequence > count) { 148767a662ecde33c3979bf02b793d392aca0403162Wink Saville referenceNumber = -1; 149767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 150767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 151767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 152767a662ecde33c3979bf02b793d392aca0403162Wink Saville 153767a662ecde33c3979bf02b793d392aca0403162Wink Saville case SmsHeader.CONCATENATED_16_BIT_REFERENCE: { 154767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] data = element.getData(); 155767a662ecde33c3979bf02b793d392aca0403162Wink Saville 156767a662ecde33c3979bf02b793d392aca0403162Wink Saville referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff); 157767a662ecde33c3979bf02b793d392aca0403162Wink Saville count = data[2] & 0xff; 158767a662ecde33c3979bf02b793d392aca0403162Wink Saville sequence = data[3] & 0xff; 159767a662ecde33c3979bf02b793d392aca0403162Wink Saville 160767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence 161767a662ecde33c3979bf02b793d392aca0403162Wink Saville // is zero, or sequence > count, ignore the entire element 162767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (count == 0 || sequence == 0 || sequence > count) { 163767a662ecde33c3979bf02b793d392aca0403162Wink Saville referenceNumber = -1; 164767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 165767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 166767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 167767a662ecde33c3979bf02b793d392aca0403162Wink Saville 168767a662ecde33c3979bf02b793d392aca0403162Wink Saville case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: { 169767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] data = element.getData(); 170767a662ecde33c3979bf02b793d392aca0403162Wink Saville 171767a662ecde33c3979bf02b793d392aca0403162Wink Saville destPort = (data[0] & 0xff) << 8; 172767a662ecde33c3979bf02b793d392aca0403162Wink Saville destPort |= (data[1] & 0xff); 173767a662ecde33c3979bf02b793d392aca0403162Wink Saville 174767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 175767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 176767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 177767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (ArrayIndexOutOfBoundsException e) { 178767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(TAG, "Bad element in header", e); 179767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; // TODO: NACK the message or something, don't just discard. 180767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 181767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 182767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 183767a662ecde33c3979bf02b793d392aca0403162Wink Saville 184767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (referenceNumber == -1) { 185767a662ecde33c3979bf02b793d392aca0403162Wink Saville // notify everyone of the message if it isn't partial 186767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[][] pdus = new byte[1][]; 187767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[0] = sms.getPdu(); 188767a662ecde33c3979bf02b793d392aca0403162Wink Saville 189767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (destPort != -1) {// GSM-style WAP indication 190767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (destPort == SmsHeader.PORT_WAP_PUSH) { 191767a662ecde33c3979bf02b793d392aca0403162Wink Saville mWapPush.dispatchWapPdu(sms.getUserData()); 192767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 193767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The message was sent to a port, so concoct a URI for it 194767a662ecde33c3979bf02b793d392aca0403162Wink Saville dispatchPortAddressedPdus(pdus, destPort); 195767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 196767a662ecde33c3979bf02b793d392aca0403162Wink Saville // It's a normal message, dispatch it 197767a662ecde33c3979bf02b793d392aca0403162Wink Saville dispatchPdus(pdus); 198767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 199767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 200767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Process the message part 201767a662ecde33c3979bf02b793d392aca0403162Wink Saville processMessagePart(sms, referenceNumber, sequence, count, destPort); 202767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 203767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 204767a662ecde33c3979bf02b793d392aca0403162Wink Saville 205767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 206767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Processes inbound messages that are in the WAP-WDP PDU format. See 207767a662ecde33c3979bf02b793d392aca0403162Wink Saville * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format. 208767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WDP segments are gathered until a datagram completes and gets dispatched. 209767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 210767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param pdu The WAP-WDP PDU segment 211767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 212767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) { 213767a662ecde33c3979bf02b793d392aca0403162Wink Saville int segment; 214767a662ecde33c3979bf02b793d392aca0403162Wink Saville int totalSegments; 215767a662ecde33c3979bf02b793d392aca0403162Wink Saville int index = 0; 216767a662ecde33c3979bf02b793d392aca0403162Wink Saville int msgType; 217767a662ecde33c3979bf02b793d392aca0403162Wink Saville 218767a662ecde33c3979bf02b793d392aca0403162Wink Saville int sourcePort; 219767a662ecde33c3979bf02b793d392aca0403162Wink Saville int destinationPort; 220767a662ecde33c3979bf02b793d392aca0403162Wink Saville 221767a662ecde33c3979bf02b793d392aca0403162Wink Saville msgType = pdu[index++]; 222767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (msgType != 0){ 223767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(TAG, "Received a WAP SMS which is not WDP. Discard."); 224767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; 225767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 226767a662ecde33c3979bf02b793d392aca0403162Wink Saville totalSegments = pdu[index++]; // >=1 227767a662ecde33c3979bf02b793d392aca0403162Wink Saville segment = pdu[index++]; // >=0 228767a662ecde33c3979bf02b793d392aca0403162Wink Saville 229767a662ecde33c3979bf02b793d392aca0403162Wink Saville //process WDP segment 230767a662ecde33c3979bf02b793d392aca0403162Wink Saville sourcePort = (0xFF & pdu[index++]) << 8; 231767a662ecde33c3979bf02b793d392aca0403162Wink Saville sourcePort |= 0xFF & pdu[index++]; 232767a662ecde33c3979bf02b793d392aca0403162Wink Saville destinationPort = (0xFF & pdu[index++]) << 8; 233767a662ecde33c3979bf02b793d392aca0403162Wink Saville destinationPort |= 0xFF & pdu[index++]; 234767a662ecde33c3979bf02b793d392aca0403162Wink Saville 235767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Lookup all other related parts 236767a662ecde33c3979bf02b793d392aca0403162Wink Saville StringBuilder where = new StringBuilder("reference_number ="); 237767a662ecde33c3979bf02b793d392aca0403162Wink Saville where.append(referenceNumber); 238767a662ecde33c3979bf02b793d392aca0403162Wink Saville where.append(" AND address = ?"); 239767a662ecde33c3979bf02b793d392aca0403162Wink Saville String[] whereArgs = new String[] {address}; 240767a662ecde33c3979bf02b793d392aca0403162Wink Saville 241767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address 242767a662ecde33c3979bf02b793d392aca0403162Wink Saville + ", src-port = " + sourcePort + ", dst-port = " + destinationPort 243767a662ecde33c3979bf02b793d392aca0403162Wink Saville + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments); 244767a662ecde33c3979bf02b793d392aca0403162Wink Saville 245767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[][] pdus = null; 246767a662ecde33c3979bf02b793d392aca0403162Wink Saville Cursor cursor = null; 247767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 248767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null); 249767a662ecde33c3979bf02b793d392aca0403162Wink Saville int cursorCount = cursor.getCount(); 250767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (cursorCount != totalSegments - 1) { 251767a662ecde33c3979bf02b793d392aca0403162Wink Saville // We don't have all the parts yet, store this one away 252767a662ecde33c3979bf02b793d392aca0403162Wink Saville ContentValues values = new ContentValues(); 253767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("date", new Long(0)); 254767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index)); 255767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("address", address); 256767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("reference_number", referenceNumber); 257767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("count", totalSegments); 258767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("sequence", segment); 259767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("destination_port", destinationPort); 260767a662ecde33c3979bf02b793d392aca0403162Wink Saville 261767a662ecde33c3979bf02b793d392aca0403162Wink Saville mResolver.insert(mRawUri, values); 262767a662ecde33c3979bf02b793d392aca0403162Wink Saville 263767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; 264767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 265767a662ecde33c3979bf02b793d392aca0403162Wink Saville 266767a662ecde33c3979bf02b793d392aca0403162Wink Saville // All the parts are in place, deal with them 267767a662ecde33c3979bf02b793d392aca0403162Wink Saville int pduColumn = cursor.getColumnIndex("pdu"); 268767a662ecde33c3979bf02b793d392aca0403162Wink Saville int sequenceColumn = cursor.getColumnIndex("sequence"); 269767a662ecde33c3979bf02b793d392aca0403162Wink Saville 270767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus = new byte[totalSegments][]; 271767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (int i = 0; i < cursorCount; i++) { 272767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor.moveToNext(); 273767a662ecde33c3979bf02b793d392aca0403162Wink Saville int cursorSequence = (int)cursor.getLong(sequenceColumn); 274767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[cursorSequence] = HexDump.hexStringToByteArray( 275767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor.getString(pduColumn)); 276767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 277767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The last part will be added later 278767a662ecde33c3979bf02b793d392aca0403162Wink Saville 279767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Remove the parts from the database 280767a662ecde33c3979bf02b793d392aca0403162Wink Saville mResolver.delete(mRawUri, where.toString(), whereArgs); 281767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (SQLException e) { 282767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(TAG, "Can't access multipart SMS database", e); 283767a662ecde33c3979bf02b793d392aca0403162Wink Saville return; // TODO: NACK the message or something, don't just discard. 284767a662ecde33c3979bf02b793d392aca0403162Wink Saville } finally { 285767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (cursor != null) cursor.close(); 286767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 287767a662ecde33c3979bf02b793d392aca0403162Wink Saville 288767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Build up the data stream 289767a662ecde33c3979bf02b793d392aca0403162Wink Saville ByteArrayOutputStream output = new ByteArrayOutputStream(); 290767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (int i = 0; i < totalSegments-1; i++) { 291767a662ecde33c3979bf02b793d392aca0403162Wink Saville // reassemble the (WSP-)pdu 292767a662ecde33c3979bf02b793d392aca0403162Wink Saville output.write(pdus[i], 0, pdus[i].length); 293767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 294767a662ecde33c3979bf02b793d392aca0403162Wink Saville 295767a662ecde33c3979bf02b793d392aca0403162Wink Saville // This one isn't in the DB, so add it 296767a662ecde33c3979bf02b793d392aca0403162Wink Saville output.write(pdu, index, pdu.length - index); 297767a662ecde33c3979bf02b793d392aca0403162Wink Saville 298767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] datagram = output.toByteArray(); 299767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Dispatch the PDU to applications 300767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (destinationPort) { 301767a662ecde33c3979bf02b793d392aca0403162Wink Saville case SmsHeader.PORT_WAP_PUSH: 302767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Handle the PUSH 303767a662ecde33c3979bf02b793d392aca0403162Wink Saville mWapPush.dispatchWapPdu(datagram); 304767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 305767a662ecde33c3979bf02b793d392aca0403162Wink Saville 306767a662ecde33c3979bf02b793d392aca0403162Wink Saville default:{ 307767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus = new byte[1][]; 308767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[0] = datagram; 309767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The messages were sent to any other WAP port 310767a662ecde33c3979bf02b793d392aca0403162Wink Saville dispatchPortAddressedPdus(pdus, destinationPort); 311767a662ecde33c3979bf02b793d392aca0403162Wink Saville break; 312767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 313767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 314767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 315767a662ecde33c3979bf02b793d392aca0403162Wink Saville 316767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 317767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendMultipartText(String destinationAddress, String scAddress, 318767a662ecde33c3979bf02b793d392aca0403162Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 319767a662ecde33c3979bf02b793d392aca0403162Wink Saville ArrayList<PendingIntent> deliveryIntents) { 320767a662ecde33c3979bf02b793d392aca0403162Wink Saville 321767a662ecde33c3979bf02b793d392aca0403162Wink Saville int ref = ++sConcatenatedRef & 0xff; 322767a662ecde33c3979bf02b793d392aca0403162Wink Saville 323767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (int i = 0, count = parts.size(); i < count; i++) { 324767a662ecde33c3979bf02b793d392aca0403162Wink Saville // build SmsHeader data 325767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] data = new byte[5]; 326767a662ecde33c3979bf02b793d392aca0403162Wink Saville data[0] = (byte) SmsHeader.CONCATENATED_8_BIT_REFERENCE; 327767a662ecde33c3979bf02b793d392aca0403162Wink Saville data[1] = (byte) 3; // 3 bytes follow 328767a662ecde33c3979bf02b793d392aca0403162Wink Saville data[2] = (byte) ref; // reference #, unique per message 329767a662ecde33c3979bf02b793d392aca0403162Wink Saville data[3] = (byte) count; // total part count 330767a662ecde33c3979bf02b793d392aca0403162Wink Saville data[4] = (byte) (i + 1); // 1-based sequence 331767a662ecde33c3979bf02b793d392aca0403162Wink Saville 332767a662ecde33c3979bf02b793d392aca0403162Wink Saville PendingIntent sentIntent = null; 333767a662ecde33c3979bf02b793d392aca0403162Wink Saville PendingIntent deliveryIntent = null; 334767a662ecde33c3979bf02b793d392aca0403162Wink Saville 335767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (sentIntents != null && sentIntents.size() > i) { 336767a662ecde33c3979bf02b793d392aca0403162Wink Saville sentIntent = sentIntents.get(i); 337767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 338767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 339767a662ecde33c3979bf02b793d392aca0403162Wink Saville deliveryIntent = deliveryIntents.get(i); 340767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 341767a662ecde33c3979bf02b793d392aca0403162Wink Saville 342767a662ecde33c3979bf02b793d392aca0403162Wink Saville SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress, 343767a662ecde33c3979bf02b793d392aca0403162Wink Saville parts.get(i), deliveryIntent != null, data); 344767a662ecde33c3979bf02b793d392aca0403162Wink Saville 345767a662ecde33c3979bf02b793d392aca0403162Wink Saville sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent); 346767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 347767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 348767a662ecde33c3979bf02b793d392aca0403162Wink Saville 349767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent, 350767a662ecde33c3979bf02b793d392aca0403162Wink Saville PendingIntent deliveryIntent) { 351767a662ecde33c3979bf02b793d392aca0403162Wink Saville super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent); 352767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 353767a662ecde33c3979bf02b793d392aca0403162Wink Saville 354767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 355767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendSms(SmsTracker tracker) { 356767a662ecde33c3979bf02b793d392aca0403162Wink Saville HashMap map = tracker.mData; 357767a662ecde33c3979bf02b793d392aca0403162Wink Saville 358767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte smsc[] = (byte[]) map.get("smsc"); 359767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte pdu[] = (byte[]) map.get("pdu"); 360767a662ecde33c3979bf02b793d392aca0403162Wink Saville 361767a662ecde33c3979bf02b793d392aca0403162Wink Saville Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 362767a662ecde33c3979bf02b793d392aca0403162Wink Saville 363767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.sendCdmaSms(pdu, reply); 364767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 365767a662ecde33c3979bf02b793d392aca0403162Wink Saville 366767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 367767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendMultipartSms (SmsTracker tracker) { 368767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented"); 369767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 370767a662ecde33c3979bf02b793d392aca0403162Wink Saville 371767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 372767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void acknowledgeLastIncomingSms(boolean success, Message response){ 373767a662ecde33c3979bf02b793d392aca0403162Wink Saville // FIXME unit test leaves cm == null. this should change 374767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (mCm != null) { 375767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.acknowledgeLastIncomingCdmaSms(success, response); 376767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 377767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 378767a662ecde33c3979bf02b793d392aca0403162Wink Saville 379767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 380767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void activateCellBroadcastSms(int activate, Message response) { 381767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.activateCdmaBroadcastSms(activate, response); 382767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 383767a662ecde33c3979bf02b793d392aca0403162Wink Saville 384767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 385767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void getCellBroadcastSmsConfig(Message response) { 386767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.getCdmaBroadcastConfig(response); 387767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 388767a662ecde33c3979bf02b793d392aca0403162Wink Saville 389767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 390767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { 391767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.setCdmaBroadcastConfig(configValuesArray, response); 392767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 393767a662ecde33c3979bf02b793d392aca0403162Wink Saville 394767a662ecde33c3979bf02b793d392aca0403162Wink Saville} 395