18b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying/*
28b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * Copyright (C) 2014 The Android Open Source Project
38b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying *
48b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * Licensed under the Apache License, Version 2.0 (the "License");
58b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * you may not use this file except in compliance with the License.
68b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * You may obtain a copy of the License at
78b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying *
88b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying *      http://www.apache.org/licenses/LICENSE-2.0
98b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying *
108b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * Unless required by applicable law or agreed to in writing, software
118b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * distributed under the License is distributed on an "AS IS" BASIS,
128b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * See the License for the specific language governing permissions and
148b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying * limitations under the License.
158b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying */
168b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
178b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingpackage com.android.internal.telephony;
188b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
198b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.telephony.Rlog;
208b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.os.Build;
218b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.util.SparseIntArray;
228b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.content.res.Resources;
238b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.content.res.XmlResourceParser;
248b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.telephony.SmsManager;
258b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport android.telephony.TelephonyManager;
268b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
278b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport com.android.internal.util.XmlUtils;
288b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport com.android.internal.telephony.cdma.sms.UserData;
298b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
308b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport org.xmlpull.v1.XmlPullParser;
318b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingimport org.xmlpull.v1.XmlPullParserException;
328b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
338b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Yingpublic class Sms7BitEncodingTranslator {
348b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String TAG = "Sms7BitEncodingTranslator";
358b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final boolean DBG = Build.IS_DEBUGGABLE ;
368b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static boolean mIs7BitTranslationTableLoaded = false;
378b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static SparseIntArray mTranslationTable = null;
388b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static SparseIntArray mTranslationTableCommon = null;
398b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static SparseIntArray mTranslationTableGSM = null;
408b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static SparseIntArray mTranslationTableCDMA = null;
418b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
428b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    // Parser variables
438b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String XML_START_TAG = "SmsEnforce7BitTranslationTable";
448b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String XML_TRANSLATION_TYPE_TAG = "TranslationType";
458b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String XML_CHARACTOR_TAG = "Character";
468b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String XML_FROM_TAG = "from";
478b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static final String XML_TO_TAG = "to";
488b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
498b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    /**
508b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * Translates each message character that is not supported by GSM 7bit
518b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * alphabet into a supported one
528b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *
538b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * @param message
548b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *            message to be translated
558b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * @param throwsException
568b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *            if true and some error occurs during translation, an exception
578b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *            is thrown; otherwise a null String is returned
588b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * @return translated message or null if some error occur
598b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     */
608b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    public static String translate(CharSequence message) {
618b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (message == null) {
628b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            Rlog.w(TAG, "Null message can not be translated");
638b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return null;
648b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
658b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
668b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        int size = message.length();
678b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (size <= 0) {
688b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return "";
698b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
708b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
718b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (!mIs7BitTranslationTableLoaded) {
728b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            mTranslationTableCommon = new SparseIntArray();
738b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            mTranslationTableGSM = new SparseIntArray();
748b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            mTranslationTableCDMA = new SparseIntArray();
758b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            load7BitTranslationTableFromXml();
768b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            mIs7BitTranslationTableLoaded = true;
778b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
788b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
798b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if ((mTranslationTableCommon != null && mTranslationTableCommon.size() > 0) ||
808b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                (mTranslationTableGSM != null && mTranslationTableGSM.size() > 0) ||
818b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                (mTranslationTableCDMA != null && mTranslationTableCDMA.size() > 0)) {
828b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            char[] output = new char[size];
838b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            for (int i = 0; i < size; i++) {
848b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                output[i] = translateIfNeeded(message.charAt(i));
858b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
868b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
878b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return String.valueOf(output);
888b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
898b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
908b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        return null;
918b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    }
928b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
938b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    /**
948b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * Translates a single character into its corresponding acceptable one, if
958b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * needed, based on GSM 7-bit alphabet
968b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *
978b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * @param c
988b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *            character to be translated
998b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * @return original character, if it's present on GSM 7-bit alphabet; a
1008b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *         corresponding character, based on the translation table or white
1018b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *         space, if no mapping is found in the translation table for such
1028b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     *         character
1038b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     */
1048b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static char translateIfNeeded(char c) {
1058b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (noTranslationNeeded(c)) {
1068b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (DBG) {
1078b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                Rlog.v(TAG, "No translation needed for " + Integer.toHexString(c));
1088b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
1098b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return c;
1108b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1118b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1128b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        /*
1138b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         * Trying to translate unicode to Gsm 7-bit alphabet; If c is not
1148b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         * present on translation table, c does not belong to Unicode Latin-1
1158b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         * (Basic + Supplement), so we don't know how to translate it to a Gsm
1168b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         * 7-bit character! We replace c for an empty space and advises the user
1178b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         * about it.
1188b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying         */
1198b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        int translation = -1;
1208b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1218b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (mTranslationTableCommon != null) {
1228b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            translation = mTranslationTableCommon.get(c, -1);
1238b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1248b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1258b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (translation == -1) {
1268b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (useCdmaFormatForMoSms()) {
1278b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                if (mTranslationTableCDMA != null) {
1288b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    translation = mTranslationTableCDMA.get(c, -1);
1298b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                }
1308b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            } else {
1318b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                if (mTranslationTableGSM != null) {
1328b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    translation = mTranslationTableGSM.get(c, -1);
1338b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                }
1348b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
1358b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1368b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1378b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (translation != -1) {
1388b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (DBG) {
1398b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                Rlog.v(TAG, Integer.toHexString(c) + " (" + c + ")" + " translated to "
1408b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        + Integer.toHexString(translation) + " (" + (char) translation + ")");
1418b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
1428b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return (char) translation;
1438b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        } else {
1448b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (DBG) {
1458b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                Rlog.w(TAG, "No translation found for " + Integer.toHexString(c)
1468b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        + "! Replacing for empty space");
1478b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
1488b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return ' ';
1498b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1508b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    }
1518b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1528b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static boolean noTranslationNeeded(char c) {
1538b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (useCdmaFormatForMoSms()) {
1548b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return GsmAlphabet.isGsmSeptets(c) && UserData.charToAscii.get(c, -1) != -1;
1558b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1568b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        else {
1578b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return GsmAlphabet.isGsmSeptets(c);
1588b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1598b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    }
1608b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1618b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static boolean useCdmaFormatForMoSms() {
1628b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (!SmsManager.getDefault().isImsSmsSupported()) {
1638b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            // use Voice technology to determine SMS format.
1648b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            return TelephonyManager.getDefault().getCurrentPhoneType()
1658b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    == PhoneConstants.PHONE_TYPE_CDMA;
1668b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1678b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        // IMS is registered with SMS support, check the SMS format supported
1688b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
1698b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    }
1708b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1718b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    /**
1728b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * Load the whole translation table file from the framework resource
1738b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     * encoded in XML.
1748b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying     */
1758b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    private static void load7BitTranslationTableFromXml() {
1768b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        XmlResourceParser parser = null;
1778b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        Resources r = Resources.getSystem();
1788b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1798b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        if (parser == null) {
1808b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: open normal file");
1818b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            parser = r.getXml(com.android.internal.R.xml.sms_7bit_translation_table);
1828b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
1838b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying
1848b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        try {
1858b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            XmlUtils.beginDocument(parser, XML_START_TAG);
1868b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            while (true)  {
1878b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                XmlUtils.nextElement(parser);
1888b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                String tag = parser.getName();
1898b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                if (DBG) {
1908b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    Rlog.d(TAG, "tag: " + tag);
1918b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                }
1928b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                if (XML_TRANSLATION_TYPE_TAG.equals(tag)) {
1938b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    String type = parser.getAttributeValue(null, "Type");
1948b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    if (DBG) {
1958b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        Rlog.d(TAG, "type: " + type);
1968b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    }
1978b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    if (type.equals("common")) {
1988b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        mTranslationTable = mTranslationTableCommon;
1998b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    } else if (type.equals("gsm")) {
2008b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        mTranslationTable = mTranslationTableGSM;
2018b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    } else if (type.equals("cdma")) {
2028b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        mTranslationTable = mTranslationTableCDMA;
2038b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    } else {
2048b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        Rlog.e(TAG, "Error Parsing 7BitTranslationTable: found incorrect type" + type);
2058b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    }
2068b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                } else if (XML_CHARACTOR_TAG.equals(tag) && mTranslationTable != null) {
2078b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    int from = parser.getAttributeUnsignedIntValue(null,
2088b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                            XML_FROM_TAG, -1);
2098b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    int to = parser.getAttributeUnsignedIntValue(null,
2108b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                            XML_TO_TAG, -1);
2118b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    if ((from != -1) && (to != -1)) {
2128b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        if (DBG) {
2138b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                            Rlog.d(TAG, "Loading mapping " + Integer.toHexString(from)
2148b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                                    .toUpperCase() + " -> " + Integer.toHexString(to)
2158b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                                    .toUpperCase());
2168b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        }
2178b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        mTranslationTable.put (from, to);
2188b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    } else {
2198b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                        Rlog.d(TAG, "Invalid translation table file format");
2208b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    }
2218b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                } else {
2228b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                    break;
2238b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                }
2248b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
2258b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: parsing successful, file loaded");
2268b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        } catch (Exception e) {
2278b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            Rlog.e(TAG, "Got exception while loading 7BitTranslationTable file.", e);
2288b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        } finally {
2298b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            if (parser instanceof XmlResourceParser) {
2308b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying                ((XmlResourceParser)parser).close();
2318b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying            }
2328b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying        }
2338b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying    }
2348b53bb26569395511e3dbd5f94bda74ea6b9e37cXia Ying}
235