diff options
author | Sang-il, Lee <gendoh@google.com> | 2010-08-05 17:07:01 +0900 |
---|---|---|
committer | Jake Hamby <jhamby@google.com> | 2010-09-09 13:23:42 -0700 |
commit | b55df4471ed55a0e91dee79304f3b1209ffa4b35 (patch) | |
tree | 1dee7f8ef7b1fbd7cd278755a824306ea366c278 /telephony | |
parent | 3e2d81cb73a81c4429d9a8ea5271724e842838fc (diff) | |
download | frameworks_base-b55df4471ed55a0e91dee79304f3b1209ffa4b35.zip frameworks_base-b55df4471ed55a0e91dee79304f3b1209ffa4b35.tar.gz frameworks_base-b55df4471ed55a0e91dee79304f3b1209ffa4b35.tar.bz2 |
Support MBCS characters in contacts and SMS messages that are stored in SIM cards.
Change-Id: I0438c5748a47512fc2a0e4b89ac85e30e3f5c6de
Diffstat (limited to 'telephony')
5 files changed, 119 insertions, 3 deletions
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index d899430..0746562 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -53,6 +53,10 @@ public class SmsMessage { public static final int ENCODING_7BIT = 1; public static final int ENCODING_8BIT = 2; public static final int ENCODING_16BIT = 3; + /** + * @hide This value is not defined in global standard. Only in Korea, this is used. + */ + public static final int ENCODING_KSC5601 = 4; /** The maximum number of payload bytes per message */ public static final int MAX_USER_DATA_BYTES = 140; diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java index 75ea116..e42827f 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java @@ -16,10 +16,14 @@ package com.android.internal.telephony; +import android.text.TextUtils; import android.util.SparseIntArray; import android.util.Log; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + /** * This class implements the character set mapping between * the GSM SMS 7-bit alphabet specified in TS 23.038 6.2.1 @@ -354,6 +358,32 @@ public class GsmAlphabet { */ public static String gsm8BitUnpackedToString(byte[] data, int offset, int length) { + return gsm8BitUnpackedToString(data, offset, length, ""); + } + + /** + * Convert a GSM alphabet string that's stored in 8-bit unpacked + * format (as it often appears in SIM records) into a String + * + * Field may be padded with trailing 0xff's. The decode stops + * at the first 0xff encountered. + * + * Additionally, in some country(ex. Korea), there are non-ASCII or MBCS characters. + * If a character set is given, characters in data are treat as MBCS. + */ + public static String + gsm8BitUnpackedToString(byte[] data, int offset, int length, String characterset) { + boolean isMbcs = false; + Charset charset = null; + ByteBuffer mbcsBuffer = null; + + if (!TextUtils.isEmpty(characterset) + && !characterset.equalsIgnoreCase("us-ascii") + && Charset.isSupported(characterset)) { + isMbcs = true; + charset = Charset.forName(characterset); + mbcsBuffer = ByteBuffer.allocate(2); + } boolean prevWasEscape; StringBuilder ret = new StringBuilder(length); @@ -379,7 +409,15 @@ public class GsmAlphabet { if (prevWasEscape) { ret.append((char)gsmExtendedToChar.get(c, ' ')); } else { - ret.append((char)gsmToChar.get(c, ' ')); + if (!isMbcs || c < 0x80 || i + 1 >= offset + length) { + ret.append((char)gsmToChar.get(c, ' ')); + } else { + // isMbcs must be true. So both mbcsBuffer and charset are initialized. + mbcsBuffer.clear(); + mbcsBuffer.put(data, i++, 2); + mbcsBuffer.flip(); + ret.append(charset.decode(mbcsBuffer).toString()); + } } prevWasEscape = false; } diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java index 005ae37..df579b0 100644 --- a/telephony/java/com/android/internal/telephony/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/IccUtils.java @@ -16,13 +16,16 @@ package com.android.internal.telephony; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Color; import android.util.Log; import com.android.internal.telephony.GsmAlphabet; - import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; /** * Various methods, useful for dealing with SIM data. @@ -150,6 +153,9 @@ public class IccUtils { */ public static String adnStringFieldToString(byte[] data, int offset, int length) { + if (length == 0) { + return ""; + } if (length >= 1) { if (data[offset] == (byte) 0x80) { int ucslen = (length - 1) / 2; @@ -225,7 +231,15 @@ public class IccUtils { return ret.toString(); } - return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length); + Resources resource = Resources.getSystem(); + String defaultCharset = ""; + try { + defaultCharset = + resource.getString(com.android.internal.R.string.gsm_alphabet_default_charset); + } catch (NotFoundException e) { + // Ignore Exception and defaultCharset is set to a empty string. + } + return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim()); } static int diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index a77484a..e24613f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -33,6 +33,7 @@ import java.io.UnsupportedEncodingException; import static android.telephony.SmsMessage.ENCODING_7BIT; import static android.telephony.SmsMessage.ENCODING_8BIT; import static android.telephony.SmsMessage.ENCODING_16BIT; +import static android.telephony.SmsMessage.ENCODING_KSC5601; import static android.telephony.SmsMessage.ENCODING_UNKNOWN; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; @@ -776,6 +777,27 @@ public class SmsMessage extends SmsMessageBase { return ret; } + /** + * Interprets the user data payload as KSC-5601 characters, and + * decodes them into a String. + * + * @param byteCount the number of bytes in the user data payload + * @return a String with the decoded characters + */ + String getUserDataKSC5601(int byteCount) { + String ret; + + try { + ret = new String(pdu, cur, byteCount, "KSC5601"); + } catch (UnsupportedEncodingException ex) { + ret = ""; + Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); + } + + cur += byteCount; + return ret; + } + boolean moreDataPresent() { return (pdu.length > cur); } @@ -1111,6 +1133,16 @@ public class SmsMessage extends SmsMessageBase { Log.w(LOG_TAG, "MWI for fax, email, or other " + (dataCodingScheme & 0xff)); } + } else if ((dataCodingScheme & 0xC0) == 0x80) { + // 3GPP TS 23.038 V7.0.0 (2006-03) section 4 + // 0x80..0xBF == Reserved coding groups + if (dataCodingScheme == 0x84) { + // This value used for KSC5601 by carriers in Korea. + encodingType = ENCODING_KSC5601; + } else { + Log.w(LOG_TAG, "5 - Unsupported SMS data coding scheme " + + (dataCodingScheme & 0xff)); + } } else { Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " + (dataCodingScheme & 0xff)); @@ -1135,6 +1167,10 @@ public class SmsMessage extends SmsMessageBase { case ENCODING_16BIT: messageBody = p.getUserDataUCS2(count); break; + + case ENCODING_KSC5601: + messageBody = p.getUserDataKSC5601(count); + break; } if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'"); diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java index a6b9a2a..7011aeb 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import com.android.internal.telephony.GsmAlphabet; + import junit.framework.TestCase; import android.test.suitebuilder.annotation.LargeTest; @@ -307,4 +309,26 @@ public class GsmAlphabetTest extends TestCase { assertEquals("a", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); } + + @SmallTest + public void testGsm8BitUpackedWithEuckr() throws Exception { + // Some feature phones in Korea store contacts as euc-kr. + // Test this situations. + byte unpacked[]; + + // Test general alphabet strings. + unpacked = IccUtils.hexStringToBytes("61626320646566FF"); + assertEquals("abc def", + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + + // Test korean strings. + unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF"); + assertEquals("\uD14C\uC2A4\uD2B8", + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + + // Test gsm Extented Characters. + unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars); + assertEquals(sGsmExtendedChars, + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + } } |