diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index c16b04d08b50b..aee45bffa3e8c 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -41,6 +41,7 @@ import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SMSDispatcher; +import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; import com.android.internal.telephony.cdma.SmsMessage; import com.android.internal.telephony.cdma.sms.SmsEnvelope; import com.android.internal.telephony.cdma.sms.UserData; @@ -366,8 +367,19 @@ final class CdmaSMSDispatcher extends SMSDispatcher { */ int refNumber = getNextConcatenatedRef() & 0x00FF; + int msgCount = parts.size(); + int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN; - for (int i = 0, msgCount = parts.size(); i < msgCount; i++) { + for (int i = 0; i < msgCount; i++) { + TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false); + if (encoding != details.codeUnitSize + && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN + || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) { + encoding = details.codeUnitSize; + } + } + + for (int i = 0; i < msgCount; i++) { SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); concatRef.refNumber = refNumber; concatRef.seqNumber = i + 1; // 1-based sequence @@ -389,6 +401,12 @@ final class CdmaSMSDispatcher extends SMSDispatcher { UserData uData = new UserData(); uData.payloadStr = parts.get(i); uData.userDataHeader = smsHeader; + if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) { + uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET; + } else { // assume UTF-16 + uData.msgEncoding = UserData.ENCODING_UNICODE_16; + } + uData.msgEncodingSet = true; /* By setting the statusReportRequested bit only for the * last message fragment, this will result in only one diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 0ca31488cc349..6ae316d0f08ea 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -28,6 +28,7 @@ import android.util.Config; import android.util.Log; import com.android.internal.telephony.IccUtils; +import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; import com.android.internal.telephony.gsm.SmsMessage; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.SMSDispatcher; @@ -165,8 +166,19 @@ final class GsmSMSDispatcher extends SMSDispatcher { ArrayList deliveryIntents) { int refNumber = getNextConcatenatedRef() & 0x00FF; + int msgCount = parts.size(); + int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN; - for (int i = 0, msgCount = parts.size(); i < msgCount; i++) { + for (int i = 0; i < msgCount; i++) { + TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false); + if (encoding != details.codeUnitSize + && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN + || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) { + encoding = details.codeUnitSize; + } + } + + for (int i = 0; i < msgCount; i++) { SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); concatRef.refNumber = refNumber; concatRef.seqNumber = i + 1; // 1-based sequence @@ -192,7 +204,8 @@ final class GsmSMSDispatcher extends SMSDispatcher { } SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress, - parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader)); + parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader), + encoding); sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent); } @@ -242,8 +255,19 @@ final class GsmSMSDispatcher extends SMSDispatcher { } int refNumber = getNextConcatenatedRef() & 0x00FF; + int msgCount = parts.size(); + int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN; - for (int i = 0, msgCount = parts.size(); i < msgCount; i++) { + for (int i = 0; i < msgCount; i++) { + TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false); + if (encoding != details.codeUnitSize + && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN + || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) { + encoding = details.codeUnitSize; + } + } + + for (int i = 0; i < msgCount; i++) { SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); concatRef.refNumber = refNumber; concatRef.seqNumber = i + 1; // 1-based sequence @@ -263,7 +287,8 @@ final class GsmSMSDispatcher extends SMSDispatcher { } SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress, - parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader)); + parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader), + encoding); HashMap map = new HashMap(); map.put("smsc", pdus.encodedScAddress); diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 569cf2559605a..ebd60a99207f0 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -225,6 +225,25 @@ public class SmsMessage extends SmsMessageBase{ public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested, byte[] header) { + return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, header, + ENCODING_UNKNOWN); + } + + + /** + * Get an SMS-SUBMIT PDU for a destination address and a message using the + * specified encoding. + * + * @param scAddress Service Centre address. Null means use default. + * @param encoding Encoding defined by constants in android.telephony.SmsMessage.ENCODING_* + * @return a SubmitPdu containing the encoded SC + * address, if applicable, and the encoded message. + * Returns null on encode error. + * @hide + */ + public static SubmitPdu getSubmitPdu(String scAddress, + String destinationAddress, String message, + boolean statusReportRequested, byte[] header, int encoding) { // Perform null parameter checks. if (message == null || destinationAddress == null) { @@ -237,18 +256,43 @@ public class SmsMessage extends SmsMessageBase{ ByteArrayOutputStream bo = getSubmitPduHead( scAddress, destinationAddress, mtiByte, statusReportRequested, ret); - - try { + // User Data (and length) + byte[] userData; + if (encoding == ENCODING_UNKNOWN) { // First, try encoding it with the GSM alphabet + encoding = ENCODING_7BIT; + } + try { + if (encoding == ENCODING_7BIT) { + userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header); + } else { //assume UCS-2 + try { + userData = encodeUCS2(message, header); + } catch(UnsupportedEncodingException uex) { + Log.e(LOG_TAG, + "Implausible UnsupportedEncodingException ", + uex); + return null; + } + } + } catch (EncodeException ex) { + // Encoding to the 7-bit alphabet failed. Let's see if we can + // send it as a UCS-2 encoded message + try { + userData = encodeUCS2(message, header); + } catch(UnsupportedEncodingException uex) { + Log.e(LOG_TAG, + "Implausible UnsupportedEncodingException ", + uex); + return null; + } + } - // User Data (and length) - byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header); - + if (encoding == ENCODING_7BIT) { if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) { // Message too long return null; } - // TP-Data-Coding-Scheme // Default encoding, uncompressed // To test writing messages to the SIM card, change this value 0x00 @@ -258,57 +302,50 @@ public class SmsMessage extends SmsMessageBase{ // the receiver's SIM card. You can then send messages to yourself // (on a phone with this change) and they'll end up on the SIM card. bo.write(0x00); - - // (no TP-Validity-Period) - - bo.write(userData, 0, userData.length); - } catch (EncodeException ex) { - byte[] userData, textPart; - // Encoding to the 7-bit alphabet failed. Let's see if we can - // send it as a UCS-2 encoded message - - try { - textPart = message.getBytes("utf-16be"); - } catch (UnsupportedEncodingException uex) { - Log.e(LOG_TAG, - "Implausible UnsupportedEncodingException ", - uex); - return null; - } - - if (header != null) { - // Need 1 byte for UDHL - userData = new byte[header.length + textPart.length + 1]; - - userData[0] = (byte)header.length; - System.arraycopy(header, 0, userData, 1, header.length); - System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length); - } - else { - userData = textPart; - } - - if (userData.length > MAX_USER_DATA_BYTES) { + } else { //assume UCS-2 + if ((0xff & userData[0]) > MAX_USER_DATA_BYTES) { // Message too long return null; } - // TP-Data-Coding-Scheme // Class 3, UCS-2 encoding, uncompressed bo.write(0x0b); - - // (no TP-Validity-Period) - - // TP-UDL - bo.write(userData.length); - - bo.write(userData, 0, userData.length); } + // (no TP-Validity-Period) + bo.write(userData, 0, userData.length); ret.encodedMessage = bo.toByteArray(); return ret; } + /** + * Packs header and UCS-2 encoded message. Includes TP-UDL & TP-UDHL if necessary + * + * @return + * @throws UnsupportedEncodingException + */ + private static byte[] encodeUCS2(String message, byte[] header) + throws UnsupportedEncodingException { + byte[] userData, textPart; + textPart = message.getBytes("utf-16be"); + + if (header != null) { + // Need 1 byte for UDHL + userData = new byte[header.length + textPart.length + 1]; + + userData[0] = (byte)header.length; + System.arraycopy(header, 0, userData, 1, header.length); + System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length); + } + else { + userData = textPart; + } + byte[] ret = new byte[userData.length+1]; + ret[0] = (byte) (userData.length & 0xff ); + System.arraycopy(userData, 0, ret, 1, userData.length); + return ret; + } + /** * Get an SMS-SUBMIT PDU for a destination address and a message *