10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2011 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.gsm; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.provider.Telephony.Sms.Intents; 240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.PhoneNumberUtils; 25ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog; 260d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.SmsManager; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandsInterface; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.cat.ComprehensionTlvTag; 30d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccIoResult; 31d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils; 320d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.uicc.UsimServiceTable; 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handler for SMS-PP data download messages. 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See 3GPP TS 31.111 section 7.1.1 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class UsimDataDownloadHandler extends Handler { 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String TAG = "UsimDataDownloadHandler"; 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** BER-TLV tag for SMS-PP download. TS 31.111 section 9.1. */ 420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int BER_SMS_PP_DOWNLOAD_TAG = 0xd1; 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Device identity value for UICC (destination). */ 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int DEV_ID_UICC = 0x81; 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Device identity value for network (source). */ 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int DEV_ID_NETWORK = 0x83; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Message containing new SMS-PP message to process. */ 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_START_DATA_DOWNLOAD = 1; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Response to SMS-PP download envelope command. */ 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_ENVELOPE_RESPONSE = 2; 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Result of writing SM to UICC (when SMS-PP service is not available). */ 570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static final int EVENT_WRITE_SMS_COMPLETE = 3; 580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 5922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville private final CommandsInterface mCi; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public UsimDataDownloadHandler(CommandsInterface commandsInterface) { 6222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi = commandsInterface; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Handle SMS-PP data download messages. Normally these are automatically handled by the 670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * radio, but we may have to deal with this type of SM arriving via the IMS stack. If the 680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * data download service is not enabled, try to write to the USIM as an SMS, and send the 690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * UICC response as the acknowledgment to the SMSC. 700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * 710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param ust the UsimServiceTable, to check if data download is enabled 720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param smsMessage the SMS message to process 730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @return {@code Activity.RESULT_OK} on success; {@code RESULT_SMS_GENERIC_ERROR} on failure 740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby int handleUsimDataDownload(UsimServiceTable ust, SmsMessage smsMessage) { 760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // If we receive an SMS-PP message before the UsimServiceTable has been loaded, 770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // assume that the data download service is not present. This is very unlikely to 780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // happen because the IMS connection will not be established until after the ISIM 790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // records have been loaded, after the USIM service table has been loaded. 800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (ust != null && ust.isAvailable( 810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby UsimServiceTable.UsimService.DATA_DL_VIA_SMS_PP)) { 820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "Received SMS-PP data download, sending to UICC."); 830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return startDataDownload(smsMessage); 840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "DATA_DL_VIA_SMS_PP service not available, storing message to UICC."); 860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby String smsc = IccUtils.bytesToHexString( 870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( 880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby smsMessage.getServiceCenterAddress())); 890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCi.writeSmsToSim(SmsManager.STATUS_ON_ICC_UNREAD, smsc, 900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby IccUtils.bytesToHexString(smsMessage.getPdu()), 910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby obtainMessage(EVENT_WRITE_SMS_COMPLETE)); 920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return Activity.RESULT_OK; // acknowledge after response from write to USIM 930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Start an SMS-PP data download for the specified message. Can be called from a different 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * thread than this Handler is running on. 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param smsMessage the message to process 1020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @return {@code Activity.RESULT_OK} on success; {@code RESULT_SMS_GENERIC_ERROR} on failure 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int startDataDownload(SmsMessage smsMessage) { 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sendMessage(obtainMessage(EVENT_START_DATA_DOWNLOAD, smsMessage))) { 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return Activity.RESULT_OK; // we will send SMS ACK/ERROR based on UICC response 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 108ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "startDataDownload failed to send message to start data download."); 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return Intents.RESULT_SMS_GENERIC_ERROR; 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void handleDataDownload(SmsMessage smsMessage) { 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dcs = smsMessage.getDataCodingScheme(); 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int pid = smsMessage.getProtocolIdentifier(); 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] pdu = smsMessage.getPdu(); // includes SC address 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int scAddressLength = pdu[0] & 0xff; 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tpduIndex = scAddressLength + 1; // start of TPDU 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tpduLength = pdu.length - tpduIndex; 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int bodyLength = getEnvelopeBodyLength(scAddressLength, tpduLength); 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Add 1 byte for SMS-PP download tag and 1-2 bytes for BER-TLV length. 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // See ETSI TS 102 223 Annex C for encoding of length and tags. 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int totalLength = bodyLength + 1 + (bodyLength > 127 ? 2 : 1); 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] envelope = new byte[totalLength]; 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int index = 0; 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // SMS-PP download tag and length (assumed to be < 256 bytes). 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) BER_SMS_PP_DOWNLOAD_TAG; 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bodyLength > 127) { 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) 0x81; // length 128-255 encoded as 0x81 + length 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) bodyLength; 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Device identities TLV 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) (0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value()); 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) 2; 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) DEV_ID_NETWORK; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) DEV_ID_UICC; 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Address TLV (if present). Encoded length is assumed to be < 127 bytes. 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (scAddressLength != 0) { 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) ComprehensionTlvTag.ADDRESS.value(); 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) scAddressLength; 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(pdu, 1, envelope, index, scAddressLength); 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville index += scAddressLength; 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // SMS TPDU TLV. Length is assumed to be < 256 bytes. 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) (0x80 | ComprehensionTlvTag.SMS_TPDU.value()); 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tpduLength > 127) { 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) 0x81; // length 128-255 encoded as 0x81 + length 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville envelope[index++] = (byte) tpduLength; 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(pdu, tpduIndex, envelope, index, tpduLength); 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville index += tpduLength; 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Verify that we calculated the payload size correctly. 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (index != envelope.length) { 163ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "startDataDownload() calculated incorrect envelope length, aborting."); 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville acknowledgeSmsWithError(CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR); 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String encodedEnvelope = IccUtils.bytesToHexString(envelope); 16922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.sendEnvelopeWithStatus(encodedEnvelope, obtainMessage( 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville EVENT_SEND_ENVELOPE_RESPONSE, new int[]{ dcs, pid })); 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Return the size in bytes of the envelope to send to the UICC, excluding the 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS-PP download tag byte and length byte(s). If the size returned is <= 127, 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the BER-TLV length will be encoded in 1 byte, otherwise 2 bytes are required. 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddressLength the length of the SMSC address, or zero if not present 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tpduLength the length of the TPDU from the SMS-PP message 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the number of bytes to allocate for the envelope command 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int getEnvelopeBodyLength(int scAddressLength, int tpduLength) { 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Add 4 bytes for device identities TLV + 1 byte for SMS TPDU tag byte 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int length = tpduLength + 5; 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Add 1 byte for TPDU length, or 2 bytes if length > 127 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length += (tpduLength > 127 ? 2 : 1); 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Add length of address tag, if present (+ 2 bytes for tag and length) 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (scAddressLength != 0) { 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = length + 2 + scAddressLength; 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return length; 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handle the response to the ENVELOPE command. 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param response UICC response encoded as hexadecimal digits. First two bytes are the 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * UICC SW1 and SW2 status bytes. 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void sendSmsAckForEnvelopeResponse(IccIoResult response, int dcs, int pid) { 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int sw1 = response.sw1; 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int sw2 = response.sw2; 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean success; 2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) { 205ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "USIM data download succeeded: " + response.toString()); 2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville success = true; 2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (sw1 == 0x93 && sw2 == 0x00) { 208ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "USIM data download failed: Toolkit busy"); 2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville acknowledgeSmsWithError(CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_APP_TOOLKIT_BUSY); 2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (sw1 == 0x62 || sw1 == 0x63) { 212ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "USIM data download failed: " + response.toString()); 2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville success = false; 2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 215ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Unexpected SW1/SW2 response from UICC: " + response.toString()); 2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville success = false; 2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] responseBytes = response.payload; 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (responseBytes == null || responseBytes.length == 0) { 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (success) { 22222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(true, 0, null); 2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville acknowledgeSmsWithError( 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR); 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] smsAckPdu; 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int index = 0; 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (success) { 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu = new byte[responseBytes.length + 5]; 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = 0x00; // TP-MTI, TP-UDHI 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = 0x07; // TP-PI: TP-PID, TP-DCS, TP-UDL present 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu = new byte[responseBytes.length + 6]; 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = 0x00; // TP-MTI, TP-UDHI 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = (byte) 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR; // TP-FCS 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = 0x07; // TP-PI: TP-PID, TP-DCS, TP-UDL present 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = (byte) pid; 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = (byte) dcs; 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (is7bitDcs(dcs)) { 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int septetCount = responseBytes.length * 8 / 7; 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = (byte) septetCount; 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsAckPdu[index++] = (byte) responseBytes.length; 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(responseBytes, 0, smsAckPdu, index, responseBytes.length); 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 25622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeIncomingGsmSmsWithPdu(success, 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville IccUtils.bytesToHexString(smsAckPdu), null); 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void acknowledgeSmsWithError(int cause) { 26122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi.acknowledgeLastIncomingGsmSms(false, cause, null); 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns whether the DCS is 7 bit. If so, set TP-UDL to the septet count of TP-UD; 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * otherwise, set TP-UDL to the octet count of TP-UD. 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param dcs the TP-Data-Coding-Scheme field from the original download SMS 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the DCS specifies 7 bit encoding; false otherwise 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean is7bitDcs(int dcs) { 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // See 3GPP TS 23.038 section 4 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return ((dcs & 0x8C) == 0x00) || ((dcs & 0xF4) == 0xF0); 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handle UICC envelope response and send SMS acknowledgement. 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg the message to handle 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 2820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby AsyncResult ar; 2830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msg.what) { 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_START_DATA_DOWNLOAD: 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleDataDownload((SmsMessage) msg.obj); 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_ENVELOPE_RESPONSE: 2900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby ar = (AsyncResult) msg.obj; 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception != null) { 293ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "UICC Send Envelope failure, exception: " + ar.exception); 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville acknowledgeSmsWithError( 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR); 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] dcsPid = (int[]) ar.userObj; 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendSmsAckForEnvelopeResponse((IccIoResult) ar.result, dcsPid[0], dcsPid[1]); 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby case EVENT_WRITE_SMS_COMPLETE: 3040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby ar = (AsyncResult) msg.obj; 3050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (ar.exception == null) { 3060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "Successfully wrote SMS-PP message to UICC"); 3070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCi.acknowledgeLastIncomingGsmSms(true, 0, null); 3080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 3090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "Failed to write SMS-PP message to UICC", ar.exception); 3100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCi.acknowledgeLastIncomingGsmSms(false, 3110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR, null); 3120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 3130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby break; 3140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 316ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Ignoring unexpected message, what=" + msg.what); 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 320