Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b53bb26 authored by Xia Ying's avatar Xia Ying Committed by Amit Mahajan
Browse files

Sms7BitEncodingTranslator

Bug: 16197894
Change-Id: I389248343c4ee621a1e8980481987742623bcbe7
parent de9bf648
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -808,7 +808,7 @@ public final class SmsManager {
     *
     * @hide
     */
    boolean isImsSmsSupported() {
    public boolean isImsSmsSupported() {
        boolean boSupported = false;
        try {
            ISms iccISms = getISmsService();
@@ -833,7 +833,7 @@ public final class SmsManager {
     *
     * @hide
     */
    String getImsSmsFormat() {
    public String getImsSmsFormat() {
        String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN;
        try {
            ISms iccISms = getISmsService();
+12 −3
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
import com.android.internal.telephony.Sms7BitEncodingTranslator;

import java.lang.Math;
import java.util.ArrayList;
@@ -363,8 +364,16 @@ public class SmsMessage {
            }
        }

        String newMsgBody = null;
        Resources r = Resources.getSystem();
        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
            newMsgBody  = Sms7BitEncodingTranslator.translate(text);
        }
        if (TextUtils.isEmpty(newMsgBody)) {
            newMsgBody = text;
        }
        int pos = 0;  // Index in code units.
        int textLen = text.length();
        int textLen = newMsgBody.length();
        ArrayList<String> result = new ArrayList<String>(ted.msgCount);
        while (pos < textLen) {
            int nextPos = 0;  // Counts code units.
@@ -374,7 +383,7 @@ public class SmsMessage {
                    nextPos = pos + Math.min(limit, textLen - pos);
                } else {
                    // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
                    nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit,
                    nextPos = GsmAlphabet.findGsmSeptetLimitIndex(newMsgBody, pos, limit,
                            ted.languageTable, ted.languageShiftTable);
                }
            } else {  // Assume unicode.
@@ -385,7 +394,7 @@ public class SmsMessage {
                          nextPos + " >= " + textLen + ")");
                break;
            }
            result.add(text.substring(pos, nextPos));
            result.add(newMsgBody.substring(pos, nextPos));
            pos = nextPos;
        }
        return result;
+234 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import android.telephony.Rlog;
import android.os.Build;
import android.util.SparseIntArray;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;

import com.android.internal.util.XmlUtils;
import com.android.internal.telephony.cdma.sms.UserData;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

public class Sms7BitEncodingTranslator {
    private static final String TAG = "Sms7BitEncodingTranslator";
    private static final boolean DBG = Build.IS_DEBUGGABLE ;
    private static boolean mIs7BitTranslationTableLoaded = false;
    private static SparseIntArray mTranslationTable = null;
    private static SparseIntArray mTranslationTableCommon = null;
    private static SparseIntArray mTranslationTableGSM = null;
    private static SparseIntArray mTranslationTableCDMA = null;

    // Parser variables
    private static final String XML_START_TAG = "SmsEnforce7BitTranslationTable";
    private static final String XML_TRANSLATION_TYPE_TAG = "TranslationType";
    private static final String XML_CHARACTOR_TAG = "Character";
    private static final String XML_FROM_TAG = "from";
    private static final String XML_TO_TAG = "to";

    /**
     * Translates each message character that is not supported by GSM 7bit
     * alphabet into a supported one
     *
     * @param message
     *            message to be translated
     * @param throwsException
     *            if true and some error occurs during translation, an exception
     *            is thrown; otherwise a null String is returned
     * @return translated message or null if some error occur
     */
    public static String translate(CharSequence message) {
        if (message == null) {
            Rlog.w(TAG, "Null message can not be translated");
            return null;
        }

        int size = message.length();
        if (size <= 0) {
            return "";
        }

        if (!mIs7BitTranslationTableLoaded) {
            mTranslationTableCommon = new SparseIntArray();
            mTranslationTableGSM = new SparseIntArray();
            mTranslationTableCDMA = new SparseIntArray();
            load7BitTranslationTableFromXml();
            mIs7BitTranslationTableLoaded = true;
        }

        if ((mTranslationTableCommon != null && mTranslationTableCommon.size() > 0) ||
                (mTranslationTableGSM != null && mTranslationTableGSM.size() > 0) ||
                (mTranslationTableCDMA != null && mTranslationTableCDMA.size() > 0)) {
            char[] output = new char[size];
            for (int i = 0; i < size; i++) {
                output[i] = translateIfNeeded(message.charAt(i));
            }

            return String.valueOf(output);
        }

        return null;
    }

    /**
     * Translates a single character into its corresponding acceptable one, if
     * needed, based on GSM 7-bit alphabet
     *
     * @param c
     *            character to be translated
     * @return original character, if it's present on GSM 7-bit alphabet; a
     *         corresponding character, based on the translation table or white
     *         space, if no mapping is found in the translation table for such
     *         character
     */
    private static char translateIfNeeded(char c) {
        if (noTranslationNeeded(c)) {
            if (DBG) {
                Rlog.v(TAG, "No translation needed for " + Integer.toHexString(c));
            }
            return c;
        }

        /*
         * Trying to translate unicode to Gsm 7-bit alphabet; If c is not
         * present on translation table, c does not belong to Unicode Latin-1
         * (Basic + Supplement), so we don't know how to translate it to a Gsm
         * 7-bit character! We replace c for an empty space and advises the user
         * about it.
         */
        int translation = -1;

        if (mTranslationTableCommon != null) {
            translation = mTranslationTableCommon.get(c, -1);
        }

        if (translation == -1) {
            if (useCdmaFormatForMoSms()) {
                if (mTranslationTableCDMA != null) {
                    translation = mTranslationTableCDMA.get(c, -1);
                }
            } else {
                if (mTranslationTableGSM != null) {
                    translation = mTranslationTableGSM.get(c, -1);
                }
            }
        }

        if (translation != -1) {
            if (DBG) {
                Rlog.v(TAG, Integer.toHexString(c) + " (" + c + ")" + " translated to "
                        + Integer.toHexString(translation) + " (" + (char) translation + ")");
            }
            return (char) translation;
        } else {
            if (DBG) {
                Rlog.w(TAG, "No translation found for " + Integer.toHexString(c)
                        + "! Replacing for empty space");
            }
            return ' ';
        }
    }

    private static boolean noTranslationNeeded(char c) {
        if (useCdmaFormatForMoSms()) {
            return GsmAlphabet.isGsmSeptets(c) && UserData.charToAscii.get(c, -1) != -1;
        }
        else {
            return GsmAlphabet.isGsmSeptets(c);
        }
    }

    private static boolean useCdmaFormatForMoSms() {
        if (!SmsManager.getDefault().isImsSmsSupported()) {
            // use Voice technology to determine SMS format.
            return TelephonyManager.getDefault().getCurrentPhoneType()
                    == PhoneConstants.PHONE_TYPE_CDMA;
        }
        // IMS is registered with SMS support, check the SMS format supported
        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
    }

    /**
     * Load the whole translation table file from the framework resource
     * encoded in XML.
     */
    private static void load7BitTranslationTableFromXml() {
        XmlResourceParser parser = null;
        Resources r = Resources.getSystem();

        if (parser == null) {
            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: open normal file");
            parser = r.getXml(com.android.internal.R.xml.sms_7bit_translation_table);
        }

        try {
            XmlUtils.beginDocument(parser, XML_START_TAG);
            while (true)  {
                XmlUtils.nextElement(parser);
                String tag = parser.getName();
                if (DBG) {
                    Rlog.d(TAG, "tag: " + tag);
                }
                if (XML_TRANSLATION_TYPE_TAG.equals(tag)) {
                    String type = parser.getAttributeValue(null, "Type");
                    if (DBG) {
                        Rlog.d(TAG, "type: " + type);
                    }
                    if (type.equals("common")) {
                        mTranslationTable = mTranslationTableCommon;
                    } else if (type.equals("gsm")) {
                        mTranslationTable = mTranslationTableGSM;
                    } else if (type.equals("cdma")) {
                        mTranslationTable = mTranslationTableCDMA;
                    } else {
                        Rlog.e(TAG, "Error Parsing 7BitTranslationTable: found incorrect type" + type);
                    }
                } else if (XML_CHARACTOR_TAG.equals(tag) && mTranslationTable != null) {
                    int from = parser.getAttributeUnsignedIntValue(null,
                            XML_FROM_TAG, -1);
                    int to = parser.getAttributeUnsignedIntValue(null,
                            XML_TO_TAG, -1);
                    if ((from != -1) && (to != -1)) {
                        if (DBG) {
                            Rlog.d(TAG, "Loading mapping " + Integer.toHexString(from)
                                    .toUpperCase() + " -> " + Integer.toHexString(to)
                                    .toUpperCase());
                        }
                        mTranslationTable.put (from, to);
                    } else {
                        Rlog.d(TAG, "Invalid translation table file format");
                    }
                } else {
                    break;
                }
            }
            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: parsing successful, file loaded");
        } catch (Exception e) {
            Rlog.e(TAG, "Got exception while loading 7BitTranslationTable file.", e);
        } finally {
            if (parser instanceof XmlResourceParser) {
                ((XmlResourceParser)parser).close();
            }
        }
    }
}
+12 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.telephony.SmsCbMessage;
import android.telephony.cdma.CdmaSmsCbProgramData;
import android.telephony.Rlog;
import android.util.Log;
import android.text.TextUtils;
import android.content.res.Resources;

import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.SmsConstants;
@@ -38,6 +40,7 @@ import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.HexDump;
import com.android.internal.telephony.Sms7BitEncodingTranslator;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -458,7 +461,15 @@ public class SmsMessage extends SmsMessageBase {
     */
    public static TextEncodingDetails calculateLength(CharSequence messageBody,
            boolean use7bitOnly) {
        return BearerData.calcTextEncodingDetails(messageBody, use7bitOnly);
        CharSequence newMsgBody = null;
        Resources r = Resources.getSystem();
        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
            newMsgBody  = Sms7BitEncodingTranslator.translate(messageBody);
        }
        if (TextUtils.isEmpty(newMsgBody)) {
            newMsgBody = messageBody;
        }
        return BearerData.calcTextEncodingDetails(newMsgBody, use7bitOnly);
    }

    /**
+13 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.telephony.PhoneNumberUtils;
import android.text.format.Time;
import android.telephony.Rlog;
import android.content.res.Resources;
import android.text.TextUtils;

import com.android.internal.telephony.EncodeException;
import com.android.internal.telephony.GsmAlphabet;
@@ -27,6 +28,7 @@ import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.Sms7BitEncodingTranslator;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
@@ -783,11 +785,19 @@ public class SmsMessage extends SmsMessageBase {
     */
    public static TextEncodingDetails calculateLength(CharSequence msgBody,
            boolean use7bitOnly) {
        TextEncodingDetails ted = GsmAlphabet.countGsmSeptets(msgBody, use7bitOnly);
        CharSequence newMsgBody = null;
        Resources r = Resources.getSystem();
        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
            newMsgBody  = Sms7BitEncodingTranslator.translate(msgBody);
        }
        if (TextUtils.isEmpty(newMsgBody)) {
            newMsgBody = msgBody;
        }
        TextEncodingDetails ted = GsmAlphabet.countGsmSeptets(newMsgBody, use7bitOnly);
        if (ted == null) {
            ted = new TextEncodingDetails();
            int octets = msgBody.length() * 2;
            ted.codeUnitCount = msgBody.length();
            int octets = newMsgBody.length() * 2;
            ted.codeUnitCount = newMsgBody.length();
            if (octets > MAX_USER_DATA_BYTES) {
                // If EMS is not supported, break down EMS into single segment SMS
                // and add page info " x/y".