10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2010 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SmsMessage; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager; 2199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Savilleimport android.telephony.Rlog; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.AndroidTestCase; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.LargeTest; 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.MediumTest; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.SmallTest; 267d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajanimport android.util.Log; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsConstants; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Test cases to verify selection of the optimal 7 bit encoding tables 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (for all combinations of enabled national language tables) for messages 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * containing Turkish, Spanish, Portuguese, Greek, and other symbols 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * present in the GSM default and national language tables defined in 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 3GPP TS 23.038. Also verifies correct SMS encoding for CDMA, which only 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * supports the GSM 7 bit default alphabet, ASCII 8 bit, and UCS-2. 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Tests both encoding variations: unsupported characters mapped to space, 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and unsupported characters force entire message to UCS-2. 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SmsMessageBodyTest extends AndroidTestCase { 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String TAG = "SmsMessageBodyTest"; 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ASCII chars in the GSM 7 bit default alphabet 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sAsciiChars = "@$_ !\"#%&'()*+,-./0123456789" + 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ":;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\r"; 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Unicode chars in the GSM 7 bit default alphabet and both locking shift tables 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmDefaultChars = "\u00a3\u00a5\u00e9\u00c7\u0394\u00c9" + 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u00dc\u00a7\u00fc\u00e0"; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Unicode chars in the GSM 7 bit default table and Turkish locking shift tables 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmDefaultAndTurkishTables = "\u00f9\u00f2\u00c5\u00e5\u00df" + 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u00a4\u00c4\u00d6\u00d1\u00e4\u00f6\u00f1"; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Unicode chars in the GSM 7 bit default table but not the locking shift tables 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmDefaultTableOnly = "\u00e8\u00ec\u00d8\u00f8\u00c6\u00e6" + 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u00a1\u00bf"; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ASCII chars in the GSM default extension table 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmExtendedAsciiChars = "{}[]\f"; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in GSM default extension table and Portuguese locking shift table 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmExtendedPortugueseLocking = "^\\|~"; 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Euro currency symbol 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGsmExtendedEuroSymbol = "\u20ac"; 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc. 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" + 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" + 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" + 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" + 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" + 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" + 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" + 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u00a2\u00a9\u00ae\u2122"; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in Turkish single shift and locking shift tables 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sTurkishChars = "\u0131\u011e\u011f\u015e\u015f\u0130"; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in Spanish single shift table and Portuguese single and locking shift tables 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sPortugueseAndSpanishChars = "\u00c1\u00e1\u00cd\u00ed" 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + "\u00d3\u00f3\u00da\u00fa"; 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in all national language tables but not in the standard GSM alphabets 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sNationalLanguageTablesOnly = "\u00e7"; 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in Portuguese single shift and locking shift tables 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sPortugueseChars = "\u00ea\u00d4\u00f4\u00c0\u00c2\u00e2" 920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + "\u00ca\u00c3\u00d5\u00e3\u00f5"; 930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // chars in Portuguese locking shift table only 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sPortugueseLockingShiftChars = "\u00aa\u221e\u00ba`"; 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Greek letters in GSM alphabet missing from Portuguese locking and single shift tables 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGreekLettersNotInPortugueseTables = "\u039b\u039e"; 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Greek letters in GSM alphabet and Portuguese single shift (but not locking shift) table 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String sGreekLettersInPortugueseShiftTable = 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "\u03a6\u0393\u03a9\u03a0\u03a8\u03a3\u0398"; 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // List of classes of characters in SMS tables 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String[] sCharacterClasses = { 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmExtendedAsciiChars, 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmExtendedPortugueseLocking, 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmDefaultChars, 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmDefaultAndTurkishTables, 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmDefaultTableOnly, 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGsmExtendedEuroSymbol, 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sUnicodeChars, 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sTurkishChars, 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sPortugueseChars, 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sPortugueseLockingShiftChars, 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sPortugueseAndSpanishChars, 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGreekLettersNotInPortugueseTables, 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sGreekLettersInPortugueseShiftTable, 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sNationalLanguageTablesOnly, 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sAsciiChars 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int sNumCharacterClasses = sCharacterClasses.length; 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // For each character class, whether it is present in a particular char table. 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // First three entries are locking shift tables, followed by four single shift tables 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean[][] sCharClassPresenceInTables = { 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ASCII chars in all GSM extension tables 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, false, true, true, true, true}, 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ASCII chars in all GSM extension tables and Portuguese locking shift table 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, true, true, true, true, true}, 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // non-ASCII chars in GSM default alphabet and all locking tables 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, true, true, false, false, false, false}, 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // non-ASCII chars in GSM default alphabet and Turkish locking shift table 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, true, false, false, false, false, false}, 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // non-ASCII chars in GSM default alphabet table only 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, false, false, false, false, false, false}, 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Euro symbol is present in several tables 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, true, true, true, true, true, true}, 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Unicode characters not present in any 7 bit tables 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, false, false, false, false, false}, 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Characters specific to Turkish language 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, true, false, false, true, false, false}, 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Characters in Portuguese single shift and locking shift tables 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, true, false, false, false, true}, 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Characters in Portuguese locking shift table only 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, true, false, false, false, false}, 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Chars in Spanish single shift and Portuguese single and locking shift tables 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, false, true, false, false, true, true}, 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Greek letters in GSM default alphabet missing from Portuguese tables 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, true, false, false, false, false, false}, 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Greek letters in GSM alphabet and Portuguese single shift table 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, true, false, false, false, false, true}, 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Chars in all national language tables but not the standard GSM tables 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {false, true, true, false, true, true, true}, 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ASCII chars in GSM default alphabet 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {true, true, true, false, false, false, false} 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int sTestLengthCount = 12; 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[] sSeptetTestLengths = 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 0, 1, 2, 80, 159, 160, 161, 240, 305, 306, 307, 320}; 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[] sUnicodeTestLengths = 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 0, 1, 2, 35, 69, 70, 71, 100, 133, 134, 135, 160}; 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[] sTestMsgCounts = 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3}; 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[] sSeptetUnitsRemaining = 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {160, 159, 158, 80, 1, 0, 145, 66, 1, 0, 152, 139}; 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[] sUnicodeUnitsRemaining = 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 70, 69, 68, 35, 1, 0, 63, 34, 1, 0, 66, 41}; 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Combinations of enabled GSM national language single shift tables 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[][] sEnabledSingleShiftTables = { 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // GSM default alphabet only 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1}, // Turkish (single shift only) 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1}, // Turkish (single and locking shift) 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {2}, // Spanish 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {3}, // Portuguese (single shift only) 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {3}, // Portuguese (single and locking shift) 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2}, // Turkish + Spanish (single shift only) 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2}, // Turkish + Spanish (single and locking shift) 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 3}, // Turkish + Portuguese (single shift only) 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 3}, // Turkish + Portuguese (single and locking shift) 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {2, 3}, // Spanish + Portuguese (single shift only) 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {2, 3}, // Spanish + Portuguese (single and locking shift) 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2, 3}, // Turkish, Spanish, Portuguese (single shift only) 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2, 3}, // Turkish, Spanish, Portuguese (single and locking shift) 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Combinations of enabled GSM national language locking shift tables 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[][] sEnabledLockingShiftTables = { 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // GSM default alphabet only 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Turkish (single shift only) 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1}, // Turkish (single and locking shift) 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Spanish (no locking shift table) 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Portuguese (single shift only) 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {3}, // Portuguese (single and locking shift) 2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Turkish + Spanish (single shift only) 2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1}, // Turkish + Spanish (single and locking shift) 2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Turkish + Portuguese (single shift only) 2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 3}, // Turkish + Portuguese (single and locking shift) 2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Spanish + Portuguese (single shift only) 2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {3}, // Spanish + Portuguese (single and locking shift) 2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {}, // Turkish, Spanish, Portuguese (single shift only) 2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 3}, // Turkish, Spanish, Portuguese (single and locking shift) 2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables 2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // LanguagePair counter indexes to check for each entry above 2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int[][] sLanguagePairIndexesByEnabledIndex = { 2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0}, // default tables only 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1}, // Turkish (single shift only) 2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 4, 5}, // Turkish (single and locking shift) 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 2}, // Spanish 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 3}, // Portuguese (single shift only) 2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 3, 8, 11}, // Portuguese (single and locking shift) 2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 2}, // Turkish + Spanish (single shift only) 2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 2, 4, 5, 6}, // Turkish + Spanish (single and locking shift) 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 3}, // Turkish + Portuguese (single shift only) 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 3, 4, 5, 7, 8, 9, 11}, // Turkish + Portuguese (single and locking shift) 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 2, 3}, // Spanish + Portuguese (single shift only) 2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 2, 3, 8, 10, 11}, // Spanish + Portuguese (single and locking shift) 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 2, 3}, // all languages (single shift only) 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // all languages (single and locking shift) 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} // all languages (no Indic chars in test) 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * User data header requires one octet for length. Count as one septet, because 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * all combinations of header elements below will have at least one free bit 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * when padding to the nearest septet boundary. 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int UDH_SEPTET_COST_LENGTH = 1; 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Using a non-default language locking shift table OR single shift table 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * requires a user data header of 3 octets, or 4 septets, plus UDH length. 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Using a non-default language locking shift table AND single shift table 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * requires a user data header of 6 octets, or 7 septets, plus UDH length. 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Multi-part messages require a user data header of 5 octets, or 6 septets, 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * plus UDH length. 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @SmallTest 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void testCalcLengthAscii() throws Exception { 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuilder sb = new StringBuilder(320); 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0}; 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int startPos = 0; 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int asciiCharsLen = sAsciiChars.length(); 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < sTestLengthCount; i++) { 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int len = sSeptetTestLengths[i]; 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertTrue(sb.length() <= len); 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (sb.length() < len) { 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int addCount = len - sb.length(); 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int endPos = (asciiCharsLen - startPos > addCount) ? 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (startPos + addCount) : asciiCharsLen; 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sb.append(sAsciiChars, startPos, endPos); 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville startPos = (endPos == asciiCharsLen) ? 0 : endPos; 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals(len, sb.length()); 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String testStr = sb.toString(); 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[0] = sTestMsgCounts[i]; 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[1] = len; 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[2] = sSeptetUnitsRemaining[i]; 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(testStr, false, values); 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(testStr, true, values); 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callCdmaLengthMethods(testStr, false, values); 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callCdmaLengthMethods(testStr, true, values); 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @SmallTest 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void testCalcLengthUnicode() throws Exception { 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuilder sb = new StringBuilder(160); 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0}; 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] values7bit = {1, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0}; 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int startPos = 0; 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int unicodeCharsLen = sUnicodeChars.length(); 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // start with length 1: empty string uses ENCODING_7BIT 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 1; i < sTestLengthCount; i++) { 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int len = sUnicodeTestLengths[i]; 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertTrue(sb.length() <= len); 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (sb.length() < len) { 3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int addCount = len - sb.length(); 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int endPos = (unicodeCharsLen - startPos > addCount) ? 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (startPos + addCount) : unicodeCharsLen; 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sb.append(sUnicodeChars, startPos, endPos); 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville startPos = (endPos == unicodeCharsLen) ? 0 : endPos; 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals(len, sb.length()); 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String testStr = sb.toString(); 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[0] = sTestMsgCounts[i]; 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[1] = len; 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[2] = sUnicodeUnitsRemaining[i]; 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values7bit[1] = len; 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values7bit[2] = SmsConstants.MAX_USER_DATA_SEPTETS - len; 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(testStr, false, values); 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callCdmaLengthMethods(testStr, false, values); 3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(testStr, true, values7bit); 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callCdmaLengthMethods(testStr, true, values7bit); 3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static class LanguagePair { 3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // index is 2 for Portuguese locking shift because there is no Spanish locking shift table 3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final int langTableIndex; 3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final int langShiftTableIndex; 3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int length; 3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int missingChars7bit; 3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville LanguagePair(int langTable, int langShiftTable) { 3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langTableIndex = langTable; 3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langShiftTableIndex = langShiftTable; 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void clear() { 3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length = 0; 3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville missingChars7bit = 0; 3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void addChar(boolean[] charClassTableRow) { 3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (charClassTableRow[langTableIndex]) { 3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length++; 3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (charClassTableRow[3 + langShiftTableIndex]) { 3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length += 2; 3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville length++; // use ' ' for unmapped char in 7 bit only mode 3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville missingChars7bit++; 3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static class CounterHelper { 3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville LanguagePair[] mCounters; 3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] mStatsCounters; 3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mUnicodeCounter; 3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CounterHelper() { 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mCounters = new LanguagePair[12]; 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mStatsCounters = new int[12]; 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < 12; i++) { 3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mCounters[i] = new LanguagePair(i/4, i%4); 3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void clear() { 3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Note: don't clear stats counters 3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < 12; i++) { 3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mCounters[i].clear(); 3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void addChar(int charClass) { 3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean[] charClassTableRow = sCharClassPresenceInTables[charClass]; 3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < 12; i++) { 3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mCounters[i].addChar(charClassTableRow); 3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length) { 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] languagePairs = sLanguagePairIndexesByEnabledIndex[enabledLangsIndex]; 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int minNumSeptets = Integer.MAX_VALUE; 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int minNumSeptetsWithHeader = Integer.MAX_VALUE; 3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int minNumMissingChars = Integer.MAX_VALUE; 3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int langIndex = -1; 3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int langShiftIndex = -1; 3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i : languagePairs) { 3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville LanguagePair pair = mCounters[i]; 3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhLength = 0; 3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (i != 0) { 3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength = UDH_SEPTET_COST_LENGTH; 3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (i < 4 || i % 4 == 0) { 3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; 3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; 3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numSeptetsWithHeader; 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pair.length > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (udhLength == 0) { 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength = UDH_SEPTET_COST_LENGTH; 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount = (pair.length + septetsPerPart - 1) / septetsPerPart; 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numSeptetsWithHeader = udhLength * msgCount + pair.length; 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numSeptetsWithHeader = udhLength + pair.length; 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (use7bitOnly) { 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pair.missingChars7bit < minNumMissingChars || (pair.missingChars7bit == 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumMissingChars && numSeptetsWithHeader < minNumSeptetsWithHeader)) { 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumSeptets = pair.length; 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumSeptetsWithHeader = numSeptetsWithHeader; 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumMissingChars = pair.missingChars7bit; 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langIndex = pair.langTableIndex; 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langShiftIndex = pair.langShiftTableIndex; 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pair.missingChars7bit == 0 && numSeptetsWithHeader < minNumSeptetsWithHeader) { 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumSeptets = pair.length; 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumSeptetsWithHeader = numSeptetsWithHeader; 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langIndex = pair.langTableIndex; 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville langShiftIndex = pair.langShiftTableIndex; 4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (langIndex == -1) { 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // nothing matches, use values for Unicode 4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int byteCount = length * 2; 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (byteCount > SmsConstants.MAX_USER_DATA_BYTES) { 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[0] = (byteCount + SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER - 1) / 4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER; 4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[2] = ((values[0] * SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER) - 4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byteCount) / 2; 4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[0] = 1; 4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[2] = (SmsConstants.MAX_USER_DATA_BYTES - byteCount) / 2; 4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[1] = length; 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[3] = SmsConstants.ENCODING_16BIT; 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[4] = 0; 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[5] = 0; 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUnicodeCounter++; 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhLength = 0; 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (langIndex != 0 || langShiftIndex != 0) { 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength = UDH_SEPTET_COST_LENGTH; 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (langIndex == 0 || langShiftIndex == 0) { 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; 4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount; 4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (minNumSeptets > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { 4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (udhLength == 0) { 4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength = UDH_SEPTET_COST_LENGTH; 4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville msgCount = (minNumSeptets + septetsPerPart - 1) / septetsPerPart; 4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville msgCount = 1; 4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[0] = msgCount; 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[1] = minNumSeptets; 4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[2] = (values[0] * (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) - 4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville minNumSeptets; 4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[3] = SmsConstants.ENCODING_7BIT; 4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[4] = (langIndex == 2 ? 3 : langIndex); // Portuguese is code 3, index 2 4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values[5] = langShiftIndex; 4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("minNumSeptetsWithHeader", minNumSeptetsWithHeader, 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville udhLength * msgCount + minNumSeptets); 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mStatsCounters[langIndex * 4 + langShiftIndex]++; 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void printStats() { 48499c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville Rlog.d(TAG, "Unicode selection count: " + mUnicodeCounter); 4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < 12; i++) { 48699c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville Rlog.d(TAG, "Language pair index " + i + " count: " + mStatsCounters[i]); 4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4917d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajan //@LargeTest 4927d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajan /*public void testCalcLengthMixed7bit() throws Exception { 4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuilder sb = new StringBuilder(320); 4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CounterHelper ch = new CounterHelper(); 4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Random r = new Random(0x4321); // use the same seed for reproducibility 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] expectedValues = new int[6]; 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] origLockingShiftTables = GsmAlphabet.getEnabledLockingShiftTables(); 4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] origSingleShiftTables = GsmAlphabet.getEnabledSingleShiftTables(); 4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int enabledLanguagesTestCases = sEnabledSingleShiftTables.length; 5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville long startTime = System.currentTimeMillis(); 5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Repeat for 10 test runs 5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int run = 0; run < 10; run++) { 5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sb.setLength(0); 5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ch.clear(); 5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int unicodeOnlyCount = 0; 5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Test incrementally from 1 to 320 character random messages 5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 1; i < 320; i++) { 5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // 1% chance to add from each special character class, else add an ASCII char 5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int charClass = r.nextInt(100); 5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (charClass >= sNumCharacterClasses) { 5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville charClass = sNumCharacterClasses - 1; // last class is ASCII 5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int classLength = sCharacterClasses[charClass].length(); 5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville char nextChar = sCharacterClasses[charClass].charAt(r.nextInt(classLength)); 5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sb.append(nextChar); 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ch.addChar(charClass); 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// if (i % 20 == 0) { 52199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville// Rlog.d(TAG, "test string: " + sb); 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// } 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Test string against all combinations of enabled languages 5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean unicodeOnly = true; 5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int j = 0; j < enabledLanguagesTestCases; j++) { 5277d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajan Log.d(TAG, "testCalcLengthMixed7bit: " + run + " " + i + " " + j); 5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.setEnabledSingleShiftTables(sEnabledSingleShiftTables[j]); 5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.setEnabledLockingShiftTables(sEnabledLockingShiftTables[j]); 5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ch.fillData(j, false, expectedValues, i); 5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (expectedValues[3] == SmsConstants.ENCODING_7BIT) { 5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville unicodeOnly = false; 5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(sb, false, expectedValues); 5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // test 7 bit only mode 5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ch.fillData(j, true, expectedValues, i); 5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville callGsmLengthMethods(sb, true, expectedValues); 5387d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajan Log.d(TAG, "testCalcLengthMixed7bit: " + run + " " + i + " " + j); 5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // after 10 iterations with a Unicode-only string, skip to next test string 5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // so we can spend more time testing strings that do encode into 7 bits. 5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (unicodeOnly && ++unicodeOnlyCount == 10) { 54399c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville// Rlog.d(TAG, "Unicode only: skipping to next test string"); 5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ch.printStats(); 54999c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville Rlog.d(TAG, "Completed in " + (System.currentTimeMillis() - startTime) + " ms"); 5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.setEnabledLockingShiftTables(origLockingShiftTables); 5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.setEnabledSingleShiftTables(origSingleShiftTables); 5527d9297a8415f4515508c0bf9abbd650e5ce6aa1bAmit Mahajan }*/ 5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void callGsmLengthMethods(CharSequence msgBody, boolean use7bitOnly, 5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] expectedValues) 5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // deprecated GSM-specific method 5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] values = android.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly); 5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], values[0]); 5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], values[1]); 5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], values[3]); 5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int activePhone = TelephonyManager.getDefault().getPhoneType(); 5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (TelephonyManager.PHONE_TYPE_GSM == activePhone) { 5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly); 5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], values[0]); 5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], values[1]); 5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], values[3]); 5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.TextEncodingDetails ted = 5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly); 5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], ted.msgCount); 5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("languageTable", expectedValues[4], ted.languageTable); 5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("languageShiftTable", expectedValues[5], ted.languageShiftTable); 5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void callCdmaLengthMethods(CharSequence msgBody, boolean use7bitOnly, 5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] expectedValues) 5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int activePhone = TelephonyManager.getDefault().getPhoneType(); 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (TelephonyManager.PHONE_TYPE_CDMA == activePhone) { 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly); 5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], values[0]); 5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], values[1]); 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], values[3]); 5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville GsmAlphabet.TextEncodingDetails ted = 5963ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly, true); 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], ted.msgCount); 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6023ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan ted = com.android.internal.telephony.cdma.sms.BearerData.calcTextEncodingDetails(msgBody, use7bitOnly, true); 6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("msgCount", expectedValues[0], ted.msgCount); 6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 609