Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 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 com.android.internal.telephony.GsmAlphabet;
     20 import com.android.internal.telephony.uicc.IccUtils;
     21 
     22 import junit.framework.TestCase;
     23 
     24 import android.test.suitebuilder.annotation.LargeTest;
     25 import android.test.suitebuilder.annotation.SmallTest;
     26 
     27 public class GsmAlphabetTest extends TestCase {
     28 
     29     private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
     30 
     31     @SmallTest
     32     public void test7bitWithHeader() throws Exception {
     33         SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
     34         concatRef.refNumber = 1;
     35         concatRef.seqNumber = 2;
     36         concatRef.msgCount = 2;
     37         concatRef.isEightBits = true;
     38         SmsHeader header = new SmsHeader();
     39         header.concatRef = concatRef;
     40 
     41         String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
     42         byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message,
     43                 SmsHeader.toByteArray(header), 0, 0);
     44         int septetCount = GsmAlphabet.countGsmSeptetsUsingTables(message, true, 0, 0);
     45         String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
     46                 userData, SmsHeader.toByteArray(header).length+2, septetCount, 1, 0, 0);
     47         assertEquals(message, parsedMessage);
     48     }
     49 
     50     // TODO: This method should *really* be a series of individual test methods.
     51     // However, it's a SmallTest because it executes quickly.
     52     @SmallTest
     53     public void testBasic() throws Exception {
     54         // '@' maps to char 0
     55         assertEquals(0, GsmAlphabet.charToGsm('@'));
     56 
     57         // `a (a with grave accent) maps to last GSM character
     58         assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0'));
     59 
     60         //
     61         // These are the extended chars
     62         // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE
     63         //
     64 
     65         for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
     66             assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
     67                     GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i)));
     68 
     69         }
     70 
     71         // euro symbol
     72         assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
     73                 GsmAlphabet.charToGsm('\u20ac'));
     74 
     75         // An unmappable char (the 'cent' char) maps to a space
     76         assertEquals(GsmAlphabet.charToGsm(' '),
     77                 GsmAlphabet.charToGsm('\u00a2'));
     78 
     79         // unmappable = space = 1 septet
     80         assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2'));
     81 
     82         //
     83         // Test extended table
     84         //
     85 
     86         for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
     87             assertEquals(sGsmExtendedChars.charAt(i),
     88                     GsmAlphabet.gsmExtendedToChar(
     89                             GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i))));
     90 
     91         }
     92 
     93         // Unmappable extended char
     94         assertEquals(GsmAlphabet.charToGsm(' '),
     95                 GsmAlphabet.charToGsmExtended('@'));
     96 
     97         //
     98         // gsmToChar()
     99         //
    100 
    101         assertEquals('@', GsmAlphabet.gsmToChar(0));
    102 
    103         // `a (a with grave accent) maps to last GSM character
    104         assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f));
    105 
    106         assertEquals('\uffff',
    107                 GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
    108 
    109         // Out-of-range/unmappable value
    110         assertEquals(' ', GsmAlphabet.gsmToChar(0x80));
    111 
    112         //
    113         // gsmExtendedToChar()
    114         //
    115 
    116         assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28));
    117 
    118         // No double-escapes
    119         assertEquals(' ', GsmAlphabet.gsmExtendedToChar(
    120                 GsmAlphabet.GSM_EXTENDED_ESCAPE));
    121 
    122         // Reserved for extension to extension table (mapped to space)
    123         assertEquals(' ', GsmAlphabet.gsmExtendedToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
    124 
    125         // Unmappable (mapped to character in default or national locking shift table)
    126         assertEquals('@', GsmAlphabet.gsmExtendedToChar(0));
    127         assertEquals('\u00e0', GsmAlphabet.gsmExtendedToChar(0x7f));
    128 
    129         //
    130         // stringTo7BitPacked, gsm7BitPackedToString
    131         //
    132 
    133         byte[] packed;
    134         StringBuilder testString = new StringBuilder(300);
    135 
    136         // Check all alignment cases
    137         for (int i = 0; i < 9; i++, testString.append('@')) {
    138             packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    139             assertEquals(testString.toString(),
    140                     GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
    141         }
    142 
    143         // Check full non-extended alphabet
    144         for (int i = 0; i < 0x80; i++) {
    145             char c;
    146 
    147             if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
    148                 continue;
    149             }
    150 
    151             c = GsmAlphabet.gsmToChar(i);
    152             testString.append(c);
    153 
    154             // These are all non-extended chars, so it should be
    155             // one septet per char
    156             assertEquals(1, GsmAlphabet.countGsmSeptets(c));
    157         }
    158 
    159         packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    160         assertEquals(testString.toString(),
    161                 GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
    162 
    163         // Test extended chars too
    164 
    165         testString.append(sGsmExtendedChars);
    166 
    167         for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
    168             // These are all extended chars, so it should be
    169             // two septets per char
    170             assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i)));
    171 
    172         }
    173 
    174         packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    175         assertEquals(testString.toString(),
    176                 GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
    177 
    178         // stringTo7BitPacked handles up to 255 septets
    179 
    180         testString.setLength(0);
    181         for (int i = 0; i < 255; i++) {
    182             testString.append('@');
    183         }
    184 
    185         packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    186         assertEquals(testString.toString(),
    187                 GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
    188 
    189         // > 255 septets throws runtime exception
    190         testString.append('@');
    191 
    192         try {
    193             GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    194             fail("expected exception");
    195         } catch (EncodeException ex) {
    196             // exception expected
    197         }
    198 
    199         // Try 254 septets with 127 extended chars
    200 
    201         testString.setLength(0);
    202         for (int i = 0; i < (255 / 2); i++) {
    203             testString.append('{');
    204         }
    205 
    206         packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    207         assertEquals(testString.toString(),
    208                 GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
    209 
    210         // > 255 septets throws runtime exception
    211         testString.append('{');
    212 
    213         try {
    214             GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
    215             fail("expected exception");
    216         } catch (EncodeException ex) {
    217             // exception expected
    218         }
    219 
    220         // Reserved for extension to extension table (mapped to space)
    221         packed = new byte[]{(byte)(0x1b | 0x80), 0x1b >> 1};
    222         assertEquals(" ", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
    223 
    224         // Unmappable (mapped to character in default alphabet table)
    225         packed[0] = 0x1b;
    226         packed[1] = 0x00;
    227         assertEquals("@", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
    228         packed[0] = (byte)(0x1b | 0x80);
    229         packed[1] = (byte)(0x7f >> 1);
    230         assertEquals("\u00e0", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
    231 
    232         //
    233         // 8 bit unpacked format
    234         //
    235         // Note: we compare hex strings here
    236         // because Assert doesn't have array comparisons
    237 
    238         byte unpacked[];
    239 
    240         unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
    241         assertEquals("Voice Mail",
    242                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    243 
    244         assertEquals(IccUtils.bytesToHexString(unpacked),
    245                 IccUtils.bytesToHexString(
    246                         GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
    247 
    248         unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
    249         // two bytes for every extended char
    250         assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
    251         assertEquals(sGsmExtendedChars,
    252                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    253 
    254         // should be two bytes per extended char
    255         assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
    256 
    257         // Test truncation of unaligned extended chars
    258         unpacked = new byte[3];
    259         GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked,
    260                 0, unpacked.length);
    261 
    262         // Should be one extended char and an 0xff at the end
    263 
    264         assertEquals(0xff, 0xff & unpacked[2]);
    265         assertEquals(sGsmExtendedChars.substring(0, 1),
    266                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    267 
    268         // Test truncation of normal chars
    269         unpacked = new byte[3];
    270         GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
    271                 0, unpacked.length);
    272 
    273         assertEquals("abc",
    274                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    275 
    276         // Test truncation of mixed normal and extended chars
    277         unpacked = new byte[3];
    278         GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked,
    279                 0, unpacked.length);
    280 
    281         assertEquals("a{",
    282                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    283 
    284         // Test padding after normal char
    285         unpacked = new byte[3];
    286         GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked,
    287                 0, unpacked.length);
    288 
    289         assertEquals("a",
    290                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    291 
    292         assertEquals(0xff, 0xff & unpacked[1]);
    293         assertEquals(0xff, 0xff & unpacked[2]);
    294 
    295         // Test malformed input -- escape char followed by end of field
    296         unpacked[0] = 0;
    297         unpacked[1] = 0;
    298         unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE;
    299 
    300         assertEquals("@@",
    301                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
    302 
    303         // non-zero offset
    304         assertEquals("@",
    305                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
    306 
    307         // test non-zero offset
    308         unpacked[0] = 0;
    309         GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
    310                 1, unpacked.length - 1);
    311 
    312 
    313         assertEquals(0, unpacked[0]);
    314 
    315         assertEquals("ab",
    316                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
    317 
    318         // test non-zero offset with truncated extended char
    319         unpacked[0] = 0;
    320 
    321         GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked,
    322                 1, unpacked.length - 1);
    323 
    324         assertEquals(0, unpacked[0]);
    325 
    326         assertEquals("a",
    327                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
    328 
    329         // Reserved for extension to extension table (mapped to space)
    330         unpacked[0] = 0x1b;
    331         unpacked[1] = 0x1b;
    332         assertEquals(" ", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
    333 
    334         // Unmappable (mapped to character in default or national locking shift table)
    335         unpacked[1] = 0x00;
    336         assertEquals("@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
    337         unpacked[1] = 0x7f;
    338         assertEquals("\u00e0", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
    339     }
    340 
    341     @SmallTest
    342     public void testGsm8BitUpackedWithEuckr() throws Exception {
    343         // Some feature phones in Korea store contacts as euc-kr.
    344         // Test this situations.
    345         byte unpacked[];
    346 
    347         // Test general alphabet strings.
    348         unpacked = IccUtils.hexStringToBytes("61626320646566FF");
    349         assertEquals("abc def",
    350                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
    351 
    352         // Test korean strings.
    353         unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF");
    354         assertEquals("\uD14C\uC2A4\uD2B8",
    355                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
    356 
    357         // Test gsm Extented Characters.
    358         unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
    359         assertEquals(sGsmExtendedChars,
    360                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
    361     }
    362 }
    363