1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.telephony.TelephonyManager; 20 import android.test.AndroidTestCase; 21 import android.test.suitebuilder.annotation.SmallTest; 22 23 import com.android.telephony.Rlog; 24 25 /** 26 * Test cases to verify selection of the optimal 7 bit encoding tables 27 * (for all combinations of enabled national language tables) for messages 28 * containing Turkish, Spanish, Portuguese, Greek, and other symbols 29 * present in the GSM default and national language tables defined in 30 * 3GPP TS 23.038. Also verifies correct SMS encoding for CDMA, which only 31 * supports the GSM 7 bit default alphabet, ASCII 8 bit, and UCS-2. 32 * Tests both encoding variations: unsupported characters mapped to space, 33 * and unsupported characters force entire message to UCS-2. 34 */ 35 public class SmsMessageBodyTest extends AndroidTestCase { 36 private static final String TAG = "SmsMessageBodyTest"; 37 38 // ASCII chars in the GSM 7 bit default alphabet 39 private static final String sAsciiChars = "@$_ !\"#%&'()*+,-./0123456789" + 40 ":;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\r"; 41 42 // Unicode chars in the GSM 7 bit default alphabet and both locking shift tables 43 private static final String sGsmDefaultChars = "\u00a3\u00a5\u00e9\u00c7\u0394\u00c9" + 44 "\u00dc\u00a7\u00fc\u00e0"; 45 46 // Unicode chars in the GSM 7 bit default table and Turkish locking shift tables 47 private static final String sGsmDefaultAndTurkishTables = "\u00f9\u00f2\u00c5\u00e5\u00df" + 48 "\u00a4\u00c4\u00d6\u00d1\u00e4\u00f6\u00f1"; 49 50 // Unicode chars in the GSM 7 bit default table but not the locking shift tables 51 private static final String sGsmDefaultTableOnly = "\u00e8\u00ec\u00d8\u00f8\u00c6\u00e6" + 52 "\u00a1\u00bf"; 53 54 // ASCII chars in the GSM default extension table 55 private static final String sGsmExtendedAsciiChars = "{}[]\f"; 56 57 // chars in GSM default extension table and Portuguese locking shift table 58 private static final String sGsmExtendedPortugueseLocking = "^\\|~"; 59 60 // Euro currency symbol 61 private static final String sGsmExtendedEuroSymbol = "\u20ac"; 62 63 // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc. 64 private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" + 65 "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" + 66 "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" + 67 "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" + 68 "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" + 69 "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" + 70 "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" + 71 "\u00a2\u00a9\u00ae\u2122"; 72 73 // chars in Turkish single shift and locking shift tables 74 private static final String sTurkishChars = "\u0131\u011e\u011f\u015e\u015f\u0130"; 75 76 // chars in Spanish single shift table and Portuguese single and locking shift tables 77 private static final String sPortugueseAndSpanishChars = "\u00c1\u00e1\u00cd\u00ed" 78 + "\u00d3\u00f3\u00da\u00fa"; 79 80 // chars in all national language tables but not in the standard GSM alphabets 81 private static final String sNationalLanguageTablesOnly = "\u00e7"; 82 83 // chars in Portuguese single shift and locking shift tables 84 private static final String sPortugueseChars = "\u00ea\u00d4\u00f4\u00c0\u00c2\u00e2" 85 + "\u00ca\u00c3\u00d5\u00e3\u00f5"; 86 87 // chars in Portuguese locking shift table only 88 private static final String sPortugueseLockingShiftChars = "\u00aa\u221e\u00ba`"; 89 90 // Greek letters in GSM alphabet missing from Portuguese locking and single shift tables 91 private static final String sGreekLettersNotInPortugueseTables = "\u039b\u039e"; 92 93 // Greek letters in GSM alphabet and Portuguese single shift (but not locking shift) table 94 private static final String sGreekLettersInPortugueseShiftTable = 95 "\u03a6\u0393\u03a9\u03a0\u03a8\u03a3\u0398"; 96 97 // List of classes of characters in SMS tables 98 private static final String[] sCharacterClasses = { 99 sGsmExtendedAsciiChars, 100 sGsmExtendedPortugueseLocking, 101 sGsmDefaultChars, 102 sGsmDefaultAndTurkishTables, 103 sGsmDefaultTableOnly, 104 sGsmExtendedEuroSymbol, 105 sUnicodeChars, 106 sTurkishChars, 107 sPortugueseChars, 108 sPortugueseLockingShiftChars, 109 sPortugueseAndSpanishChars, 110 sGreekLettersNotInPortugueseTables, 111 sGreekLettersInPortugueseShiftTable, 112 sNationalLanguageTablesOnly, 113 sAsciiChars 114 }; 115 116 private static final int sNumCharacterClasses = sCharacterClasses.length; 117 118 // For each character class, whether it is present in a particular char table. 119 // First three entries are locking shift tables, followed by four single shift tables 120 private static final boolean[][] sCharClassPresenceInTables = { 121 // ASCII chars in all GSM extension tables 122 {false, false, false, true, true, true, true}, 123 // ASCII chars in all GSM extension tables and Portuguese locking shift table 124 {false, false, true, true, true, true, true}, 125 // non-ASCII chars in GSM default alphabet and all locking tables 126 {true, true, true, false, false, false, false}, 127 // non-ASCII chars in GSM default alphabet and Turkish locking shift table 128 {true, true, false, false, false, false, false}, 129 // non-ASCII chars in GSM default alphabet table only 130 {true, false, false, false, false, false, false}, 131 // Euro symbol is present in several tables 132 {false, true, true, true, true, true, true}, 133 // Unicode characters not present in any 7 bit tables 134 {false, false, false, false, false, false, false}, 135 // Characters specific to Turkish language 136 {false, true, false, false, true, false, false}, 137 // Characters in Portuguese single shift and locking shift tables 138 {false, false, true, false, false, false, true}, 139 // Characters in Portuguese locking shift table only 140 {false, false, true, false, false, false, false}, 141 // Chars in Spanish single shift and Portuguese single and locking shift tables 142 {false, false, true, false, false, true, true}, 143 // Greek letters in GSM default alphabet missing from Portuguese tables 144 {true, true, false, false, false, false, false}, 145 // Greek letters in GSM alphabet and Portuguese single shift table 146 {true, true, false, false, false, false, true}, 147 // Chars in all national language tables but not the standard GSM tables 148 {false, true, true, false, true, true, true}, 149 // ASCII chars in GSM default alphabet 150 {true, true, true, false, false, false, false} 151 }; 152 153 private static final int sTestLengthCount = 12; 154 155 private static final int[] sSeptetTestLengths = 156 { 0, 1, 2, 80, 159, 160, 161, 240, 305, 306, 307, 320}; 157 158 private static final int[] sUnicodeTestLengths = 159 { 0, 1, 2, 35, 69, 70, 71, 100, 133, 134, 135, 160}; 160 161 private static final int[] sTestMsgCounts = 162 { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3}; 163 164 private static final int[] sSeptetUnitsRemaining = 165 {160, 159, 158, 80, 1, 0, 145, 66, 1, 0, 152, 139}; 166 167 private static final int[] sUnicodeUnitsRemaining = 168 { 70, 69, 68, 35, 1, 0, 63, 34, 1, 0, 66, 41}; 169 170 // Combinations of enabled GSM national language single shift tables 171 private static final int[][] sEnabledSingleShiftTables = { 172 {}, // GSM default alphabet only 173 {1}, // Turkish (single shift only) 174 {1}, // Turkish (single and locking shift) 175 {2}, // Spanish 176 {3}, // Portuguese (single shift only) 177 {3}, // Portuguese (single and locking shift) 178 {1, 2}, // Turkish + Spanish (single shift only) 179 {1, 2}, // Turkish + Spanish (single and locking shift) 180 {1, 3}, // Turkish + Portuguese (single shift only) 181 {1, 3}, // Turkish + Portuguese (single and locking shift) 182 {2, 3}, // Spanish + Portuguese (single shift only) 183 {2, 3}, // Spanish + Portuguese (single and locking shift) 184 {1, 2, 3}, // Turkish, Spanish, Portuguese (single shift only) 185 {1, 2, 3}, // Turkish, Spanish, Portuguese (single and locking shift) 186 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables 187 }; 188 189 // Combinations of enabled GSM national language locking shift tables 190 private static final int[][] sEnabledLockingShiftTables = { 191 {}, // GSM default alphabet only 192 {}, // Turkish (single shift only) 193 {1}, // Turkish (single and locking shift) 194 {}, // Spanish (no locking shift table) 195 {}, // Portuguese (single shift only) 196 {3}, // Portuguese (single and locking shift) 197 {}, // Turkish + Spanish (single shift only) 198 {1}, // Turkish + Spanish (single and locking shift) 199 {}, // Turkish + Portuguese (single shift only) 200 {1, 3}, // Turkish + Portuguese (single and locking shift) 201 {}, // Spanish + Portuguese (single shift only) 202 {3}, // Spanish + Portuguese (single and locking shift) 203 {}, // Turkish, Spanish, Portuguese (single shift only) 204 {1, 3}, // Turkish, Spanish, Portuguese (single and locking shift) 205 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables 206 }; 207 208 // LanguagePair counter indexes to check for each entry above 209 private static final int[][] sLanguagePairIndexesByEnabledIndex = { 210 {0}, // default tables only 211 {0, 1}, // Turkish (single shift only) 212 {0, 1, 4, 5}, // Turkish (single and locking shift) 213 {0, 2}, // Spanish 214 {0, 3}, // Portuguese (single shift only) 215 {0, 3, 8, 11}, // Portuguese (single and locking shift) 216 {0, 1, 2}, // Turkish + Spanish (single shift only) 217 {0, 1, 2, 4, 5, 6}, // Turkish + Spanish (single and locking shift) 218 {0, 1, 3}, // Turkish + Portuguese (single shift only) 219 {0, 1, 3, 4, 5, 7, 8, 9, 11}, // Turkish + Portuguese (single and locking shift) 220 {0, 2, 3}, // Spanish + Portuguese (single shift only) 221 {0, 2, 3, 8, 10, 11}, // Spanish + Portuguese (single and locking shift) 222 {0, 1, 2, 3}, // all languages (single shift only) 223 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // all languages (single and locking shift) 224 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} // all languages (no Indic chars in test) 225 }; 226 227 /** 228 * User data header requires one octet for length. Count as one septet, because 229 * all combinations of header elements below will have at least one free bit 230 * when padding to the nearest septet boundary. 231 */ 232 private static final int UDH_SEPTET_COST_LENGTH = 1; 233 234 /** 235 * Using a non-default language locking shift table OR single shift table 236 * requires a user data header of 3 octets, or 4 septets, plus UDH length. 237 */ 238 private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; 239 240 /** 241 * Using a non-default language locking shift table AND single shift table 242 * requires a user data header of 6 octets, or 7 septets, plus UDH length. 243 */ 244 private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; 245 246 /** 247 * Multi-part messages require a user data header of 5 octets, or 6 septets, 248 * plus UDH length. 249 */ 250 private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; 251 252 @SmallTest testCalcLengthAscii()253 public void testCalcLengthAscii() throws Exception { 254 StringBuilder sb = new StringBuilder(320); 255 int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0}; 256 int startPos = 0; 257 int asciiCharsLen = sAsciiChars.length(); 258 259 for (int i = 0; i < sTestLengthCount; i++) { 260 int len = sSeptetTestLengths[i]; 261 assertTrue(sb.length() <= len); 262 263 while (sb.length() < len) { 264 int addCount = len - sb.length(); 265 int endPos = (asciiCharsLen - startPos > addCount) ? 266 (startPos + addCount) : asciiCharsLen; 267 sb.append(sAsciiChars, startPos, endPos); 268 startPos = (endPos == asciiCharsLen) ? 0 : endPos; 269 } 270 assertEquals(len, sb.length()); 271 272 String testStr = sb.toString(); 273 values[0] = sTestMsgCounts[i]; 274 values[1] = len; 275 values[2] = sSeptetUnitsRemaining[i]; 276 277 callGsmLengthMethods(testStr, false, values); 278 callGsmLengthMethods(testStr, true, values); 279 callCdmaLengthMethods(testStr, false, values); 280 callCdmaLengthMethods(testStr, true, values); 281 } 282 } 283 284 @SmallTest testCalcLengthUnicode()285 public void testCalcLengthUnicode() throws Exception { 286 StringBuilder sb = new StringBuilder(160); 287 int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0}; 288 int[] values7bit = {1, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0}; 289 int startPos = 0; 290 int unicodeCharsLen = sUnicodeChars.length(); 291 292 // start with length 1: empty string uses ENCODING_7BIT 293 for (int i = 1; i < sTestLengthCount; i++) { 294 int len = sUnicodeTestLengths[i]; 295 assertTrue(sb.length() <= len); 296 297 while (sb.length() < len) { 298 int addCount = len - sb.length(); 299 int endPos = (unicodeCharsLen - startPos > addCount) ? 300 (startPos + addCount) : unicodeCharsLen; 301 sb.append(sUnicodeChars, startPos, endPos); 302 startPos = (endPos == unicodeCharsLen) ? 0 : endPos; 303 } 304 assertEquals(len, sb.length()); 305 306 String testStr = sb.toString(); 307 values[0] = sTestMsgCounts[i]; 308 values[1] = len; 309 values[2] = sUnicodeUnitsRemaining[i]; 310 values7bit[1] = len; 311 values7bit[2] = SmsConstants.MAX_USER_DATA_SEPTETS - len; 312 313 callGsmLengthMethods(testStr, false, values); 314 callCdmaLengthMethods(testStr, false, values); 315 callGsmLengthMethods(testStr, true, values7bit); 316 callCdmaLengthMethods(testStr, true, values7bit); 317 } 318 } 319 320 private static class LanguagePair { 321 // index is 2 for Portuguese locking shift because there is no Spanish locking shift table 322 private final int langTableIndex; 323 private final int langShiftTableIndex; 324 int length; 325 int missingChars7bit; 326 LanguagePair(int langTable, int langShiftTable)327 LanguagePair(int langTable, int langShiftTable) { 328 langTableIndex = langTable; 329 langShiftTableIndex = langShiftTable; 330 } 331 clear()332 void clear() { 333 length = 0; 334 missingChars7bit = 0; 335 } 336 addChar(boolean[] charClassTableRow)337 void addChar(boolean[] charClassTableRow) { 338 if (charClassTableRow[langTableIndex]) { 339 length++; 340 } else if (charClassTableRow[3 + langShiftTableIndex]) { 341 length += 2; 342 } else { 343 length++; // use ' ' for unmapped char in 7 bit only mode 344 missingChars7bit++; 345 } 346 } 347 } 348 349 private static class CounterHelper { 350 LanguagePair[] mCounters; 351 int[] mStatsCounters; 352 int mUnicodeCounter; 353 CounterHelper()354 CounterHelper() { 355 mCounters = new LanguagePair[12]; 356 mStatsCounters = new int[12]; 357 for (int i = 0; i < 12; i++) { 358 mCounters[i] = new LanguagePair(i/4, i%4); 359 } 360 } 361 clear()362 void clear() { 363 // Note: don't clear stats counters 364 for (int i = 0; i < 12; i++) { 365 mCounters[i].clear(); 366 } 367 } 368 addChar(int charClass)369 void addChar(int charClass) { 370 boolean[] charClassTableRow = sCharClassPresenceInTables[charClass]; 371 for (int i = 0; i < 12; i++) { 372 mCounters[i].addChar(charClassTableRow); 373 } 374 } 375 fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length)376 void fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length) { 377 int[] languagePairs = sLanguagePairIndexesByEnabledIndex[enabledLangsIndex]; 378 int minNumSeptets = Integer.MAX_VALUE; 379 int minNumSeptetsWithHeader = Integer.MAX_VALUE; 380 int minNumMissingChars = Integer.MAX_VALUE; 381 int langIndex = -1; 382 int langShiftIndex = -1; 383 for (int i : languagePairs) { 384 LanguagePair pair = mCounters[i]; 385 int udhLength = 0; 386 if (i != 0) { 387 udhLength = UDH_SEPTET_COST_LENGTH; 388 if (i < 4 || i % 4 == 0) { 389 udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; 390 } else { 391 udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; 392 } 393 } 394 int numSeptetsWithHeader; 395 if (pair.length > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { 396 if (udhLength == 0) { 397 udhLength = UDH_SEPTET_COST_LENGTH; 398 } 399 udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; 400 int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; 401 int msgCount = (pair.length + septetsPerPart - 1) / septetsPerPart; 402 numSeptetsWithHeader = udhLength * msgCount + pair.length; 403 } else { 404 numSeptetsWithHeader = udhLength + pair.length; 405 } 406 407 if (use7bitOnly) { 408 if (pair.missingChars7bit < minNumMissingChars || (pair.missingChars7bit == 409 minNumMissingChars && numSeptetsWithHeader < minNumSeptetsWithHeader)) { 410 minNumSeptets = pair.length; 411 minNumSeptetsWithHeader = numSeptetsWithHeader; 412 minNumMissingChars = pair.missingChars7bit; 413 langIndex = pair.langTableIndex; 414 langShiftIndex = pair.langShiftTableIndex; 415 } 416 } else { 417 if (pair.missingChars7bit == 0 && numSeptetsWithHeader < minNumSeptetsWithHeader) { 418 minNumSeptets = pair.length; 419 minNumSeptetsWithHeader = numSeptetsWithHeader; 420 langIndex = pair.langTableIndex; 421 langShiftIndex = pair.langShiftTableIndex; 422 } 423 } 424 } 425 if (langIndex == -1) { 426 // nothing matches, use values for Unicode 427 int byteCount = length * 2; 428 if (byteCount > SmsConstants.MAX_USER_DATA_BYTES) { 429 values[0] = (byteCount + SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER - 1) / 430 SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER; 431 values[2] = ((values[0] * SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER) - 432 byteCount) / 2; 433 } else { 434 values[0] = 1; 435 values[2] = (SmsConstants.MAX_USER_DATA_BYTES - byteCount) / 2; 436 } 437 values[1] = length; 438 values[3] = SmsConstants.ENCODING_16BIT; 439 values[4] = 0; 440 values[5] = 0; 441 mUnicodeCounter++; 442 } else { 443 int udhLength = 0; 444 if (langIndex != 0 || langShiftIndex != 0) { 445 udhLength = UDH_SEPTET_COST_LENGTH; 446 if (langIndex == 0 || langShiftIndex == 0) { 447 udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE; 448 } else { 449 udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES; 450 } 451 } 452 int msgCount; 453 if (minNumSeptets > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) { 454 if (udhLength == 0) { 455 udhLength = UDH_SEPTET_COST_LENGTH; 456 } 457 udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE; 458 int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength; 459 msgCount = (minNumSeptets + septetsPerPart - 1) / septetsPerPart; 460 } else { 461 msgCount = 1; 462 } 463 values[0] = msgCount; 464 values[1] = minNumSeptets; 465 values[2] = (values[0] * (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) - 466 minNumSeptets; 467 values[3] = SmsConstants.ENCODING_7BIT; 468 values[4] = (langIndex == 2 ? 3 : langIndex); // Portuguese is code 3, index 2 469 values[5] = langShiftIndex; 470 assertEquals("minNumSeptetsWithHeader", minNumSeptetsWithHeader, 471 udhLength * msgCount + minNumSeptets); 472 mStatsCounters[langIndex * 4 + langShiftIndex]++; 473 } 474 } 475 printStats()476 void printStats() { 477 Rlog.d(TAG, "Unicode selection count: " + mUnicodeCounter); 478 for (int i = 0; i < 12; i++) { 479 Rlog.d(TAG, "Language pair index " + i + " count: " + mStatsCounters[i]); 480 } 481 } 482 } 483 484 //@LargeTest 485 /*public void testCalcLengthMixed7bit() throws Exception { 486 StringBuilder sb = new StringBuilder(320); 487 CounterHelper ch = new CounterHelper(); 488 Random r = new Random(0x4321); // use the same seed for reproducibility 489 int[] expectedValues = new int[6]; 490 int[] origLockingShiftTables = GsmAlphabet.getEnabledLockingShiftTables(); 491 int[] origSingleShiftTables = GsmAlphabet.getEnabledSingleShiftTables(); 492 int enabledLanguagesTestCases = sEnabledSingleShiftTables.length; 493 long startTime = System.currentTimeMillis(); 494 495 // Repeat for 10 test runs 496 for (int run = 0; run < 10; run++) { 497 sb.setLength(0); 498 ch.clear(); 499 int unicodeOnlyCount = 0; 500 501 // Test incrementally from 1 to 320 character random messages 502 for (int i = 1; i < 320; i++) { 503 // 1% chance to add from each special character class, else add an ASCII char 504 int charClass = r.nextInt(100); 505 if (charClass >= sNumCharacterClasses) { 506 charClass = sNumCharacterClasses - 1; // last class is ASCII 507 } 508 int classLength = sCharacterClasses[charClass].length(); 509 char nextChar = sCharacterClasses[charClass].charAt(r.nextInt(classLength)); 510 sb.append(nextChar); 511 ch.addChar(charClass); 512 513 // if (i % 20 == 0) { 514 // Rlog.d(TAG, "test string: " + sb); 515 // } 516 517 // Test string against all combinations of enabled languages 518 boolean unicodeOnly = true; 519 for (int j = 0; j < enabledLanguagesTestCases; j++) { 520 Log.d(TAG, "testCalcLengthMixed7bit: " + run + " " + i + " " + j); 521 GsmAlphabet.setEnabledSingleShiftTables(sEnabledSingleShiftTables[j]); 522 GsmAlphabet.setEnabledLockingShiftTables(sEnabledLockingShiftTables[j]); 523 ch.fillData(j, false, expectedValues, i); 524 if (expectedValues[3] == SmsConstants.ENCODING_7BIT) { 525 unicodeOnly = false; 526 } 527 callGsmLengthMethods(sb, false, expectedValues); 528 // test 7 bit only mode 529 ch.fillData(j, true, expectedValues, i); 530 callGsmLengthMethods(sb, true, expectedValues); 531 Log.d(TAG, "testCalcLengthMixed7bit: " + run + " " + i + " " + j); 532 } 533 // after 10 iterations with a Unicode-only string, skip to next test string 534 // so we can spend more time testing strings that do encode into 7 bits. 535 if (unicodeOnly && ++unicodeOnlyCount == 10) { 536 // Rlog.d(TAG, "Unicode only: skipping to next test string"); 537 break; 538 } 539 } 540 } 541 ch.printStats(); 542 Rlog.d(TAG, "Completed in " + (System.currentTimeMillis() - startTime) + " ms"); 543 GsmAlphabet.setEnabledLockingShiftTables(origLockingShiftTables); 544 GsmAlphabet.setEnabledSingleShiftTables(origSingleShiftTables); 545 }*/ 546 callGsmLengthMethods(CharSequence msgBody, boolean use7bitOnly, int[] expectedValues)547 private void callGsmLengthMethods(CharSequence msgBody, boolean use7bitOnly, 548 int[] expectedValues) 549 { 550 // deprecated GSM-specific method 551 int[] values = android.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly); 552 assertEquals("msgCount", expectedValues[0], values[0]); 553 assertEquals("codeUnitCount", expectedValues[1], values[1]); 554 assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 555 assertEquals("codeUnitSize", expectedValues[3], values[3]); 556 557 int activePhone = TelephonyManager.getDefault().getPhoneType(); 558 if (TelephonyManager.PHONE_TYPE_GSM == activePhone) { 559 values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly); 560 assertEquals("msgCount", expectedValues[0], values[0]); 561 assertEquals("codeUnitCount", expectedValues[1], values[1]); 562 assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 563 assertEquals("codeUnitSize", expectedValues[3], values[3]); 564 } 565 566 GsmAlphabet.TextEncodingDetails ted = 567 com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly); 568 assertEquals("msgCount", expectedValues[0], ted.msgCount); 569 assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 570 assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 571 assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 572 assertEquals("languageTable", expectedValues[4], ted.languageTable); 573 assertEquals("languageShiftTable", expectedValues[5], ted.languageShiftTable); 574 } 575 callCdmaLengthMethods(CharSequence msgBody, boolean use7bitOnly, int[] expectedValues)576 private void callCdmaLengthMethods(CharSequence msgBody, boolean use7bitOnly, 577 int[] expectedValues) 578 { 579 int activePhone = TelephonyManager.getDefault().getPhoneType(); 580 if (TelephonyManager.PHONE_TYPE_CDMA == activePhone) { 581 int[] values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly); 582 assertEquals("msgCount", expectedValues[0], values[0]); 583 assertEquals("codeUnitCount", expectedValues[1], values[1]); 584 assertEquals("codeUnitsRemaining", expectedValues[2], values[2]); 585 assertEquals("codeUnitSize", expectedValues[3], values[3]); 586 } 587 588 GsmAlphabet.TextEncodingDetails ted = 589 com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly, true); 590 assertEquals("msgCount", expectedValues[0], ted.msgCount); 591 assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 592 assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 593 assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 594 595 ted = com.android.internal.telephony.cdma.sms.BearerData.calcTextEncodingDetails(msgBody, use7bitOnly, true); 596 assertEquals("msgCount", expectedValues[0], ted.msgCount); 597 assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount); 598 assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining); 599 assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize); 600 } 601 } 602