1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/* 2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2006 The Android Open Source Project 3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License. 6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at 7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * http://www.apache.org/licenses/LICENSE-2.0 9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software 11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and 14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License. 15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.gsm; 18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 19c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.Activity; 20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent; 21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent.CanceledException; 22c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Intent; 23c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult; 24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message; 25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.SystemProperties; 26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms; 27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms.Intents; 28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.PhoneNumberUtils; 29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.SmsCbLocation; 30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.SmsCbMessage; 31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.SmsManager; 32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.gsm.GsmCellLocation; 33ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog; 34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.CommandsInterface; 36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.GsmAlphabet; 37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneBase; 38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsConstants; 39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SMSDispatcher; 40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsHeader; 41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsMessageBase; 42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsStorageMonitor; 43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsUsageMonitor; 44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.TelephonyProperties; 45d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils; 46d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UsimServiceTable; 47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.HashMap; 49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.Iterator; 50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmSMSDispatcher extends SMSDispatcher { 52cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville private static final String TAG = "GsmSMSDispatcher"; 53cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville private static final boolean VDBG = false; 54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Status report received */ 56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_NEW_SMS_STATUS_REPORT = 100; 57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** New broadcast SMS */ 59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_NEW_BROADCAST_SMS = 101; 60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Result of writing SM to UICC (when SMS-PP service is not available). */ 62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_WRITE_SMS_COMPLETE = 102; 63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Handler for SMS-PP data download messages to UICC. */ 65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final UsimDataDownloadHandler mDataDownloadHandler; 66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, 68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsUsageMonitor usageMonitor) { 69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville super(phone, storageMonitor, usageMonitor); 7022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mDataDownloadHandler = new UsimDataDownloadHandler(mCi); 7122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.setOnNewGsmSms(this, EVENT_NEW_SMS, null); 7222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); 7322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null); 74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public void dispose() { 7822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.unSetOnNewGsmSms(this); 7922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.unSetOnSmsStatus(this); 8022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.unSetOnNewGsmBroadcastSms(this); 81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected String getFormat() { 85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return SmsConstants.FORMAT_3GPP; 86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Handles 3GPP format-specific events coming from the phone stack. 90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Other events are handled by {@link SMSDispatcher#handleMessage}. 91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param msg the message to handle 93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public void handleMessage(Message msg) { 96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (msg.what) { 97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_NEW_SMS_STATUS_REPORT: 98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handleStatusReport((AsyncResult) msg.obj); 99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_NEW_BROADCAST_SMS: 102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handleBroadcastSms((AsyncResult)msg.obj); 103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_WRITE_SMS_COMPLETE: 106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville AsyncResult ar = (AsyncResult) msg.obj; 107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (ar.exception == null) { 108ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Successfully wrote SMS-PP message to UICC"); 10922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(true, 0, null); 110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 111ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Failed to write SMS-PP message to UICC", ar.exception); 11222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(false, 113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR, null); 114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville super.handleMessage(msg); 119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Called when a status report is received. This should correspond to 124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * a previously successful SEND. 125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param ar AsyncResult passed into the message handler. ar.result should 127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * be a String representing the status report PDU, as ASCII hex. 128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void handleStatusReport(AsyncResult ar) { 130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String pduString = (String) ar.result; 131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage sms = SmsMessage.newFromCDS(pduString); 132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms != null) { 134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int tpStatus = sms.getStatus(); 13522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville int messageRef = sms.mMessageRef; 136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0, count = deliveryPendingList.size(); i < count; i++) { 137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsTracker tracker = deliveryPendingList.get(i); 138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (tracker.mMessageRef == messageRef) { 139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Found it. Remove from list and broadcast. 140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) { 141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville deliveryPendingList.remove(i); 142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent intent = tracker.mDeliveryIntent; 144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Intent fillIn = new Intent(); 145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString)); 146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville fillIn.putExtra("format", SmsConstants.FORMAT_3GPP); 147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville try { 148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville intent.send(mContext, Activity.RESULT_OK, fillIn); 149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } catch (CanceledException ex) {} 150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Only expect to see one tracker matching this messageref 152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville acknowledgeLastIncomingSms(true, Intents.RESULT_SMS_HANDLED, null); 157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public int dispatchMessage(SmsMessageBase smsb) { 162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // If sms is null, means there was a parsing error. 164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (smsb == null) { 165ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "dispatchMessage: message is null"); 166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_GENERIC_ERROR; 167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage sms = (SmsMessage) smsb; 170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isTypeZero()) { 172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be 173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Displayed/Stored/Notified. They should only be acknowledged. 174ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received short message type 0, Don't display or store it. Send Ack"); 175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Send SMS-PP data download messages to UICC. See 3GPP TS 31.111 section 7.1.1. 179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isUsimDataDownload()) { 180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville UsimServiceTable ust = mPhone.getUsimServiceTable(); 181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // If we receive an SMS-PP message before the UsimServiceTable has been loaded, 182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // assume that the data download service is not present. This is very unlikely to 183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // happen because the IMS connection will not be established until after the ISIM 184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // records have been loaded, after the USIM service table has been loaded. 185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (ust != null && ust.isAvailable( 186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville UsimServiceTable.UsimService.DATA_DL_VIA_SMS_PP)) { 187ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received SMS-PP data download, sending to UICC."); 188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mDataDownloadHandler.startDataDownload(sms); 189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 190ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DATA_DL_VIA_SMS_PP service not available, storing message to UICC."); 191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String smsc = IccUtils.bytesToHexString( 192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( 193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sms.getServiceCenterAddress())); 19422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.writeSmsToSim(SmsManager.STATUS_ON_ICC_UNREAD, smsc, 195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville IccUtils.bytesToHexString(sms.getPdu()), 196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville obtainMessage(EVENT_WRITE_SMS_COMPLETE)); 197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Activity.RESULT_OK; // acknowledge after response from write to USIM 198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (mSmsReceiveDisabled) { 202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Device doesn't support SMS service, 203ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received short message on device which doesn't support " 204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville + "SMS service. Ignored."); 205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Special case the message waiting indicator messages 209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville boolean handled = false; 210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isMWISetMessage()) { 211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mPhone.setVoiceMessageWaiting(1, -1); // line 1: unknown number of msgs waiting 212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handled = sms.isMwiDontStore(); 213cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (VDBG) { 214ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled); 215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else if (sms.isMWIClearMessage()) { 217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mPhone.setVoiceMessageWaiting(1, 0); // line 1: no msgs waiting 218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handled = sms.isMwiDontStore(); 219cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (VDBG) { 220ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled); 221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (handled) { 225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (!mStorageMonitor.isStorageAvailable() && 229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) { 230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // It's a storable message and there's no storage available. Bail. 231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // (See TS 23.038 for a description of class 0 messages.) 232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_OUT_OF_MEMORY; 233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return dispatchNormalMessage(smsb); 236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendData(String destAddr, String scAddr, int destPort, 241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville scAddr, destAddr, destPort, data, (deliveryIntent != null)); 244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destAddr); 247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 248ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null"); 249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendText(String destAddr, String scAddr, String text, 255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent sentIntent, PendingIntent deliveryIntent) { 256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville scAddr, destAddr, text, (deliveryIntent != null)); 258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destAddr); 261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 262ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null"); 263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody, 269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville boolean use7bitOnly) { 270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return SmsMessage.calculateLength(messageBody, use7bitOnly); 271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendNewSubmitPdu(String destinationAddress, String scAddress, 276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String message, SmsHeader smsHeader, int encoding, 277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) { 278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress, 279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader), 280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville encoding, smsHeader.languageTable, smsHeader.languageShiftTable); 281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destinationAddress); 284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 285ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null"); 286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendSms(SmsTracker tracker) { 292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville HashMap<String, Object> map = tracker.mData; 293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte smsc[] = (byte[]) map.get("smsc"); 295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte pdu[] = (byte[]) map.get("pdu"); 296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 298454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks 299454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks if (tracker.mRetryCount > 0) { 300454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks Rlog.d(TAG, "sendSms: " 301454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks + " mRetryCount=" + tracker.mRetryCount 302454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks + " mMessageRef=" + tracker.mMessageRef 303454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks + " SS=" + mPhone.getServiceState().getState()); 304454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks 305454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks // per TS 23.040 Section 9.2.3.6: If TP-MTI SMS-SUBMIT (0x01) type 306454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks // TP-RD (bit 2) is 1 for retry 307454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks // and TP-MR is set to previously failed sms TP-MR 308454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks if (((0x01 & pdu[0]) == 0x01)) { 309454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks pdu[0] |= 0x04; // TP-RD 310454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks pdu[1] = (byte) tracker.mMessageRef; // TP-MR 311454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } 312454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } 31322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); 314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) { 31922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response); 320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static int resultToCause(int rc) { 323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (rc) { 324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Activity.RESULT_OK: 325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_HANDLED: 326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Cause code is ignored on success. 327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return 0; 328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_OUT_OF_MEMORY: 329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED; 330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_GENERIC_ERROR: 331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR; 333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Holds all info about a message page needed to assemble a complete 338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * concatenated message 339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final class SmsCbConcatInfo { 341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbHeader mHeader; 343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbLocation mLocation; 344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public SmsCbConcatInfo(SmsCbHeader header, SmsCbLocation location) { 346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mHeader = header; 347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mLocation = location; 348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public int hashCode() { 352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return (mHeader.getSerialNumber() * 31) + mLocation.hashCode(); 353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean equals(Object obj) { 357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (obj instanceof SmsCbConcatInfo) { 358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo other = (SmsCbConcatInfo)obj; 359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Two pages match if they have the same serial number (which includes the 361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // geographical scope and update number), and both pages belong to the same 362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // location (PLMN, plus LAC and CID if these are part of the geographical scope). 363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mHeader.getSerialNumber() == other.mHeader.getSerialNumber() 364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville && mLocation.equals(other.mLocation); 365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return false; 368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Compare the location code for this message to the current location code. The match is 372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * relative to the geographical scope of the message, which determines whether the LAC 373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * and Cell ID are saved in mLocation or set to -1 to match all values. 374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param plmn the current PLMN 376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param lac the current Location Area (GSM) or Service Area (UMTS) 377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param cid the current Cell ID 378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @return true if this message is valid for the current location; false otherwise 379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean matchesLocation(String plmn, int lac, int cid) { 381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mLocation.isInLocationArea(plmn, lac, cid); 382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This map holds incomplete concatenated messages waiting for assembly 386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap = 387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville new HashMap<SmsCbConcatInfo, byte[][]>(); 388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Handle 3GPP format SMS-CB message. 391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param ar the AsyncResult containing the received PDUs 392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void handleBroadcastSms(AsyncResult ar) { 394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville try { 395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[] receivedPdu = (byte[])ar.result; 396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 397cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (VDBG) { 398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < receivedPdu.length; i += 8) { 399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville StringBuilder sb = new StringBuilder("SMS CB pdu data: "); 400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int j = i; j < i + 8 && j < receivedPdu.length; j++) { 401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int b = receivedPdu[j] & 0xff; 402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (b < 0x10) { 403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append('0'); 404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append(Integer.toHexString(b)).append(' '); 406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 407ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, sb.toString()); 408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbHeader header = new SmsCbHeader(receivedPdu); 412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String plmn = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); 4130fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int lac = -1; 4140fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int cid = -1; 4150fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka android.telephony.CellLocation cl = mPhone.getCellLocation(); 4160fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // Check if cell location is GsmCellLocation. This is required to support 4170fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // dual-mode devices such as CDMA/LTE devices that require support for 4180fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // both 3GPP and 3GPP2 format messages 4190fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka if (cl instanceof GsmCellLocation) { 4200fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka GsmCellLocation cellLocation = (GsmCellLocation)cl; 4210fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka lac = cellLocation.getLac(); 4220fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka cid = cellLocation.getCid(); 4230fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka } 424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbLocation location; 426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (header.getGeographicalScope()) { 427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE: 428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, -1); 429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE: 432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE: 433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, cid); 434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE: 437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn); 439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[][] pdus; 443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int pageCount = header.getNumberOfPages(); 444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pageCount > 1) { 445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Multi-page message 446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo concatInfo = new SmsCbConcatInfo(header, location); 447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Try to find other pages of the same message 449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = mSmsCbPageMap.get(concatInfo); 450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus == null) { 452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This is the first page of this message, make room for all 453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // pages and keep until complete 454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[pageCount][]; 455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.put(concatInfo, pdus); 457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Page parameter is one-based 460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[header.getPageIndex() - 1] = receivedPdu; 461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < pdus.length; i++) { 463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus[i] == null) { 464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Still missing pages, exit 465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return; 466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Message complete, remove and dispatch 470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.remove(concatInfo); 471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Single page message 473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[1][]; 474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[0] = receivedPdu; 475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbMessage message = GsmSmsCbMessage.createSmsCbMessage(header, location, pdus); 478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville dispatchBroadcastMessage(message); 479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Remove messages that are out of scope to prevent the map from 481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // growing indefinitely, containing incomplete messages that were 482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // never assembled 483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Iterator<SmsCbConcatInfo> iter = mSmsCbPageMap.keySet().iterator(); 484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville while (iter.hasNext()) { 486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo info = iter.next(); 487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (!info.matchesLocation(plmn, lac, cid)) { 489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville iter.remove(); 490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } catch (RuntimeException e) { 493ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Error in decoding SMS CB pdu", e); 494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville} 497