FileDocCategorySizeDatePackage
SmsMessageBodyTest.javaAPI DocAndroid 5.1 API29451Thu Mar 12 22:22:54 GMT 2015com.android.internal.telephony

SmsMessageBodyTest

public class SmsMessageBodyTest extends android.test.AndroidTestCase
Test cases to verify selection of the optimal 7 bit encoding tables (for all combinations of enabled national language tables) for messages containing Turkish, Spanish, Portuguese, Greek, and other symbols present in the GSM default and national language tables defined in 3GPP TS 23.038. Also verifies correct SMS encoding for CDMA, which only supports the GSM 7 bit default alphabet, ASCII 8 bit, and UCS-2. Tests both encoding variations: unsupported characters mapped to space, and unsupported characters force entire message to UCS-2.

Fields Summary
private static final String
TAG
private static final String
sAsciiChars
private static final String
sGsmDefaultChars
private static final String
sGsmDefaultAndTurkishTables
private static final String
sGsmDefaultTableOnly
private static final String
sGsmExtendedAsciiChars
private static final String
sGsmExtendedPortugueseLocking
private static final String
sGsmExtendedEuroSymbol
private static final String
sUnicodeChars
private static final String
sTurkishChars
private static final String
sPortugueseAndSpanishChars
private static final String
sNationalLanguageTablesOnly
private static final String
sPortugueseChars
private static final String
sPortugueseLockingShiftChars
private static final String
sGreekLettersNotInPortugueseTables
private static final String
sGreekLettersInPortugueseShiftTable
private static final String[]
sCharacterClasses
private static final int
sNumCharacterClasses
private static final boolean[]
sCharClassPresenceInTables
private static final int
sTestLengthCount
private static final int[]
sSeptetTestLengths
private static final int[]
sUnicodeTestLengths
private static final int[]
sTestMsgCounts
private static final int[]
sSeptetUnitsRemaining
private static final int[]
sUnicodeUnitsRemaining
private static final int[]
sEnabledSingleShiftTables
private static final int[]
sEnabledLockingShiftTables
private static final int[]
sLanguagePairIndexesByEnabledIndex
private static final int
UDH_SEPTET_COST_LENGTH
User data header requires one octet for length. Count as one septet, because 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_ONE_SHIFT_TABLE
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_TWO_SHIFT_TABLES
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_CONCATENATED_MESSAGE
Multi-part messages require a user data header of 5 octets, or 6 septets, plus UDH length.
Constructors Summary
Methods Summary
private voidcallCdmaLengthMethods(java.lang.CharSequence msgBody, boolean use7bitOnly, int[] expectedValues)

        int activePhone = TelephonyManager.getDefault().getPhoneType();
        if (TelephonyManager.PHONE_TYPE_CDMA == activePhone) {
            int[] values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
            assertEquals("msgCount",           expectedValues[0], values[0]);
            assertEquals("codeUnitCount",      expectedValues[1], values[1]);
            assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
            assertEquals("codeUnitSize",       expectedValues[3], values[3]);
        }

        GsmAlphabet.TextEncodingDetails ted =
                com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly, true);
        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);

        ted = com.android.internal.telephony.cdma.sms.BearerData.calcTextEncodingDetails(msgBody, use7bitOnly, true);
        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);
    
private voidcallGsmLengthMethods(java.lang.CharSequence msgBody, boolean use7bitOnly, int[] expectedValues)

        // deprecated GSM-specific method
        int[] values = android.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
        assertEquals("msgCount",           expectedValues[0], values[0]);
        assertEquals("codeUnitCount",      expectedValues[1], values[1]);
        assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
        assertEquals("codeUnitSize",       expectedValues[3], values[3]);

        int activePhone = TelephonyManager.getDefault().getPhoneType();
        if (TelephonyManager.PHONE_TYPE_GSM == activePhone) {
            values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
            assertEquals("msgCount",           expectedValues[0], values[0]);
            assertEquals("codeUnitCount",      expectedValues[1], values[1]);
            assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
            assertEquals("codeUnitSize",       expectedValues[3], values[3]);
        }

        GsmAlphabet.TextEncodingDetails ted =
                com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);
        assertEquals("languageTable",      expectedValues[4], ted.languageTable);
        assertEquals("languageShiftTable", expectedValues[5], ted.languageShiftTable);
    
