CdmaSMSDispatcher.java revision a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019
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 20867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.app.Activity; 21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.app.PendingIntent; 22a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.app.PendingIntent.CanceledException; 23767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.content.ContentValues; 24ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krauseimport android.content.SharedPreferences; 25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.Cursor; 26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.SQLException; 27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.AsyncResult; 28767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Message; 29117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport android.os.SystemProperties; 303960ced4638fdb24ddf904fcb6734dae0959671ejshimport android.provider.Telephony; 31867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.provider.Telephony.Sms.Intents; 32ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krauseimport android.preference.PreferenceManager; 33767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Config; 34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log; 35a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.telephony.SmsManager; 36a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jshimport android.telephony.SmsMessage.MessageClass; 37767a662ecde33c3979bf02b793d392aca0403162Wink Saville 38117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport com.android.internal.telephony.TelephonyProperties; 39867641ece36e2fd17faaea79cf19506ab17177c6jshimport com.android.internal.telephony.CommandsInterface; 40767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader; 41767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase; 42767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SMSDispatcher; 43767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.SmsMessage; 44767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope; 45fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalinkimport com.android.internal.telephony.cdma.sms.UserData; 46767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.util.HexDump; 47767a662ecde33c3979bf02b793d392aca0403162Wink Saville 48767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream; 49767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList; 50767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap; 51a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport java.lang.Boolean; 52767a662ecde33c3979bf02b793d392aca0403162Wink Saville 53767a662ecde33c3979bf02b793d392aca0403162Wink Saville 54767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher { 55767a662ecde33c3979bf02b793d392aca0403162Wink Saville private static final String TAG = "CDMA"; 56767a662ecde33c3979bf02b793d392aca0403162Wink Saville 5764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink private CDMAPhone mCdmaPhone; 5864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink 59767a662ecde33c3979bf02b793d392aca0403162Wink Saville CdmaSMSDispatcher(CDMAPhone phone) { 60767a662ecde33c3979bf02b793d392aca0403162Wink Saville super(phone); 6164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink mCdmaPhone = phone; 62767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 63767a662ecde33c3979bf02b793d392aca0403162Wink Saville 64767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 65767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Called when a status report is received. This should correspond to 66767a662ecde33c3979bf02b793d392aca0403162Wink Saville * a previously successful SEND. 67767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Is a special GSM function, should never be called in CDMA!! 68767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 69767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param ar AsyncResult passed into the message handler. ar.result should 70767a662ecde33c3979bf02b793d392aca0403162Wink Saville * be a String representing the status report PDU, as ASCII hex. 71767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 72767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void handleStatusReport(AsyncResult ar) { 73767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!"); 74767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 75767a662ecde33c3979bf02b793d392aca0403162Wink Saville 763960ced4638fdb24ddf904fcb6734dae0959671ejsh /** {@inheritDoc} */ 773960ced4638fdb24ddf904fcb6734dae0959671ejsh protected int dispatchMessage(SmsMessageBase smsb) { 78767a662ecde33c3979bf02b793d392aca0403162Wink Saville 79767a662ecde33c3979bf02b793d392aca0403162Wink Saville // If sms is null, means there was a parsing error. 80767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (smsb == null) { 813960ced4638fdb24ddf904fcb6734dae0959671ejsh return Intents.RESULT_SMS_GENERIC_ERROR; 82767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 83767a662ecde33c3979bf02b793d392aca0403162Wink Saville 84117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 85117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang if (inEcm.equals("true")) { 86117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang return Intents.RESULT_SMS_GENERIC_ERROR; 87117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang } 88117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang 89767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Decode BD stream and set sms variables. 9064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink SmsMessage sms = (SmsMessage) smsb; 91767a662ecde33c3979bf02b793d392aca0403162Wink Saville sms.parseSms(); 9264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink int teleService = sms.getTeleService(); 9364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink boolean handled = false; 94767a662ecde33c3979bf02b793d392aca0403162Wink Saville 95a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh if ((SmsEnvelope.TELESERVICE_VMN == teleService) || 96a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh (SmsEnvelope.TELESERVICE_MWI == teleService)) { 97a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh // handling Voicemail 98a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh int voicemailCount = sms.getNumOfVoicemails(); 99a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh Log.d(TAG, "Voicemail count=" + voicemailCount); 100a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh // Store the voicemail count in preferences. 101a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( 102a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh ((CDMAPhone) mPhone).getContext()); 103a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh SharedPreferences.Editor editor = sp.edit(); 104a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount); 105a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh editor.commit(); 106a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh ((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount); 107a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh handled = true; 108a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh } else if ((sms.getUserData() == null)) { 109767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (Config.LOGD) { 110767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "Received SMS without user data"); 111767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 11264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink handled = true; 113767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 114767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1153960ced4638fdb24ddf904fcb6734dae0959671ejsh if (handled) { 1163960ced4638fdb24ddf904fcb6734dae0959671ejsh return Intents.RESULT_SMS_HANDLED; 1173960ced4638fdb24ddf904fcb6734dae0959671ejsh } 118767a662ecde33c3979bf02b793d392aca0403162Wink Saville 119a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) { 120a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh // It's a storable message and there's no storage available. Bail. 121a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh // (See C.S0015-B v2.0 for a description of "Immediate Display" 122a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh // messages, which we represent as CLASS_0.) 123a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh return Intents.RESULT_SMS_OUT_OF_MEMORY; 124a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh } 125a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh 126c84401fb8b3ed90039bd132b343852303ef88ce6yong liu if (SmsEnvelope.TELESERVICE_WAP == teleService) { 1273960ced4638fdb24ddf904fcb6734dae0959671ejsh return processCdmaWapPdu(sms.getUserData(), sms.messageRef, 1283960ced4638fdb24ddf904fcb6734dae0959671ejsh sms.getOriginatingAddress()); 129767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 130767a662ecde33c3979bf02b793d392aca0403162Wink Saville 13164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink /** 13264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * TODO(cleanup): Why are we using a getter method for this 13364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * (and for so many other sms fields)? Trivial getters and 13464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * setters like this are direct violations of the style guide. 13564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * If the purpose is to protect agaist writes (by not 13664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * providing a setter) then any protection is illusory (and 13764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * hence bad) for cases where the values are not primitives, 13864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * such as this call for the header. Since this is an issue 13964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * with the public API it cannot be changed easily, but maybe 14064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * something can be done eventually. 14164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink */ 14264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink SmsHeader smsHeader = sms.getUserDataHeader(); 14364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink 14464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink /** 14564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * TODO(cleanup): Since both CDMA and GSM use the same header 14664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * format, this dispatch processing is naturally identical, 14764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * and code should probably not be replicated explicitly. 14864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink */ 14964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink // See if message is partial or port addressed. 15064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink if ((smsHeader == null) || (smsHeader.concatRef == null)) { 15164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink // Message is not partial (not part of concatenated sequence). 152767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[][] pdus = new byte[1][]; 153767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[0] = sms.getPdu(); 154767a662ecde33c3979bf02b793d392aca0403162Wink Saville 15531fd22923aaefc85652a5b5939c6d4aa6fa289e2jsh if (smsHeader != null && smsHeader.portAddrs != null) { 15664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) { 15764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink // GSM-style WAP indication 1583960ced4638fdb24ddf904fcb6734dae0959671ejsh return mWapPush.dispatchWapPdu(sms.getUserData()); 1593960ced4638fdb24ddf904fcb6734dae0959671ejsh } else { 1603960ced4638fdb24ddf904fcb6734dae0959671ejsh // The message was sent to a port, so concoct a URI for it. 1613960ced4638fdb24ddf904fcb6734dae0959671ejsh dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort); 162767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 163767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 16464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink // Normal short and non-port-addressed message, dispatch it. 165767a662ecde33c3979bf02b793d392aca0403162Wink Saville dispatchPdus(pdus); 166767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 1673960ced4638fdb24ddf904fcb6734dae0959671ejsh return Activity.RESULT_OK; 168767a662ecde33c3979bf02b793d392aca0403162Wink Saville } else { 16964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink // Process the message part. 1703960ced4638fdb24ddf904fcb6734dae0959671ejsh return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs); 171767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 172767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 173767a662ecde33c3979bf02b793d392aca0403162Wink Saville 174767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** 175767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Processes inbound messages that are in the WAP-WDP PDU format. See 176767a662ecde33c3979bf02b793d392aca0403162Wink Saville * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format. 177767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WDP segments are gathered until a datagram completes and gets dispatched. 178767a662ecde33c3979bf02b793d392aca0403162Wink Saville * 179767a662ecde33c3979bf02b793d392aca0403162Wink Saville * @param pdu The WAP-WDP PDU segment 1803960ced4638fdb24ddf904fcb6734dae0959671ejsh * @return a result code from {@link Telephony.Sms.Intents}, or 1813960ced4638fdb24ddf904fcb6734dae0959671ejsh * {@link Activity#RESULT_OK} if the message has been broadcast 1823960ced4638fdb24ddf904fcb6734dae0959671ejsh * to applications 183767a662ecde33c3979bf02b793d392aca0403162Wink Saville */ 1843960ced4638fdb24ddf904fcb6734dae0959671ejsh protected int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) { 185767a662ecde33c3979bf02b793d392aca0403162Wink Saville int segment; 186767a662ecde33c3979bf02b793d392aca0403162Wink Saville int totalSegments; 187767a662ecde33c3979bf02b793d392aca0403162Wink Saville int index = 0; 188767a662ecde33c3979bf02b793d392aca0403162Wink Saville int msgType; 189767a662ecde33c3979bf02b793d392aca0403162Wink Saville 1905c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause int sourcePort = 0; 1915c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause int destinationPort = 0; 192767a662ecde33c3979bf02b793d392aca0403162Wink Saville 193767a662ecde33c3979bf02b793d392aca0403162Wink Saville msgType = pdu[index++]; 194767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (msgType != 0){ 195767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.w(TAG, "Received a WAP SMS which is not WDP. Discard."); 1963960ced4638fdb24ddf904fcb6734dae0959671ejsh return Intents.RESULT_SMS_HANDLED; 197767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 198767a662ecde33c3979bf02b793d392aca0403162Wink Saville totalSegments = pdu[index++]; // >=1 199767a662ecde33c3979bf02b793d392aca0403162Wink Saville segment = pdu[index++]; // >=0 200767a662ecde33c3979bf02b793d392aca0403162Wink Saville 2015c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause // Only the first segment contains sourcePort and destination Port 2025c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause if (segment == 0) { 2035c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause //process WDP segment 2045c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause sourcePort = (0xFF & pdu[index++]) << 8; 2055c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause sourcePort |= 0xFF & pdu[index++]; 2065c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause destinationPort = (0xFF & pdu[index++]) << 8; 2075c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause destinationPort |= 0xFF & pdu[index++]; 2085c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause } 209767a662ecde33c3979bf02b793d392aca0403162Wink Saville 210767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Lookup all other related parts 211767a662ecde33c3979bf02b793d392aca0403162Wink Saville StringBuilder where = new StringBuilder("reference_number ="); 212767a662ecde33c3979bf02b793d392aca0403162Wink Saville where.append(referenceNumber); 213767a662ecde33c3979bf02b793d392aca0403162Wink Saville where.append(" AND address = ?"); 214767a662ecde33c3979bf02b793d392aca0403162Wink Saville String[] whereArgs = new String[] {address}; 215767a662ecde33c3979bf02b793d392aca0403162Wink Saville 216767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address 217767a662ecde33c3979bf02b793d392aca0403162Wink Saville + ", src-port = " + sourcePort + ", dst-port = " + destinationPort 218767a662ecde33c3979bf02b793d392aca0403162Wink Saville + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments); 219767a662ecde33c3979bf02b793d392aca0403162Wink Saville 220767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[][] pdus = null; 221767a662ecde33c3979bf02b793d392aca0403162Wink Saville Cursor cursor = null; 222767a662ecde33c3979bf02b793d392aca0403162Wink Saville try { 223767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null); 224767a662ecde33c3979bf02b793d392aca0403162Wink Saville int cursorCount = cursor.getCount(); 225767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (cursorCount != totalSegments - 1) { 226767a662ecde33c3979bf02b793d392aca0403162Wink Saville // We don't have all the parts yet, store this one away 227767a662ecde33c3979bf02b793d392aca0403162Wink Saville ContentValues values = new ContentValues(); 228767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("date", new Long(0)); 229767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index)); 230767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("address", address); 231767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("reference_number", referenceNumber); 232767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("count", totalSegments); 233767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("sequence", segment); 234767a662ecde33c3979bf02b793d392aca0403162Wink Saville values.put("destination_port", destinationPort); 235767a662ecde33c3979bf02b793d392aca0403162Wink Saville 236767a662ecde33c3979bf02b793d392aca0403162Wink Saville mResolver.insert(mRawUri, values); 237767a662ecde33c3979bf02b793d392aca0403162Wink Saville 2383960ced4638fdb24ddf904fcb6734dae0959671ejsh return Intents.RESULT_SMS_HANDLED; 239767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 240767a662ecde33c3979bf02b793d392aca0403162Wink Saville 241767a662ecde33c3979bf02b793d392aca0403162Wink Saville // All the parts are in place, deal with them 242767a662ecde33c3979bf02b793d392aca0403162Wink Saville int pduColumn = cursor.getColumnIndex("pdu"); 243767a662ecde33c3979bf02b793d392aca0403162Wink Saville int sequenceColumn = cursor.getColumnIndex("sequence"); 244767a662ecde33c3979bf02b793d392aca0403162Wink Saville 245767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus = new byte[totalSegments][]; 246767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (int i = 0; i < cursorCount; i++) { 247767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor.moveToNext(); 248767a662ecde33c3979bf02b793d392aca0403162Wink Saville int cursorSequence = (int)cursor.getLong(sequenceColumn); 2495c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause // Read the destination port from the first segment 2505c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause if (cursorSequence == 0) { 2515c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause int destinationPortColumn = cursor.getColumnIndex("destination_port"); 2525c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause destinationPort = (int)cursor.getLong(destinationPortColumn); 2535c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause } 254767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[cursorSequence] = HexDump.hexStringToByteArray( 255767a662ecde33c3979bf02b793d392aca0403162Wink Saville cursor.getString(pduColumn)); 256767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 257767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The last part will be added later 258767a662ecde33c3979bf02b793d392aca0403162Wink Saville 259767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Remove the parts from the database 260767a662ecde33c3979bf02b793d392aca0403162Wink Saville mResolver.delete(mRawUri, where.toString(), whereArgs); 261767a662ecde33c3979bf02b793d392aca0403162Wink Saville } catch (SQLException e) { 262767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.e(TAG, "Can't access multipart SMS database", e); 2633960ced4638fdb24ddf904fcb6734dae0959671ejsh return Intents.RESULT_SMS_GENERIC_ERROR; 264767a662ecde33c3979bf02b793d392aca0403162Wink Saville } finally { 265767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (cursor != null) cursor.close(); 266767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 267767a662ecde33c3979bf02b793d392aca0403162Wink Saville 268767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Build up the data stream 269767a662ecde33c3979bf02b793d392aca0403162Wink Saville ByteArrayOutputStream output = new ByteArrayOutputStream(); 270767a662ecde33c3979bf02b793d392aca0403162Wink Saville for (int i = 0; i < totalSegments-1; i++) { 271767a662ecde33c3979bf02b793d392aca0403162Wink Saville // reassemble the (WSP-)pdu 272767a662ecde33c3979bf02b793d392aca0403162Wink Saville output.write(pdus[i], 0, pdus[i].length); 273767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 274767a662ecde33c3979bf02b793d392aca0403162Wink Saville 275767a662ecde33c3979bf02b793d392aca0403162Wink Saville // This one isn't in the DB, so add it 276767a662ecde33c3979bf02b793d392aca0403162Wink Saville output.write(pdu, index, pdu.length - index); 277767a662ecde33c3979bf02b793d392aca0403162Wink Saville 278767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte[] datagram = output.toByteArray(); 279767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Dispatch the PDU to applications 280767a662ecde33c3979bf02b793d392aca0403162Wink Saville switch (destinationPort) { 281767a662ecde33c3979bf02b793d392aca0403162Wink Saville case SmsHeader.PORT_WAP_PUSH: 282767a662ecde33c3979bf02b793d392aca0403162Wink Saville // Handle the PUSH 2833960ced4638fdb24ddf904fcb6734dae0959671ejsh return mWapPush.dispatchWapPdu(datagram); 284767a662ecde33c3979bf02b793d392aca0403162Wink Saville 285767a662ecde33c3979bf02b793d392aca0403162Wink Saville default:{ 286767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus = new byte[1][]; 287767a662ecde33c3979bf02b793d392aca0403162Wink Saville pdus[0] = datagram; 288767a662ecde33c3979bf02b793d392aca0403162Wink Saville // The messages were sent to any other WAP port 289767a662ecde33c3979bf02b793d392aca0403162Wink Saville dispatchPortAddressedPdus(pdus, destinationPort); 2903960ced4638fdb24ddf904fcb6734dae0959671ejsh return Activity.RESULT_OK; 291767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 292767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 293767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 294767a662ecde33c3979bf02b793d392aca0403162Wink Saville 295767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 2961f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink protected void sendData(String destAddr, String scAddr, int destPort, 2971f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 2981f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 2991f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink scAddr, destAddr, destPort, data, (deliveryIntent != null)); 3001f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink sendSubmitPdu(pdu, sentIntent, deliveryIntent); 3011f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink } 3021f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink 3031f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink /** {@inheritDoc} */ 3041f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink protected void sendText(String destAddr, String scAddr, String text, 3051f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink PendingIntent sentIntent, PendingIntent deliveryIntent) { 3061f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 3071f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink scAddr, destAddr, text, (deliveryIntent != null), null); 3081f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink sendSubmitPdu(pdu, sentIntent, deliveryIntent); 3091f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink } 3101f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink 3111f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink /** {@inheritDoc} */ 31264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink protected void sendMultipartText(String destAddr, String scAddr, 313767a662ecde33c3979bf02b793d392aca0403162Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 314767a662ecde33c3979bf02b793d392aca0403162Wink Saville ArrayList<PendingIntent> deliveryIntents) { 315767a662ecde33c3979bf02b793d392aca0403162Wink Saville 31664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink /** 31764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * TODO(cleanup): There is no real code difference between 31864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * this and the GSM version, and hence it should be moved to 31964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * the base class or consolidated somehow, provided calling 32064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink * the proper submitpdu stuff can be arranged. 32164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink */ 322767a662ecde33c3979bf02b793d392aca0403162Wink Saville 32364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink int refNumber = getNextConcatenatedRef() & 0x00FF; 324767a662ecde33c3979bf02b793d392aca0403162Wink Saville 32564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink for (int i = 0, msgCount = parts.size(); i < msgCount; i++) { 32664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 32764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink concatRef.refNumber = refNumber; 32864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink concatRef.seqNumber = i + 1; // 1-based sequence 32964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink concatRef.msgCount = msgCount; 33064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink concatRef.isEightBits = true; 33164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink SmsHeader smsHeader = new SmsHeader(); 33264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink smsHeader.concatRef = concatRef; 333767a662ecde33c3979bf02b793d392aca0403162Wink Saville 33464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink PendingIntent sentIntent = null; 335767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (sentIntents != null && sentIntents.size() > i) { 336767a662ecde33c3979bf02b793d392aca0403162Wink Saville sentIntent = sentIntents.get(i); 337767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 33864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink 33964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink PendingIntent deliveryIntent = null; 340767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 341767a662ecde33c3979bf02b793d392aca0403162Wink Saville deliveryIntent = deliveryIntents.get(i); 342767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 343767a662ecde33c3979bf02b793d392aca0403162Wink Saville 344fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink UserData uData = new UserData(); 345fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink uData.payloadStr = parts.get(i); 346fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink uData.userDataHeader = smsHeader; 347fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink 348fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destAddr, 349fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink uData, deliveryIntent != null); 350767a662ecde33c3979bf02b793d392aca0403162Wink Saville 35164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink sendSubmitPdu(submitPdu, sentIntent, deliveryIntent); 352767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 353767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 354767a662ecde33c3979bf02b793d392aca0403162Wink Saville 3551f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu, 3561f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink PendingIntent sentIntent, PendingIntent deliveryIntent) { 3571f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) { 358a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng if (sentIntent != null) { 359a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng try { 360a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE); 361a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng } catch (CanceledException ex) {} 362a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng } 363a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng if (Config.LOGD) { 364a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng Log.d(TAG, "Block SMS in Emergency Callback mode"); 365a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng } 366a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng return; 367a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng } 3681f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent); 369a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng } 370a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng 371767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 372767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendSms(SmsTracker tracker) { 373767a662ecde33c3979bf02b793d392aca0403162Wink Saville HashMap map = tracker.mData; 374767a662ecde33c3979bf02b793d392aca0403162Wink Saville 375767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte smsc[] = (byte[]) map.get("smsc"); 376767a662ecde33c3979bf02b793d392aca0403162Wink Saville byte pdu[] = (byte[]) map.get("pdu"); 377767a662ecde33c3979bf02b793d392aca0403162Wink Saville 378767a662ecde33c3979bf02b793d392aca0403162Wink Saville Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 379767a662ecde33c3979bf02b793d392aca0403162Wink Saville 380767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.sendCdmaSms(pdu, reply); 381767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 382767a662ecde33c3979bf02b793d392aca0403162Wink Saville 383767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 384767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void sendMultipartSms (SmsTracker tracker) { 385767a662ecde33c3979bf02b793d392aca0403162Wink Saville Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented"); 386767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 387767a662ecde33c3979bf02b793d392aca0403162Wink Saville 388767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 389867641ece36e2fd17faaea79cf19506ab17177c6jsh protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ 390767a662ecde33c3979bf02b793d392aca0403162Wink Saville // FIXME unit test leaves cm == null. this should change 391117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang 392117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 393117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang if (inEcm.equals("true")) { 394117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang return; 395117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang } 396117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang 397767a662ecde33c3979bf02b793d392aca0403162Wink Saville if (mCm != null) { 398867641ece36e2fd17faaea79cf19506ab17177c6jsh mCm.acknowledgeLastIncomingCdmaSms(success, resultToCause(result), response); 399767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 400767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 401767a662ecde33c3979bf02b793d392aca0403162Wink Saville 402767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 403767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void activateCellBroadcastSms(int activate, Message response) { 404e337d651a5199551ae3d3180176f8ac7d58c9acdjohnwang mCm.setCdmaBroadcastActivation((activate == 0), response); 405767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 406767a662ecde33c3979bf02b793d392aca0403162Wink Saville 407767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 408767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void getCellBroadcastSmsConfig(Message response) { 409767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.getCdmaBroadcastConfig(response); 410767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 411767a662ecde33c3979bf02b793d392aca0403162Wink Saville 412767a662ecde33c3979bf02b793d392aca0403162Wink Saville /** {@inheritDoc} */ 413767a662ecde33c3979bf02b793d392aca0403162Wink Saville protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { 414767a662ecde33c3979bf02b793d392aca0403162Wink Saville mCm.setCdmaBroadcastConfig(configValuesArray, response); 415767a662ecde33c3979bf02b793d392aca0403162Wink Saville } 416767a662ecde33c3979bf02b793d392aca0403162Wink Saville 417867641ece36e2fd17faaea79cf19506ab17177c6jsh private int resultToCause(int rc) { 418867641ece36e2fd17faaea79cf19506ab17177c6jsh switch (rc) { 419867641ece36e2fd17faaea79cf19506ab17177c6jsh case Activity.RESULT_OK: 420867641ece36e2fd17faaea79cf19506ab17177c6jsh case Intents.RESULT_SMS_HANDLED: 421867641ece36e2fd17faaea79cf19506ab17177c6jsh // Cause code is ignored on success. 422867641ece36e2fd17faaea79cf19506ab17177c6jsh return 0; 423867641ece36e2fd17faaea79cf19506ab17177c6jsh case Intents.RESULT_SMS_OUT_OF_MEMORY: 424867641ece36e2fd17faaea79cf19506ab17177c6jsh return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE; 425867641ece36e2fd17faaea79cf19506ab17177c6jsh case Intents.RESULT_SMS_GENERIC_ERROR: 426867641ece36e2fd17faaea79cf19506ab17177c6jsh default: 427867641ece36e2fd17faaea79cf19506ab17177c6jsh return CommandsInterface.CDMA_SMS_FAIL_CAUSE_OTHER_TERMINAL_PROBLEM; 428867641ece36e2fd17faaea79cf19506ab17177c6jsh } 429867641ece36e2fd17faaea79cf19506ab17177c6jsh } 430767a662ecde33c3979bf02b793d392aca0403162Wink Saville} 431