| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.telephony; |
| |
| import android.telephony.SmsMessage; |
| import android.telephony.TelephonyManager; |
| import android.telephony.Rlog; |
| import android.test.AndroidTestCase; |
| import android.test.suitebuilder.annotation.LargeTest; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import com.android.internal.telephony.SmsConstants; |
| |
| import java.util.Random; |
| |
| /** |
| * 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. |
| */ |
| public class SmsMessageBodyTest extends AndroidTestCase { |
| private static final String TAG = "SmsMessageBodyTest"; |
| |
| // ASCII chars in the GSM 7 bit default alphabet |
| private static final String sAsciiChars = "@$_ !\"#%&'()*+,-./0123456789" + |
| ":;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\r"; |
| |
| // Unicode chars in the GSM 7 bit default alphabet and both locking shift tables |
| private static final String sGsmDefaultChars = "\u00a3\u00a5\u00e9\u00c7\u0394\u00c9" + |
| "\u00dc\u00a7\u00fc\u00e0"; |
| |
| // Unicode chars in the GSM 7 bit default table and Turkish locking shift tables |
| private static final String sGsmDefaultAndTurkishTables = "\u00f9\u00f2\u00c5\u00e5\u00df" + |
| "\u00a4\u00c4\u00d6\u00d1\u00e4\u00f6\u00f1"; |
| |
| // Unicode chars in the GSM 7 bit default table but not the locking shift tables |
| private static final String sGsmDefaultTableOnly = "\u00e8\u00ec\u00d8\u00f8\u00c6\u00e6" + |
| "\u00a1\u00bf"; |
| |
| // ASCII chars in the GSM default extension table |
| private static final String sGsmExtendedAsciiChars = "{}[]\f"; |
| |
| // chars in GSM default extension table and Portuguese locking shift table |
| private static final String sGsmExtendedPortugueseLocking = "^\\|~"; |
| |
| // Euro currency symbol |
| private static final String sGsmExtendedEuroSymbol = "\u20ac"; |
| |
| // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc. |
| private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" + |
| "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" + |
| "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" + |
| "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" + |
| "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" + |
| "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" + |
| "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" + |
| "\u00a2\u00a9\u00ae\u2122"; |
| |
| // chars in Turkish single shift and locking shift tables |
| private static final String sTurkishChars = "\u0131\u011e\u011f\u015e\u015f\u0130"; |
| |
| // chars in Spanish single shift table and Portuguese single and locking shift tables |
| private static final String sPortugueseAndSpanishChars = "\u00c1\u00e1\u00cd\u00ed" |
| + "\u00d3\u00f3\u00da\u00fa"; |
| |
| // chars in all national language tables but not in the standard GSM alphabets |
| private static final String sNationalLanguageTablesOnly = "\u00e7"; |
| |
| // chars in Portuguese single shift and locking shift tables |
| private static final String sPortugueseChars = "\u00ea\u00d4\u00f4\u00c0\u00c2\u00e2" |
| + "\u00ca\u00c3\u00d5\u00e3\u00f5"; |
| |
| // chars in Portuguese locking shift table only |
| private static final String sPortugueseLockingShiftChars = "\u00aa\u221e\u00ba`"; |
| |
| // Greek letters in GSM alphabet missing from Portuguese locking and single shift tables |
| private static final String sGreekLettersNotInPortugueseTables = "\u039b\u039e"; |
| |
| // Greek letters in GSM alphabet and Portuguese single shift (but not locking shift) table |
| private static final String sGreekLettersInPortugueseShiftTable = |
| "\u03a6\u0393\u03a9\u03a0\u03a8\u03a3\u0398"; |
| |
| // List of classes of characters in SMS tables |
| private static final String[] sCharacterClasses = { |
| sGsmExtendedAsciiChars, |
| sGsmExtendedPortugueseLocking, |
| sGsmDefaultChars, |
| sGsmDefaultAndTurkishTables, |
| sGsmDefaultTableOnly, |
| sGsmExtendedEuroSymbol, |
| sUnicodeChars, |
| sTurkishChars, |
| sPortugueseChars, |
| sPortugueseLockingShiftChars, |
| sPortugueseAndSpanishChars, |
| sGreekLettersNotInPortugueseTables, |
| sGreekLettersInPortugueseShiftTable, |
| sNationalLanguageTablesOnly, |
| sAsciiChars |
| }; |
| |
| private static final int sNumCharacterClasses = sCharacterClasses.length; |
| |
| // For each character class, whether it is present in a particular char table. |
| // First three entries are locking shift tables, followed by four single shift tables |
| private static final boolean[][] sCharClassPresenceInTables = { |
| // ASCII chars in all GSM extension tables |
| {false, false, false, true, true, true, true}, |
| // ASCII chars in all GSM extension tables and Portuguese locking shift table |
| {false, false, true, true, true, true, true}, |
| // non-ASCII chars in GSM default alphabet and all locking tables |
| {true, true, true, false, false, false, false}, |
| // non-ASCII chars in GSM default alphabet and Turkish locking shift table |
| {true, true, false, false, false, false, false}, |
| // non-ASCII chars in GSM default alphabet table only |
| {true, false, false, false, false, false, false}, |
| // Euro symbol is present in several tables |
| {false, true, true, true, true, true, true}, |
| // Unicode characters not present in any 7 bit tables |
| {false, false, false, false, false, false, false}, |
| // Characters specific to Turkish language |
| {false, true, false, false, true, false, false}, |
| // Characters in Portuguese single shift and locking shift tables |
| {false, false, true, false, false, false, true}, |
| // Characters in Portuguese locking shift table only |
| {false, false, true, false, false, false, false}, |
| // Chars in Spanish single shift and Portuguese single and locking shift tables |
| {false, false, true, false, false, true, true}, |
| // Greek letters in GSM default alphabet missing from Portuguese tables |
| {true, true, false, false, false, false, false}, |
| // Greek letters in GSM alphabet and Portuguese single shift table |
| {true, true, false, false, false, false, true}, |
| // Chars in all national language tables but not the standard GSM tables |
| {false, true, true, false, true, true, true}, |
| // ASCII chars in GSM default alphabet |
| {true, true, true, false, false, false, false} |
| }; |
| |
| private static final int sTestLengthCount = 12; |
| |
| private static final int[] sSeptetTestLengths = |
| { 0, 1, 2, 80, 159, 160, 161, 240, 305, 306, 307, 320}; |
| |
| private static final int[] sUnicodeTestLengths = |
| { 0, 1, 2, 35, 69, 70, 71, 100, 133, 134, 135, 160}; |
| |
| private static final int[] sTestMsgCounts = |
| { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3}; |
| |
| private static final int[] sSeptetUnitsRemaining = |
| {160, 159, 158, 80, 1, 0, 145, 66, 1, 0, 152, 139}; |
| |
| private static final int[] sUnicodeUnitsRemaining = |
| { 70, 69, 68, 35, 1, 0, 63, 34, 1, 0, 66, 41}; |
| |
| // Combinations of enabled GSM national language single shift tables |
| private static final int[][] sEnabledSingleShiftTables = { |
| {}, // GSM default alphabet only |
| {1}, // Turkish (single shift only) |
| {1}, // Turkish (single and locking shift) |
| {2}, // Spanish |
| {3}, // Portuguese (single shift only) |
| {3}, // Portuguese (single and locking shift) |
| {1, 2}, // Turkish + Spanish (single shift only) |
| {1, 2}, // Turkish + Spanish (single and locking shift) |
| {1, 3}, // Turkish + Portuguese (single shift only) |
| {1, 3}, // Turkish + Portuguese (single and locking shift) |
| {2, 3}, // Spanish + Portuguese (single shift only) |
| {2, 3}, // Spanish + Portuguese (single and locking shift) |
| {1, 2, 3}, // Turkish, Spanish, Portuguese (single shift only) |
| {1, 2, 3}, // Turkish, Spanish, Portuguese (single and locking shift) |
| {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables |
| }; |
| |
| // Combinations of enabled GSM national language locking shift tables |
| private static final int[][] sEnabledLockingShiftTables = { |
| {}, // GSM default alphabet only |
| {}, // Turkish (single shift only) |
| {1}, // Turkish (single and locking shift) |
| {}, // Spanish (no locking shift table) |
| {}, // Portuguese (single shift only) |
| {3}, // Portuguese (single and locking shift) |
| {}, // Turkish + Spanish (single shift only) |
| {1}, // Turkish + Spanish (single and locking shift) |
| {}, // Turkish + Portuguese (single shift only) |
| {1, 3}, // Turkish + Portuguese (single and locking shift) |
| {}, // Spanish + Portuguese (single shift only) |
| {3}, // Spanish + Portuguese (single and locking shift) |
| {}, // Turkish, Spanish, Portuguese (single shift only) |
| {1, 3}, // Turkish, Spanish, Portuguese (single and locking shift) |
| {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables |
| }; |
| |
| // LanguagePair counter indexes to check for each entry above |
| private static final int[][] sLanguagePairIndexesByEnabledIndex = { |
| {0}, // default tables only |
| {0, 1}, // Turkish (single shift only) |
| {0, 1, 4, 5}, // Turkish (single and locking shift) |
| {0, 2}, // Spanish |
| {0, 3}, // Portuguese (single shift only) |
| {0, 3, 8, 11}, // Portuguese (single and locking shift) |
| {0, 1, 2}, // Turkish + Spanish (single shift only) |
| {0, 1, 2, 4, 5, 6}, // Turkish + Spanish (single and locking shift) |
| {0, 1, 3}, // Turkish + Portuguese (single shift only) |
| {0, 1, 3, 4, 5, 7, 8, 9, 11}, // Turkish + Portuguese (single and locking shift) |
| {0, 2, 3}, // Spanish + Portuguese (single shift only) |
| {0, 2, 3, 8, 10, 11}, // Spanish + Portuguese (single and locking shift) |
| {0, 1, 2, 3}, // all languages (single shift only) |
| {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // all languages (single and locking shift) |
| {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} // all languages (no Indic chars in test) |
| }; |
| |
| /** |
| * 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_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; |
| |
| /** |
| * 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; |
| |
| /** |
| * 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; |
| |
| @SmallTest |
| public void testCalcLengthAscii() throws Exception { |
| 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); |
| } |
| } |
| |
| @SmallTest |
| public void testCalcLengthUnicode() throws Exception { |
| 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); |
| } |
| } |
| |
| private static class LanguagePair { |
| // index is 2 for Portuguese locking shift because there is no Spanish locking shift table |
| private final int langTableIndex; |
| private final int langShiftTableIndex; |
| int length; |
| int missingChars7bit; |
| |
| LanguagePair(int langTable, int langShiftTable) { |
| langTableIndex = langTable; |
| langShiftTableIndex = langShiftTable; |
| } |
| |
| void clear() { |
| length = 0; |
| missingChars7bit = 0; |
| } |
| |
| void addChar(boolean[] charClassTableRow) { |
| if (charClassTableRow[langTableIndex]) { |
| length++; |
| } else if (charClassTableRow[3 + langShiftTableIndex]) { |
| length += 2; |
| } else { |
| length++; // use ' ' for unmapped char in 7 bit only mode |
| missingChars7bit++; |
| } |
| } |
| } |
| |
| private static class CounterHelper { |
| LanguagePair[] mCounters; |
| int[] mStatsCounters; |
| int mUnicodeCounter; |
| |
| CounterHelper() { |
| mCounters = new LanguagePair[12]; |
| mStatsCounters = new int[12]; |
| for (int i = 0; i < 12; i++) { |
| mCounters[i] = new LanguagePair(i/4, i%4); |
| } |
| } |
| |
| void clear() { |
| // Note: don't clear stats counters |
| for (int i = 0; i < 12; i++) { |
| mCounters[i].clear(); |
| } |
| } |
| |
| void addChar(int charClass) { |
| boolean[] charClassTableRow = sCharClassPresenceInTables[charClass]; |
| for (int i = 0; i < 12; i++) { |
| mCounters[i].addChar(charClassTableRow); |
| } |
| } |
| |
| void fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length) { |
| int[] languagePairs = sLanguagePairIndexesByEnabledIndex[enabledLangsIndex]; |
| int minNumSeptets = Integer.MAX_VALUE; |
| int minNumSeptetsWithHeader = Integer.MAX_VALUE; |
| int minNumMissingChars = Integer.MAX_VALUE; |
| int langIndex = -1; |
| int langShiftIndex = -1; |
| for (int i : languagePairs) { |
| LanguagePair pair = mCounters[i]; |
| int udhLength = 0; |
| if (i != 0) { |
| udhLength = UDH_SEPTET_COST_LENGTH; |
| if (i < 4 || i % 4 == 0) { |
| udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; |
| } else { |
| udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; |
| } |
| } |
| int numSeptetsWithHeader; |
| if (pair.length > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { |
| if (udhLength == 0) { |
| udhLength = UDH_SEPTET_COST_LENGTH; |
| } |
| udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; |
| int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; |
| int msgCount = (pair.length + septetsPerPart - 1) / septetsPerPart; |
| numSeptetsWithHeader = udhLength * msgCount + pair.length; |
| } else { |
| numSeptetsWithHeader = udhLength + pair.length; |
| } |
| |
| if (use7bitOnly) { |
| if (pair.missingChars7bit < minNumMissingChars || (pair.missingChars7bit == |
| minNumMissingChars && numSeptetsWithHeader < minNumSeptetsWithHeader)) { |
| minNumSeptets = pair.length; |
| minNumSeptetsWithHeader = numSeptetsWithHeader; |
| minNumMissingChars = pair.missingChars7bit; |
| langIndex = pair.langTableIndex; |
| langShiftIndex = pair.langShiftTableIndex; |
| } |
| } else { |
| if (pair.missingChars7bit == 0 && numSeptetsWithHeader < minNumSeptetsWithHeader) { |
| minNumSeptets = pair.length; |
| minNumSeptetsWithHeader = numSeptetsWithHeader; |
| langIndex = pair.langTableIndex; |
| langShiftIndex = pair.langShiftTableIndex; |
| } |
| } |
| } |
| if (langIndex == -1) { |
| // nothing matches, use values for Unicode |
| int byteCount = length * 2; |
| if (byteCount > SmsConstants.MAX_USER_DATA_BYTES) { |
| values[0] = (byteCount + SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER - 1) / |
| SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER; |
| values[2] = ((values[0] * SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER) - |
| byteCount) / 2; |
| } else { |
| values[0] = 1; |
| values[2] = (SmsConstants.MAX_USER_DATA_BYTES - byteCount) / 2; |
| } |
| values[1] = length; |
| values[3] = SmsConstants.ENCODING_16BIT; |
| values[4] = 0; |
| values[5] = 0; |
| mUnicodeCounter++; |
| } else { |
| int udhLength = 0; |
| if (langIndex != 0 || langShiftIndex != 0) { |
| udhLength = UDH_SEPTET_COST_LENGTH; |
| if (langIndex == 0 || langShiftIndex == 0) { |
| udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; |
| } else { |
| udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; |
| } |
| } |
| int msgCount; |
| if (minNumSeptets > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { |
| if (udhLength == 0) { |
| udhLength = UDH_SEPTET_COST_LENGTH; |
| } |
| udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; |
| int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; |
| msgCount = (minNumSeptets + septetsPerPart - 1) / septetsPerPart; |
| } else { |
| msgCount = 1; |
| } |
| values[0] = msgCount; |
| values[1] = minNumSeptets; |
| values[2] = (values[0] * (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) - |
| minNumSeptets; |
| values[3] = SmsConstants.ENCODING_7BIT; |
| values[4] = (langIndex == 2 ? 3 : langIndex); // Portuguese is code 3, index 2 |
| values[5] = langShiftIndex; |
| assertEquals("minNumSeptetsWithHeader", minNumSeptetsWithHeader, |
| udhLength * msgCount + minNumSeptets); |
| mStatsCounters[langIndex * 4 + langShiftIndex]++; |
| } |
| } |
| |
| void printStats() { |
| Rlog.d(TAG, "Unicode selection count: " + mUnicodeCounter); |
| for (int i = 0; i < 12; i++) { |
| Rlog.d(TAG, "Language pair index " + i + " count: " + mStatsCounters[i]); |
| } |
| } |
| } |
| |
| @LargeTest |
| public void testCalcLengthMixed7bit() throws Exception { |
| 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); |
| } |
| |
| private void callGsmLengthMethods(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); |
| } |
| |
| private void callCdmaLengthMethods(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); |
| } |
| } |