summaryrefslogtreecommitdiffstats
path: root/telephony
diff options
context:
space:
mode:
authorSang-il, Lee <gendoh@google.com>2010-08-05 17:07:01 +0900
committerJake Hamby <jhamby@google.com>2010-09-09 13:23:42 -0700
commitb55df4471ed55a0e91dee79304f3b1209ffa4b35 (patch)
tree1dee7f8ef7b1fbd7cd278755a824306ea366c278 /telephony
parent3e2d81cb73a81c4429d9a8ea5271724e842838fc (diff)
downloadframeworks_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')
-rw-r--r--telephony/java/android/telephony/SmsMessage.java4
-rw-r--r--telephony/java/com/android/internal/telephony/GsmAlphabet.java40
-rw-r--r--telephony/java/com/android/internal/telephony/IccUtils.java18
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsMessage.java36
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java24
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"));
+ }
}