GsmSMSDispatcher.java revision d720945f2be5ea5fe0faf67e67d9ea0e184eba67
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 { 52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final String TAG = "GSM"; 53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Status report received */ 55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_NEW_SMS_STATUS_REPORT = 100; 56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** New broadcast SMS */ 58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_NEW_BROADCAST_SMS = 101; 59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Result of writing SM to UICC (when SMS-PP service is not available). */ 61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final int EVENT_WRITE_SMS_COMPLETE = 102; 62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** Handler for SMS-PP data download messages to UICC. */ 64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final UsimDataDownloadHandler mDataDownloadHandler; 65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, 67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsUsageMonitor usageMonitor) { 68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville super(phone, storageMonitor, usageMonitor); 69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mDataDownloadHandler = new UsimDataDownloadHandler(mCm); 70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null); 71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); 72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null); 73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public void dispose() { 77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.unSetOnNewGsmSms(this); 78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.unSetOnSmsStatus(this); 79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.unSetOnNewGsmBroadcastSms(this); 80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected String getFormat() { 84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return SmsConstants.FORMAT_3GPP; 85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Handles 3GPP format-specific events coming from the phone stack. 89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Other events are handled by {@link SMSDispatcher#handleMessage}. 90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param msg the message to handle 92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public void handleMessage(Message msg) { 95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (msg.what) { 96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_NEW_SMS_STATUS_REPORT: 97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handleStatusReport((AsyncResult) msg.obj); 98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_NEW_BROADCAST_SMS: 101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handleBroadcastSms((AsyncResult)msg.obj); 102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case EVENT_WRITE_SMS_COMPLETE: 105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville AsyncResult ar = (AsyncResult) msg.obj; 106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (ar.exception == null) { 107ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Successfully wrote SMS-PP message to UICC"); 108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.acknowledgeLastIncomingGsmSms(true, 0, null); 109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 110ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Failed to write SMS-PP message to UICC", ar.exception); 111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.acknowledgeLastIncomingGsmSms(false, 112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR, null); 113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville super.handleMessage(msg); 118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Called when a status report is received. This should correspond to 123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * a previously successful SEND. 124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param ar AsyncResult passed into the message handler. ar.result should 126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * be a String representing the status report PDU, as ASCII hex. 127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void handleStatusReport(AsyncResult ar) { 129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String pduString = (String) ar.result; 130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage sms = SmsMessage.newFromCDS(pduString); 131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms != null) { 133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int tpStatus = sms.getStatus(); 134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int messageRef = sms.messageRef; 135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0, count = deliveryPendingList.size(); i < count; i++) { 136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsTracker tracker = deliveryPendingList.get(i); 137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (tracker.mMessageRef == messageRef) { 138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Found it. Remove from list and broadcast. 139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) { 140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville deliveryPendingList.remove(i); 141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent intent = tracker.mDeliveryIntent; 143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Intent fillIn = new Intent(); 144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString)); 145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville fillIn.putExtra("format", SmsConstants.FORMAT_3GPP); 146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville try { 147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville intent.send(mContext, Activity.RESULT_OK, fillIn); 148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } catch (CanceledException ex) {} 149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Only expect to see one tracker matching this messageref 151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville acknowledgeLastIncomingSms(true, Intents.RESULT_SMS_HANDLED, null); 156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public int dispatchMessage(SmsMessageBase smsb) { 161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // If sms is null, means there was a parsing error. 163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (smsb == null) { 164ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "dispatchMessage: message is null"); 165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_GENERIC_ERROR; 166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage sms = (SmsMessage) smsb; 169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isTypeZero()) { 171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be 172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Displayed/Stored/Notified. They should only be acknowledged. 173ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received short message type 0, Don't display or store it. Send Ack"); 174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Send SMS-PP data download messages to UICC. See 3GPP TS 31.111 section 7.1.1. 178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isUsimDataDownload()) { 179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville UsimServiceTable ust = mPhone.getUsimServiceTable(); 180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // If we receive an SMS-PP message before the UsimServiceTable has been loaded, 181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // assume that the data download service is not present. This is very unlikely to 182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // happen because the IMS connection will not be established until after the ISIM 183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // records have been loaded, after the USIM service table has been loaded. 184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (ust != null && ust.isAvailable( 185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville UsimServiceTable.UsimService.DATA_DL_VIA_SMS_PP)) { 186ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received SMS-PP data download, sending to UICC."); 187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mDataDownloadHandler.startDataDownload(sms); 188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 189ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DATA_DL_VIA_SMS_PP service not available, storing message to UICC."); 190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String smsc = IccUtils.bytesToHexString( 191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( 192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sms.getServiceCenterAddress())); 193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.writeSmsToSim(SmsManager.STATUS_ON_ICC_UNREAD, smsc, 194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville IccUtils.bytesToHexString(sms.getPdu()), 195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville obtainMessage(EVENT_WRITE_SMS_COMPLETE)); 196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Activity.RESULT_OK; // acknowledge after response from write to USIM 197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (mSmsReceiveDisabled) { 201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Device doesn't support SMS service, 202ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received short message on device which doesn't support " 203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville + "SMS service. Ignored."); 204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Special case the message waiting indicator messages 208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville boolean handled = false; 209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (sms.isMWISetMessage()) { 210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mPhone.setVoiceMessageWaiting(1, -1); // line 1: unknown number of msgs waiting 211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handled = sms.isMwiDontStore(); 212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (false) { 213ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled); 214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else if (sms.isMWIClearMessage()) { 216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mPhone.setVoiceMessageWaiting(1, 0); // line 1: no msgs waiting 217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville handled = sms.isMwiDontStore(); 218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (false) { 219ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled); 220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (handled) { 224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_HANDLED; 225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (!mStorageMonitor.isStorageAvailable() && 228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) { 229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // It's a storable message and there's no storage available. Bail. 230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // (See TS 23.038 for a description of class 0 messages.) 231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return Intents.RESULT_SMS_OUT_OF_MEMORY; 232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return dispatchNormalMessage(smsb); 235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendData(String destAddr, String scAddr, int destPort, 240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville scAddr, destAddr, destPort, data, (deliveryIntent != null)); 243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destAddr); 246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 247ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null"); 248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendText(String destAddr, String scAddr, String text, 254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent sentIntent, PendingIntent deliveryIntent) { 255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( 256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville scAddr, destAddr, text, (deliveryIntent != null)); 257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destAddr); 260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 261ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null"); 262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody, 268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville boolean use7bitOnly) { 269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return SmsMessage.calculateLength(messageBody, use7bitOnly); 270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendNewSubmitPdu(String destinationAddress, String scAddress, 275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String message, SmsHeader smsHeader, int encoding, 276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) { 277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress, 278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader), 279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville encoding, smsHeader.languageTable, smsHeader.languageShiftTable); 280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdu != null) { 281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent, 282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville destinationAddress); 283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 284ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null"); 285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void sendSms(SmsTracker tracker) { 291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville HashMap<String, Object> map = tracker.mData; 292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte smsc[] = (byte[]) map.get("smsc"); 294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte pdu[] = (byte[]) map.get("pdu"); 295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); 297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); 298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** {@inheritDoc} */ 301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) { 303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mCm.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response); 304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static int resultToCause(int rc) { 307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (rc) { 308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Activity.RESULT_OK: 309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_HANDLED: 310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Cause code is ignored on success. 311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return 0; 312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_OUT_OF_MEMORY: 313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED; 314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case Intents.RESULT_SMS_GENERIC_ERROR: 315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR; 317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Holds all info about a message page needed to assemble a complete 322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * concatenated message 323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final class SmsCbConcatInfo { 325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbHeader mHeader; 327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final SmsCbLocation mLocation; 328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public SmsCbConcatInfo(SmsCbHeader header, SmsCbLocation location) { 330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mHeader = header; 331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mLocation = location; 332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public int hashCode() { 336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return (mHeader.getSerialNumber() * 31) + mLocation.hashCode(); 337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville @Override 340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean equals(Object obj) { 341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (obj instanceof SmsCbConcatInfo) { 342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo other = (SmsCbConcatInfo)obj; 343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Two pages match if they have the same serial number (which includes the 345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // geographical scope and update number), and both pages belong to the same 346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // location (PLMN, plus LAC and CID if these are part of the geographical scope). 347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mHeader.getSerialNumber() == other.mHeader.getSerialNumber() 348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville && mLocation.equals(other.mLocation); 349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return false; 352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Compare the location code for this message to the current location code. The match is 356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * relative to the geographical scope of the message, which determines whether the LAC 357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * and Cell ID are saved in mLocation or set to -1 to match all values. 358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param plmn the current PLMN 360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param lac the current Location Area (GSM) or Service Area (UMTS) 361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param cid the current Cell ID 362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @return true if this message is valid for the current location; false otherwise 363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville public boolean matchesLocation(String plmn, int lac, int cid) { 365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return mLocation.isInLocationArea(plmn, lac, cid); 366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This map holds incomplete concatenated messages waiting for assembly 370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap = 371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville new HashMap<SmsCbConcatInfo, byte[][]>(); 372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville /** 374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Handle 3GPP format SMS-CB message. 375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * @param ar the AsyncResult containing the received PDUs 376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void handleBroadcastSms(AsyncResult ar) { 378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville try { 379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[] receivedPdu = (byte[])ar.result; 380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (false) { 382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < receivedPdu.length; i += 8) { 383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville StringBuilder sb = new StringBuilder("SMS CB pdu data: "); 384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int j = i; j < i + 8 && j < receivedPdu.length; j++) { 385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int b = receivedPdu[j] & 0xff; 386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (b < 0x10) { 387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append('0'); 388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville sb.append(Integer.toHexString(b)).append(' '); 390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 391ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, sb.toString()); 392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbHeader header = new SmsCbHeader(receivedPdu); 396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville String plmn = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); 3970fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int lac = -1; 3980fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka int cid = -1; 3990fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka android.telephony.CellLocation cl = mPhone.getCellLocation(); 4000fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // Check if cell location is GsmCellLocation. This is required to support 4010fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // dual-mode devices such as CDMA/LTE devices that require support for 4020fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka // both 3GPP and 3GPP2 format messages 4030fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka if (cl instanceof GsmCellLocation) { 4040fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka GsmCellLocation cellLocation = (GsmCellLocation)cl; 4050fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka lac = cellLocation.getLac(); 4060fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka cid = cellLocation.getCid(); 4070fd49b6b31960a768702d202a066b1088ec489a1Alex Yakavenka } 408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbLocation location; 410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville switch (header.getGeographicalScope()) { 411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE: 412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, -1); 413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE: 416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE: 417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn, lac, cid); 418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE: 421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville default: 422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville location = new SmsCbLocation(plmn); 423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville break; 424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville byte[][] pdus; 427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville int pageCount = header.getNumberOfPages(); 428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pageCount > 1) { 429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Multi-page message 430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo concatInfo = new SmsCbConcatInfo(header, location); 431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Try to find other pages of the same message 433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = mSmsCbPageMap.get(concatInfo); 434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus == null) { 436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // This is the first page of this message, make room for all 437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // pages and keep until complete 438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[pageCount][]; 439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.put(concatInfo, pdus); 441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Page parameter is one-based 444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[header.getPageIndex() - 1] = receivedPdu; 445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville for (int i = 0; i < pdus.length; i++) { 447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (pdus[i] == null) { 448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Still missing pages, exit 449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return; 450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Message complete, remove and dispatch 454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville mSmsCbPageMap.remove(concatInfo); 455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } else { 456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Single page message 457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus = new byte[1][]; 458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville pdus[0] = receivedPdu; 459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbMessage message = GsmSmsCbMessage.createSmsCbMessage(header, location, pdus); 462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville dispatchBroadcastMessage(message); 463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // Remove messages that are out of scope to prevent the map from 465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // growing indefinitely, containing incomplete messages that were 466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville // never assembled 467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville Iterator<SmsCbConcatInfo> iter = mSmsCbPageMap.keySet().iterator(); 468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville while (iter.hasNext()) { 470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville SmsCbConcatInfo info = iter.next(); 471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (!info.matchesLocation(plmn, lac, cid)) { 473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville iter.remove(); 474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } catch (RuntimeException e) { 477ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Error in decoding SMS CB pdu", e); 478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville} 481