diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2010-12-21 12:05:04 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-12-21 12:05:04 -0800 |
commit | b3177c135bb7a3db3318893335a9ac0bc39d9cf8 (patch) | |
tree | 5ec90fff3e1c204f1acdeab338e2f53a470a1f64 /telephony | |
parent | 490db31b851af9195f8f5bd4c5b21f59be56b207 (diff) | |
parent | 749c627fc0f30dd3db051f22f20b69a51dc19e59 (diff) | |
download | frameworks_base-b3177c135bb7a3db3318893335a9ac0bc39d9cf8.zip frameworks_base-b3177c135bb7a3db3318893335a9ac0bc39d9cf8.tar.gz frameworks_base-b3177c135bb7a3db3318893335a9ac0bc39d9cf8.tar.bz2 |
am 749c627f: Merge "Support for KSC5601 on SIM."
* commit '749c627fc0f30dd3db051f22f20b69a51dc19e59':
Support for KSC5601 on SIM.
Diffstat (limited to 'telephony')
7 files changed, 192 insertions, 1 deletions
diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java index 1bf2d3c..a01b00d 100644 --- a/telephony/java/com/android/internal/telephony/AdnRecord.java +++ b/telephony/java/com/android/internal/telephony/AdnRecord.java @@ -283,7 +283,7 @@ public class AdnRecord implements Parcelable { private void parseRecord(byte[] record) { try { - alphaTag = IccUtils.adnStringFieldToString( + alphaTag = IccUtils.adnStringFieldToStringKsc5601Support( record, 0, record.length - FOOTER_SIZE_BYTES); int footerOffset = record.length - FOOTER_SIZE_BYTES; diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java index 957eddd..5bd7523 100644 --- a/telephony/java/com/android/internal/telephony/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/IccUtils.java @@ -150,6 +150,47 @@ public class IccUtils { */ public static String adnStringFieldToString(byte[] data, int offset, int length) { + String s = adnStringFieldToStringUcs2Helper(data, offset, length); + if (s == null) { + s = adnStringFieldToStringGsm8BitHelper(data, offset, length); + } + return s; + } + + /** + * Almost identical to the method {@link #adnStringFieldToString}. + * + * Exception: + * If the SIM is Korean (MCC equals "450"), KSC5601 encoding will be + * assumed (instead of GSM8Bit). This could lead to unintended consequences, + * if the ADN alphaTag was saved with GSM8Bit. This is considered an + * acceptable risk. + */ + public static String + adnStringFieldToStringKsc5601Support(byte[] data, int offset, int length) { + String s = adnStringFieldToStringUcs2Helper(data, offset, length); + + if (s == null) { + if (SimRegionCache.getRegion() == SimRegionCache.MCC_KOREAN) { + try { + int len = offset; + byte stop = (byte)0xFF; + while (len < length && data[len] != stop) { + len++; + } + return new String(data, offset, len, "KSC5601"); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "implausible UnsupportedEncodingException", e); + } + } + + return adnStringFieldToStringGsm8BitHelper(data, offset, length); + } + return s; + } + + private static String + adnStringFieldToStringUcs2Helper(byte[] data, int offset, int length) { if (length >= 1) { if (data[offset] == (byte) 0x80) { int ucslen = (length - 1) / 2; @@ -225,6 +266,11 @@ public class IccUtils { return ret.toString(); } + return null; + } + + private static String + adnStringFieldToStringGsm8BitHelper(byte[] data, int offset, int length) { return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length); } diff --git a/telephony/java/com/android/internal/telephony/SimRegionCache.java b/telephony/java/com/android/internal/telephony/SimRegionCache.java new file mode 100644 index 0000000..2cf6d25 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SimRegionCache.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 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.os.SystemProperties; + +public class SimRegionCache { + public static final int MCC_UNSET = Integer.MIN_VALUE; + public static final int MCC_KOREAN = 450; + + private static int regionFromMcc = MCC_UNSET; + + /** + * Returns the region as read from the MCC of the SIM card. + * If the property {@link TelephonyProperties# + * PROPERTY_ICC_OPERATOR_NUMERIC} + * returns null or an empty String, the value is {@link #MCC_UNSET} + * + * @return the cached region, if set. + */ + public static int getRegion() { + if (regionFromMcc == MCC_UNSET) { + String plmn = SystemProperties.get( + TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, + null); + + if (plmn != null && plmn.length() >= 3) { + try { + regionFromMcc = Integer.parseInt(plmn.substring(0, 3)); + } catch(Exception e) { + // Nothing that can be done here. + } + } + } + return regionFromMcc; + } +} diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 9a3c476..f4c5e6c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -24,6 +24,7 @@ import android.util.Log; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; +import com.android.internal.telephony.SimRegionCache; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; @@ -48,6 +49,12 @@ import static android.telephony.SmsMessage.MessageClass; public class SmsMessage extends SmsMessageBase{ static final String LOG_TAG = "GSM"; + /** + * Used with the ENCODING_ constants from {@link android.telephony.SmsMessage} + * Not a part of the public API, therefore not in order with those constants. + */ + private static final int ENCODING_KSC5601 = 4000; + private MessageClass messageClass; /** @@ -781,6 +788,28 @@ public class SmsMessage extends SmsMessageBase{ return ret; } + /** + * Interprets the user data payload as KSC5601 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) { + // Should return same as ENCODING_UNKNOWN on error. + ret = null; + Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); + } + + cur += byteCount; + return ret; + } + boolean moreDataPresent() { return (pdu.length > cur); } @@ -1110,6 +1139,10 @@ public class SmsMessage extends SmsMessageBase{ } else { Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " + (dataCodingScheme & 0xff)); + if (SimRegionCache.getRegion() == SimRegionCache.MCC_KOREAN) { + Log.w(LOG_TAG, "Korean SIM, using KSC5601 for decoding."); + encodingType = ENCODING_KSC5601; + } } // set both the user data and the user data header. @@ -1131,6 +1164,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/AdnRecordTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java index 8a4a285..5511c09c 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java @@ -170,6 +170,18 @@ public class AdnRecordTest extends TestCase { assertEquals("Adgjm", adn.getAlphaTag()); assertEquals("+18885551212,12345678", adn.getNumber()); assertFalse(adn.isEmpty()); + + // + // Test that a ADN record with KSC5601 will get converted correctly + // This test will only be run when using a Korean SIM + // + if (SimRegionCache.getRegion() == SimRegionCache.MCC_KOREAN) { + adn = new AdnRecord(IccUtils.hexStringToBytes( + "3030312C20C8AB41B1E6FFFFFFFFFFFF07811010325476F8FFFFFFFFFFFF")); + assertEquals("001, \uD64DA\uAE38", adn.getAlphaTag()); + assertEquals("01012345678", adn.getNumber()); + assertFalse(adn.isEmpty()); + } } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java index 8a66614..f578a8d 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java @@ -102,4 +102,25 @@ public class SMSDispatcherTest extends AndroidTestCase { sms = SmsMessage.createFromEfRecord(1, data); assertNotNull(sms.getMessageBody()); } + + @MediumTest + public void testEfRecordKorean() throws Exception { + if (SimRegionCache.getRegion() == SimRegionCache.MCC_KOREAN) { + SmsMessage sms; + + String s = "01089128010099010259040ba11000000000f00095013091900563008c4142" + + "434445b0a1b3aab4d9b6f3b8b631323334354142434445b0a1b3aab4d9b6f3" + + "b8b631323334354142434445b0a1b3aab4d9b6f3b8b6313233343541424344" + + "45b0a1b3aab4d9b6f3b8b63132333435000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000ffffffffffffff"; + + + byte[] data = IccUtils.hexStringToBytes(s); + + sms = SmsMessage.createFromEfRecord(1, data); + assertNotNull(sms.getMessageBody()); + assertTrue(sms.getMessageBody().startsWith("ABCDE\uAC00\uB098\uB2E4\uB77C\uB9C812345ABCDE")); + } + } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java index db38ede..0502636 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java @@ -82,6 +82,30 @@ public class SimUtilsTest extends TestCase { data = IccUtils.hexStringToBytes("820505302D82d32d31"); // Example from 3GPP TS 11.11 V18.1.3.0 annex B assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToString(data, 0, data.length)); + + /* + * adnStringFieldToStringKsc5601Support() + * Tests equal the ones above, and will only be run if the SIM is NOT korean. + */ + + if (SimRegionCache.getRegion() != SimRegionCache.MCC_KOREAN) { + data = IccUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff"); + // Again, skip prepended 0 + // (this is an EF[ADN] record) + assertEquals("Voice Mail", IccUtils.adnStringFieldToStringKsc5601Support(data, 1, data.length - 15)); + + data = IccUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF"); + // (this is from an EF[ADN] record) + assertEquals("\u9673\u539A\u5764/M", IccUtils.adnStringFieldToStringKsc5601Support(data, 0, data.length)); + + data = IccUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF"); + // (this is made up to test since I don't have a real one) + assertEquals("Vo\u00ECce M\u00E0il", IccUtils.adnStringFieldToStringKsc5601Support(data, 0, data.length)); + + data = IccUtils.hexStringToBytes("820505302D82d32d31"); + // Example from 3GPP TS 11.11 V18.1.3.0 annex B + assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToStringKsc5601Support(data, 0, data.length)); + } } } |