public voidtestCalcLengthAscii()


    
         
        StringBuilder sb = new StringBuilder(320);
        int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
        int startPos = 0;
        int asciiCharsLen = sAsciiChars.length();

        for (int i = 0; i < sTestLengthCount; i++) {
            int len = sSeptetTestLengths[i];
            assertTrue(sb.length() <= len);

            while (sb.length() < len) {
                int addCount = len - sb.length();
                int endPos = (asciiCharsLen - startPos > addCount) ?
                        (startPos + addCount) : asciiCharsLen;
                sb.append(sAsciiChars, startPos, endPos);
                startPos = (endPos == asciiCharsLen) ? 0 : endPos;
            }
            assertEquals(len, sb.length());

            String testStr = sb.toString();
            values[0] = sTestMsgCounts[i];
            values[1] = len;
            values[2] = sSeptetUnitsRemaining[i];

            callGsmLengthMethods(testStr, false, values);
            callGsmLengthMethods(testStr, true, values);
            callCdmaLengthMethods(testStr, false, values);
            callCdmaLengthMethods(testStr, true, values);
        }
    
public voidtestCalcLengthMixed7bit()

        StringBuilder sb = new StringBuilder(320);
        CounterHelper ch = new CounterHelper();
        Random r = new Random(0x4321);  // use the same seed for reproducibility
        int[] expectedValues = new int[6];
        int[] origLockingShiftTables = GsmAlphabet.getEnabledLockingShiftTables();
        int[] origSingleShiftTables = GsmAlphabet.getEnabledSingleShiftTables();
        int enabledLanguagesTestCases = sEnabledSingleShiftTables.length;
        long startTime = System.currentTimeMillis();

        // Repeat for 10 test runs
        for (int run = 0; run < 10; run++) {
            sb.setLength(0);
            ch.clear();
            int unicodeOnlyCount = 0;

            // Test incrementally from 1 to 320 character random messages
            for (int i = 1; i < 320; i++) {
                // 1% chance to add from each special character class, else add an ASCII char
                int charClass = r.nextInt(100);
                if (charClass >= sNumCharacterClasses) {
                    charClass = sNumCharacterClasses - 1;   // last class is ASCII
                }
                int classLength = sCharacterClasses[charClass].length();
                char nextChar = sCharacterClasses[charClass].charAt(r.nextInt(classLength));
                sb.append(nextChar);
                ch.addChar(charClass);

//                if (i % 20 == 0) {
//                    Rlog.d(TAG, "test string: " + sb);
//                }

                // Test string against all combinations of enabled languages
                boolean unicodeOnly = true;
                for (int j = 0; j < enabledLanguagesTestCases; j++) {
                    GsmAlphabet.setEnabledSingleShiftTables(sEnabledSingleShiftTables[j]);
                    GsmAlphabet.setEnabledLockingShiftTables(sEnabledLockingShiftTables[j]);
                    ch.fillData(j, false, expectedValues, i);
                    if (expectedValues[3] == SmsConstants.ENCODING_7BIT) {
                        unicodeOnly = false;
                    }
                    callGsmLengthMethods(sb, false, expectedValues);
                    // test 7 bit only mode
                    ch.fillData(j, true, expectedValues, i);
                    callGsmLengthMethods(sb, true, expectedValues);
                }
                // after 10 iterations with a Unicode-only string, skip to next test string
                // so we can spend more time testing strings that do encode into 7 bits.
                if (unicodeOnly && ++unicodeOnlyCount == 10) {
//                    Rlog.d(TAG, "Unicode only: skipping to next test string");
                    break;
                }
            }
        }
        ch.printStats();
        Rlog.d(TAG, "Completed in " + (System.currentTimeMillis() - startTime) + " ms");
        GsmAlphabet.setEnabledLockingShiftTables(origLockingShiftTables);
        GsmAlphabet.setEnabledSingleShiftTables(origSingleShiftTables);
    
public voidtestCalcLengthUnicode()

        StringBuilder sb = new StringBuilder(160);
        int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0};
        int[] values7bit = {1, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
        int startPos = 0;
        int unicodeCharsLen = sUnicodeChars.length();

        // start with length 1: empty string uses ENCODING_7BIT
        for (int i = 1; i < sTestLengthCount; i++) {
            int len = sUnicodeTestLengths[i];
            assertTrue(sb.length() <= len);

            while (sb.length() < len) {
                int addCount = len - sb.length();
                int endPos = (unicodeCharsLen - startPos > addCount) ?
                        (startPos + addCount) : unicodeCharsLen;
                sb.append(sUnicodeChars, startPos, endPos);
                startPos = (endPos == unicodeCharsLen) ? 0 : endPos;
            }
            assertEquals(len, sb.length());

            String testStr = sb.toString();
            values[0] = sTestMsgCounts[i];
            values[1] = len;
            values[2] = sUnicodeUnitsRemaining[i];
            values7bit[1] = len;
            values7bit[2] = SmsConstants.MAX_USER_DATA_SEPTETS - len;

            callGsmLengthMethods(testStr, false, values);
            callCdmaLengthMethods(testStr, false, values);
            callGsmLengthMethods(testStr, true, values7bit);
            callCdmaLengthMethods(testStr, true, values7bit);
        }