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