1ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby/* 2ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Copyright (C) 2011 The Android Open Source Project 3ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 4ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 5ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * you may not use this file except in compliance with the License. 6ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * You may obtain a copy of the License at 7ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 8ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * http://www.apache.org/licenses/LICENSE-2.0 9ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 10ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Unless required by applicable law or agreed to in writing, software 11ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 12ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * See the License for the specific language governing permissions and 14ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * limitations under the License. 15ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 16ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 17ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambypackage com.android.internal.telephony.gsm; 18ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 19ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.app.Activity; 20ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.os.AsyncResult; 21ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.os.Handler; 22ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.os.Message; 23ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.provider.Telephony.Sms.Intents; 24ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport android.util.Log; 25ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 26ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport com.android.internal.telephony.CommandsInterface; 27ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport com.android.internal.telephony.IccIoResult; 28ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport com.android.internal.telephony.IccUtils; 29ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambyimport com.android.internal.telephony.cat.ComprehensionTlvTag; 30ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 31ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby/** 32ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Handler for SMS-PP data download messages. 33ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * See 3GPP TS 31.111 section 7.1.1 34ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 35ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hambypublic class UsimDataDownloadHandler extends Handler { 36ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final String TAG = "UsimDataDownloadHandler"; 37ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 38ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** BER-TLV tag for SMS-PP download. TS 31.111 section 9.1. */ 39ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final int BER_SMS_PP_DOWNLOAD_TAG = 0xd1; 40ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 41ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** Device identity value for UICC (destination). */ 42ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final int DEV_ID_UICC = 0x81; 43ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 44ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** Device identity value for network (source). */ 45ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final int DEV_ID_NETWORK = 0x83; 46ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 47ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** Message containing new SMS-PP message to process. */ 48ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final int EVENT_START_DATA_DOWNLOAD = 1; 49ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 50ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** Response to SMS-PP download envelope command. */ 51ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static final int EVENT_SEND_ENVELOPE_RESPONSE = 2; 52ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 53ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private final CommandsInterface mCI; 54ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 55ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby public UsimDataDownloadHandler(CommandsInterface commandsInterface) { 56ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby mCI = commandsInterface; 57ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 58ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 59ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** 60ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Start an SMS-PP data download for the specified message. Can be called from a different 61ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * thread than this Handler is running on. 62ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 63ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param smsMessage the message to process 64ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @return Activity.RESULT_OK on success; Intents.RESULT_SMS_GENERIC_ERROR on failure 65ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 66ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby public int startDataDownload(SmsMessage smsMessage) { 67ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (sendMessage(obtainMessage(EVENT_START_DATA_DOWNLOAD, smsMessage))) { 68ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return Activity.RESULT_OK; // we will send SMS ACK/ERROR based on UICC response 69ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else { 70ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "startDataDownload failed to send message to start data download."); 71ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return Intents.RESULT_SMS_GENERIC_ERROR; 72ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 73ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 74ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 75ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private void handleDataDownload(SmsMessage smsMessage) { 76ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int dcs = smsMessage.getDataCodingScheme(); 77ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int pid = smsMessage.getProtocolIdentifier(); 78ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby byte[] pdu = smsMessage.getPdu(); // includes SC address 79ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 80ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int scAddressLength = pdu[0] & 0xff; 81ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int tpduIndex = scAddressLength + 1; // start of TPDU 82ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int tpduLength = pdu.length - tpduIndex; 83ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 84ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int bodyLength = getEnvelopeBodyLength(scAddressLength, tpduLength); 85ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 86ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Add 1 byte for SMS-PP download tag and 1-2 bytes for BER-TLV length. 87ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // See ETSI TS 102 223 Annex C for encoding of length and tags. 88ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int totalLength = bodyLength + 1 + (bodyLength > 127 ? 2 : 1); 89ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 90ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby byte[] envelope = new byte[totalLength]; 91ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int index = 0; 92ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 93ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // SMS-PP download tag and length (assumed to be < 256 bytes). 94ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) BER_SMS_PP_DOWNLOAD_TAG; 95ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (bodyLength > 127) { 96ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) 0x81; // length 128-255 encoded as 0x81 + length 97ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 98ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) bodyLength; 99ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 100ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Device identities TLV 101ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) (0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value()); 102ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) 2; 103ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) DEV_ID_NETWORK; 104ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) DEV_ID_UICC; 105ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 106ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Address TLV (if present). Encoded length is assumed to be < 127 bytes. 107ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (scAddressLength != 0) { 108ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) ComprehensionTlvTag.ADDRESS.value(); 109ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) scAddressLength; 110ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby System.arraycopy(pdu, 1, envelope, index, scAddressLength); 111ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby index += scAddressLength; 112ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 113ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 114ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // SMS TPDU TLV. Length is assumed to be < 256 bytes. 115ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) (0x80 | ComprehensionTlvTag.SMS_TPDU.value()); 116ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (tpduLength > 127) { 117ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) 0x81; // length 128-255 encoded as 0x81 + length 118ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 119ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby envelope[index++] = (byte) tpduLength; 120ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby System.arraycopy(pdu, tpduIndex, envelope, index, tpduLength); 121ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby index += tpduLength; 122ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 123ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Verify that we calculated the payload size correctly. 124ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (index != envelope.length) { 125ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "startDataDownload() calculated incorrect envelope length, aborting."); 126ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby acknowledgeSmsWithError(CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR); 127ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return; 128ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 129ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 130ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby String encodedEnvelope = IccUtils.bytesToHexString(envelope); 131ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby mCI.sendEnvelopeWithStatus(encodedEnvelope, obtainMessage( 132ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby EVENT_SEND_ENVELOPE_RESPONSE, new int[]{ dcs, pid })); 133ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 134ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 135ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** 136ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Return the size in bytes of the envelope to send to the UICC, excluding the 137ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * SMS-PP download tag byte and length byte(s). If the size returned is <= 127, 138ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * the BER-TLV length will be encoded in 1 byte, otherwise 2 bytes are required. 139ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 140ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param scAddressLength the length of the SMSC address, or zero if not present 141ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param tpduLength the length of the TPDU from the SMS-PP message 142ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @return the number of bytes to allocate for the envelope command 143ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 144ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static int getEnvelopeBodyLength(int scAddressLength, int tpduLength) { 145ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Add 4 bytes for device identities TLV + 1 byte for SMS TPDU tag byte 146ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int length = tpduLength + 5; 147ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Add 1 byte for TPDU length, or 2 bytes if length > 127 148ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby length += (tpduLength > 127 ? 2 : 1); 149ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // Add length of address tag, if present (+ 2 bytes for tag and length) 150ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (scAddressLength != 0) { 151ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby length = length + 2 + scAddressLength; 152ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 153ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return length; 154ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 155ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 156ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** 157ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Handle the response to the ENVELOPE command. 158ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param response UICC response encoded as hexadecimal digits. First two bytes are the 159ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * UICC SW1 and SW2 status bytes. 160ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 161ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private void sendSmsAckForEnvelopeResponse(IccIoResult response, int dcs, int pid) { 162ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int sw1 = response.sw1; 163ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int sw2 = response.sw2; 164ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 165ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby boolean success; 166ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) { 167ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.d(TAG, "USIM data download succeeded: " + response.toString()); 168ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby success = true; 169ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else if (sw1 == 0x93 && sw2 == 0x00) { 170ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "USIM data download failed: Toolkit busy"); 171ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby acknowledgeSmsWithError(CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_APP_TOOLKIT_BUSY); 172ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return; 173ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else if (sw1 == 0x62 || sw1 == 0x63) { 174ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "USIM data download failed: " + response.toString()); 175ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby success = false; 176ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else { 177ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "Unexpected SW1/SW2 response from UICC: " + response.toString()); 178ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby success = false; 179ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 180ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 181ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby byte[] responseBytes = response.payload; 182ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (responseBytes == null || responseBytes.length == 0) { 183ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (success) { 184ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby mCI.acknowledgeLastIncomingGsmSms(true, 0, null); 185ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else { 186ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby acknowledgeSmsWithError( 187ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR); 188ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 189ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return; 190ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 191ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 192ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby byte[] smsAckPdu; 193ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int index = 0; 194ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (success) { 195ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu = new byte[responseBytes.length + 5]; 196ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = 0x00; // TP-MTI, TP-UDHI 197ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = 0x07; // TP-PI: TP-PID, TP-DCS, TP-UDL present 198ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else { 199ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu = new byte[responseBytes.length + 6]; 200ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = 0x00; // TP-MTI, TP-UDHI 201ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = (byte) 202ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR; // TP-FCS 203ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = 0x07; // TP-PI: TP-PID, TP-DCS, TP-UDL present 204ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 205ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 206ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = (byte) pid; 207ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = (byte) dcs; 208ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 209ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (is7bitDcs(dcs)) { 210ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int septetCount = responseBytes.length * 8 / 7; 211ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = (byte) septetCount; 212ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } else { 213ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby smsAckPdu[index++] = (byte) responseBytes.length; 214ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 215ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 216ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby System.arraycopy(responseBytes, 0, smsAckPdu, index, responseBytes.length); 217ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 218ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby mCI.acknowledgeIncomingGsmSmsWithPdu(success, 219ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby IccUtils.bytesToHexString(smsAckPdu), null); 220ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 221ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 222ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private void acknowledgeSmsWithError(int cause) { 223ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby mCI.acknowledgeLastIncomingGsmSms(false, cause, null); 224ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 225ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 226ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** 227ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Returns whether the DCS is 7 bit. If so, set TP-UDL to the septet count of TP-UD; 228ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * otherwise, set TP-UDL to the octet count of TP-UD. 229ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param dcs the TP-Data-Coding-Scheme field from the original download SMS 230ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @return true if the DCS specifies 7 bit encoding; false otherwise 231ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 232ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby private static boolean is7bitDcs(int dcs) { 233ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby // See 3GPP TS 23.038 section 4 234ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return ((dcs & 0x8C) == 0x00) || ((dcs & 0xF4) == 0xF0); 235ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 236ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 237ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby /** 238ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * Handle UICC envelope response and send SMS acknowledgement. 239ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * 240ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby * @param msg the message to handle 241ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby */ 242ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby @Override 243ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby public void handleMessage(Message msg) { 244ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby switch (msg.what) { 245ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby case EVENT_START_DATA_DOWNLOAD: 246ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby handleDataDownload((SmsMessage) msg.obj); 247ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby break; 248ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 249ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby case EVENT_SEND_ENVELOPE_RESPONSE: 250ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby AsyncResult ar = (AsyncResult) msg.obj; 251ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 252ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby if (ar.exception != null) { 253ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "UICC Send Envelope failure, exception: " + ar.exception); 254ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby acknowledgeSmsWithError( 255ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby CommandsInterface.GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR); 256ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby return; 257ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 258ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 259ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby int[] dcsPid = (int[]) ar.userObj; 260ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby sendSmsAckForEnvelopeResponse((IccIoResult) ar.result, dcsPid[0], dcsPid[1]); 261ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby break; 262ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby 263ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby default: 264ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby Log.e(TAG, "Ignoring unexpected message, what=" + msg.what); 265ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 266ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby } 267ac09d2af145b4d820a34f5e7628bc42e2e211bdbJake Hamby} 268