Loading telephony/java/android/telephony/SmsMessage.java +24 −5 Original line number Diff line number Diff line Loading @@ -291,12 +291,31 @@ public class SmsMessage { // flexibly... int limit; if (ted.codeUnitSize == ENCODING_7BIT) { int udhLength; if (ted.languageTable != 0 && ted.languageShiftTable != 0) { udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES; } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) { udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE; } else { udhLength = 0; } if (ted.msgCount > 1) { limit = (ted.codeUnitSize == ENCODING_7BIT) ? MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER; udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE; } if (udhLength != 0) { udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH; } limit = MAX_USER_DATA_SEPTETS - udhLength; } else { limit = (ted.codeUnitSize == ENCODING_7BIT) ? MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES; if (ted.msgCount > 1) { limit = MAX_USER_DATA_BYTES_WITH_HEADER; } else { limit = MAX_USER_DATA_BYTES; } } int pos = 0; // Index in code units. Loading telephony/java/com/android/internal/telephony/GsmAlphabet.java +4 −4 Original line number Diff line number Diff line Loading @@ -60,25 +60,25 @@ public class GsmAlphabet { * all combinations of header elements below will have at least one free bit * when padding to the nearest septet boundary. */ private static final int UDH_SEPTET_COST_LENGTH = 1; public static final int UDH_SEPTET_COST_LENGTH = 1; /** * Using a non-default language locking shift table OR single shift table * requires a user data header of 3 octets, or 4 septets, plus UDH length. */ private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; public static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; /** * Using a non-default language locking shift table AND single shift table * requires a user data header of 6 octets, or 7 septets, plus UDH length. */ private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; public static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; /** * Multi-part messages require a user data header of 5 octets, or 6 septets, * plus UDH length. */ private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; public static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; /** * Converts a char to a GSM 7 bit table index. Loading telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java +109 −2 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.internal.telephony; import android.telephony.TelephonyManager; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.telephony.gsm.SmsMessage; import com.android.internal.util.HexDump; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import java.util.ArrayList; public class GsmSmsTest extends AndroidTestCase { Loading Loading @@ -231,6 +234,110 @@ public class GsmSmsTest extends AndroidTestCase { + "\u00a7~abcdefghijklmnopqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0" }; @SmallTest public void testFragmentText() throws Exception { boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == TelephonyManager.PHONE_TYPE_GSM); // Valid 160 character 7-bit text. String text = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890"; SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); assertEquals(1, ted.msgCount); assertEquals(160, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(0, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(1, fragments.size()); } // Valid 161 character 7-bit text. text = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901"; ted = SmsMessage.calculateLength(text, false); assertEquals(2, ted.msgCount); assertEquals(161, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(0, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(2, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1)); assertEquals(153, fragments.get(0).length()); assertEquals(8, fragments.get(1).length()); } } @SmallTest public void testFragmentTurkishText() throws Exception { boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == TelephonyManager.PHONE_TYPE_GSM); int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables(); int[] turkishTable = { 1 }; GsmAlphabet.setEnabledSingleShiftTables(turkishTable); // Valid 77 character text with Turkish characters. String text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğş"; SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); assertEquals(1, ted.msgCount); assertEquals(154, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(1, fragments.size()); assertEquals(text, fragments.get(0)); assertEquals(77, fragments.get(0).length()); } // Valid 78 character text with Turkish characters. text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğşı"; ted = SmsMessage.calculateLength(text, false); assertEquals(2, ted.msgCount); assertEquals(156, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(2, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1)); assertEquals(74, fragments.get(0).length()); assertEquals(4, fragments.get(1).length()); } // Valid 160 character text with Turkish characters. text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğ" + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı"; ted = SmsMessage.calculateLength(text, false); assertEquals(3, ted.msgCount); assertEquals(320, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(3, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2)); assertEquals(74, fragments.get(0).length()); assertEquals(74, fragments.get(1).length()); assertEquals(12, fragments.get(2).length()); } GsmAlphabet.setEnabledSingleShiftTables(oldTables); } @SmallTest public void testDecode() throws Exception { decodeSingle(0); // default table Loading Loading
telephony/java/android/telephony/SmsMessage.java +24 −5 Original line number Diff line number Diff line Loading @@ -291,12 +291,31 @@ public class SmsMessage { // flexibly... int limit; if (ted.codeUnitSize == ENCODING_7BIT) { int udhLength; if (ted.languageTable != 0 && ted.languageShiftTable != 0) { udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES; } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) { udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE; } else { udhLength = 0; } if (ted.msgCount > 1) { limit = (ted.codeUnitSize == ENCODING_7BIT) ? MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER; udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE; } if (udhLength != 0) { udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH; } limit = MAX_USER_DATA_SEPTETS - udhLength; } else { limit = (ted.codeUnitSize == ENCODING_7BIT) ? MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES; if (ted.msgCount > 1) { limit = MAX_USER_DATA_BYTES_WITH_HEADER; } else { limit = MAX_USER_DATA_BYTES; } } int pos = 0; // Index in code units. Loading
telephony/java/com/android/internal/telephony/GsmAlphabet.java +4 −4 Original line number Diff line number Diff line Loading @@ -60,25 +60,25 @@ public class GsmAlphabet { * all combinations of header elements below will have at least one free bit * when padding to the nearest septet boundary. */ private static final int UDH_SEPTET_COST_LENGTH = 1; public static final int UDH_SEPTET_COST_LENGTH = 1; /** * Using a non-default language locking shift table OR single shift table * requires a user data header of 3 octets, or 4 septets, plus UDH length. */ private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; public static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; /** * Using a non-default language locking shift table AND single shift table * requires a user data header of 6 octets, or 7 septets, plus UDH length. */ private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; public static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; /** * Multi-part messages require a user data header of 5 octets, or 6 septets, * plus UDH length. */ private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; public static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; /** * Converts a char to a GSM 7 bit table index. Loading
telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java +109 −2 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.internal.telephony; import android.telephony.TelephonyManager; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.telephony.gsm.SmsMessage; import com.android.internal.util.HexDump; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import java.util.ArrayList; public class GsmSmsTest extends AndroidTestCase { Loading Loading @@ -231,6 +234,110 @@ public class GsmSmsTest extends AndroidTestCase { + "\u00a7~abcdefghijklmnopqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0" }; @SmallTest public void testFragmentText() throws Exception { boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == TelephonyManager.PHONE_TYPE_GSM); // Valid 160 character 7-bit text. String text = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890"; SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); assertEquals(1, ted.msgCount); assertEquals(160, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(0, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(1, fragments.size()); } // Valid 161 character 7-bit text. text = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901"; ted = SmsMessage.calculateLength(text, false); assertEquals(2, ted.msgCount); assertEquals(161, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(0, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(2, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1)); assertEquals(153, fragments.get(0).length()); assertEquals(8, fragments.get(1).length()); } } @SmallTest public void testFragmentTurkishText() throws Exception { boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == TelephonyManager.PHONE_TYPE_GSM); int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables(); int[] turkishTable = { 1 }; GsmAlphabet.setEnabledSingleShiftTables(turkishTable); // Valid 77 character text with Turkish characters. String text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğş"; SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); assertEquals(1, ted.msgCount); assertEquals(154, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(1, fragments.size()); assertEquals(text, fragments.get(0)); assertEquals(77, fragments.get(0).length()); } // Valid 78 character text with Turkish characters. text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğşı"; ted = SmsMessage.calculateLength(text, false); assertEquals(2, ted.msgCount); assertEquals(156, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(2, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1)); assertEquals(74, fragments.get(0).length()); assertEquals(4, fragments.get(1).length()); } // Valid 160 character text with Turkish characters. text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğ" + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı"; ted = SmsMessage.calculateLength(text, false); assertEquals(3, ted.msgCount); assertEquals(320, ted.codeUnitCount); assertEquals(1, ted.codeUnitSize); assertEquals(0, ted.languageTable); assertEquals(1, ted.languageShiftTable); if (isGsmPhone) { ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); assertEquals(3, fragments.size()); assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2)); assertEquals(74, fragments.get(0).length()); assertEquals(74, fragments.get(1).length()); assertEquals(12, fragments.get(2).length()); } GsmAlphabet.setEnabledSingleShiftTables(oldTables); } @SmallTest public void testDecode() throws Exception { decodeSingle(0); // default table Loading