GsmSMSDispatcher.java revision 22d85a8e3a575a6d01d2c788587971657dfe20c6
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); 29822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); 299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) { 30422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response); 305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static int resultToCause(int rc) { 308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (rc) { 309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Activity.RESULT_OK: 310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_HANDLED: 311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Cause code is ignored on success. 312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return 0; 313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_OUT_OF_MEMORY: 314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED; 315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_GENERIC_ERROR: 316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR; 318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Holds all info about a message page needed to assemble a complete 323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * concatenated message 324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final class SmsCbConcatInfo { 326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbHeader mHeader; 328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbLocation mLocation; 329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public SmsCbConcatInfo(SmsCbHeader header, SmsCbLocation location) { 331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mHeader = header; 332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mLocation = location; 333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public int hashCode() { 337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return (mHeader.getSerialNumber() * 31) + mLocation.hashCode(); 338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean equals(Object obj) { 342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (obj instanceof SmsCbConcatInfo) { 343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo other = (SmsCbConcatInfo)obj; 344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Two pages match if they have the same serial number (which includes the 346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // geographical scope and update number), and both pages belong to the same 347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // location (PLMN, plus LAC and CID if these are part of the geographical scope). 348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mHeader.getSerialNumber() == other.mHeader.getSerialNumber() 349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville && mLocation.equals(other.mLocation); 350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return false; 353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Compare the location code for this message to the current location code. The match is 357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * relative to the geographical scope of the message, which determines whether the LAC 358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * and Cell ID are saved in mLocation or set to -1 to match all values. 359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param plmn the current PLMN 361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param lac the current Location Area (GSM) or Service Area (UMTS) 362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param cid the current Cell ID 363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @return true if this message is valid for the current location; false otherwise 364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean matchesLocation(String plmn, int lac, int cid) { 366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mLocation.isInLocationArea(plmn, lac, cid); 367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This map holds incomplete concatenated messages waiting for assembly 371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap = 372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville new HashMap<SmsCbConcatInfo, byte[][]>(); 373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Handle 3GPP format SMS-CB message. 376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param ar the AsyncResult containing the received PDUs 377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void handleBroadcastSms(AsyncResult ar) { 379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville try { 380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[] receivedPdu = (byte[])ar.result; 381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 382cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (VDBG) { 383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < receivedPdu.length; i += 8) { 384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville StringBuilder sb = new StringBuilder("SMS CB pdu data: "); 385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int j = i; j < i + 8 && j < receivedPdu.length; j++) { 386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int b = receivedPdu[j] & 0xff; 387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (b < 0x10) { 388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append('0'); 389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append(Integer.toHexString(b)).append(' '); 391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 392ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, sb.toString()); 393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbHeader header = new SmsCbHeader(receivedPdu); 397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String plmn = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); 3980fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int lac = -1; 3990fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int cid = -1; 4000fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka android.telephony.CellLocation cl = mPhone.getCellLocation(); 4010fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // Check if cell location is GsmCellLocation. This is required to support 4020fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // dual-mode devices such as CDMA/LTE devices that require support for 4030fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // both 3GPP and 3GPP2 format messages 4040fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka if (cl instanceof GsmCellLocation) { 4050fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka GsmCellLocation cellLocation = (GsmCellLocation)cl; 4060fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka lac = cellLocation.getLac(); 4070fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka cid = cellLocation.getCid(); 4080fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka } 409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbLocation location; 411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (header.getGeographicalScope()) { 412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE: 413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, -1); 414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE: 417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE: 418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, cid); 419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE: 422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn); 424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[][] pdus; 428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int pageCount = header.getNumberOfPages(); 429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pageCount > 1) { 430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Multi-page message 431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo concatInfo = new SmsCbConcatInfo(header, location); 432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Try to find other pages of the same message 434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = mSmsCbPageMap.get(concatInfo); 435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus == null) { 437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This is the first page of this message, make room for all 438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // pages and keep until complete 439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[pageCount][]; 440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.put(concatInfo, pdus); 442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Page parameter is one-based 445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[header.getPageIndex() - 1] = receivedPdu; 446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < pdus.length; i++) { 448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus[i] == null) { 449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Still missing pages, exit 450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return; 451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Message complete, remove and dispatch 455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.remove(concatInfo); 456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Single page message 458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[1][]; 459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[0] = receivedPdu; 460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbMessage message = GsmSmsCbMessage.createSmsCbMessage(header, location, pdus); 463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville dispatchBroadcastMessage(message); 464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Remove messages that are out of scope to prevent the map from 466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // growing indefinitely, containing incomplete messages that were 467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // never assembled 468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Iterator<SmsCbConcatInfo> iter = mSmsCbPageMap.keySet().iterator(); 469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville while (iter.hasNext()) { 471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo info = iter.next(); 472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (!info.matchesLocation(plmn, lac, cid)) { 474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville iter.remove(); 475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } catch (RuntimeException e) { 478ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Error in decoding SMS CB pdu", e); 479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville} 482