Merge tag 'android-11.0.0_r48' into int/11/fp3
Android 11.0.0 Release 48 (RD2A.211001.002)
* tag 'android-11.0.0_r48':
Change-Id: I3088ffad48e5ab2ff896bfb8eafa70d08862076a
diff --git a/src/com/android/cellbroadcastservice/GsmAlphabet.java b/src/com/android/cellbroadcastservice/GsmAlphabet.java
index 1efb7be..5565d44 100644
--- a/src/com/android/cellbroadcastservice/GsmAlphabet.java
+++ b/src/com/android/cellbroadcastservice/GsmAlphabet.java
@@ -16,9 +16,13 @@
package com.android.cellbroadcastservice;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;
+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
@@ -723,4 +727,103 @@
return ret.toString();
}
+
+ /**
+ * 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.
+ *
+ * @param data the byte array to decode
+ * @param offset array offset for the first character to decode
+ * @param length the number of bytes to decode
+ * @return the decoded string
+ */
+ 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);
+ }
+
+ // Always use GSM 7 bit default alphabet table for this method
+ String languageTableToChar = sLanguageTables[0];
+ String shiftTableToChar = sLanguageShiftTables[0];
+
+ StringBuilder ret = new StringBuilder(length);
+ boolean prevWasEscape = false;
+ for (int i = offset; i < offset + length; i++) {
+ // Never underestimate the pain that can be caused
+ // by signed bytes
+ int c = data[i] & 0xff;
+
+ if (c == 0xff) {
+ break;
+ } else if (c == GSM_EXTENDED_ESCAPE) {
+ if (prevWasEscape) {
+ // Two escape chars in a row
+ // We treat this as a space
+ // See Note 1 in table 6.2.1.1 of TS 23.038 v7.00
+ ret.append(' ');
+ prevWasEscape = false;
+ } else {
+ prevWasEscape = true;
+ }
+ } else {
+ if (prevWasEscape) {
+ char shiftChar =
+ c < shiftTableToChar.length() ? shiftTableToChar.charAt(c) : ' ';
+ if (shiftChar == ' ') {
+ // display character from main table if not present in shift table
+ if (c < languageTableToChar.length()) {
+ ret.append(languageTableToChar.charAt(c));
+ } else {
+ ret.append(' ');
+ }
+ } else {
+ ret.append(shiftChar);
+ }
+ } else {
+ if (!isMbcs || c < 0x80 || i + 1 >= offset + length) {
+ if (c < languageTableToChar.length()) {
+ ret.append(languageTableToChar.charAt(c));
+ } else {
+ ret.append(' ');
+ }
+ } 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;
+ }
+ }
+
+ return ret.toString();
+ }
}
diff --git a/src/com/android/cellbroadcastservice/GsmSmsCbMessage.java b/src/com/android/cellbroadcastservice/GsmSmsCbMessage.java
index 2e14c83..d5d39d7 100644
--- a/src/com/android/cellbroadcastservice/GsmSmsCbMessage.java
+++ b/src/com/android/cellbroadcastservice/GsmSmsCbMessage.java
@@ -390,6 +390,12 @@
}
break;
+ case SmsMessage.ENCODING_8BIT:
+ // Support decoding the pdu as pack GSM 8-bit (a GSM alphabet string that's stored
+ // in 8-bit unpacked format) characters.
+ body = GsmAlphabet.gsm8BitUnpackedToString(pdu, offset, length);
+ break;
+
case SmsMessage.ENCODING_16BIT:
if (dcs.hasLanguageIndicator && pdu.length >= offset + 2) {
// Language is two GSM characters.
diff --git a/tests/src/com/android/cellbroadcastservice/tests/GsmSmsCbMessageTest.java b/tests/src/com/android/cellbroadcastservice/tests/GsmSmsCbMessageTest.java
index e1c9308..0b03f4d 100644
--- a/tests/src/com/android/cellbroadcastservice/tests/GsmSmsCbMessageTest.java
+++ b/tests/src/com/android/cellbroadcastservice/tests/GsmSmsCbMessageTest.java
@@ -579,37 +579,28 @@
}
@Test
- public void testGetMessageBody8Bit() {
+ public void testGetMessageBodyGsm8Bit() {
byte[] pdu = {
(byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x44, (byte) 0x11,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,
- (byte) 0x41,
- (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45
+ (byte) 0x41, (byte) 0x20, (byte) 0x47, (byte) 0x53, (byte) 0x4D, (byte) 0x20,
+ (byte) 0x38, (byte) 0x2D, (byte) 0x62, (byte) 0x69, (byte) 0x74, (byte) 0x20,
+ (byte) 0x6D, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x61, (byte) 0x67,
+ (byte) 0x65, (byte) 0x20, (byte) 0x77, (byte) 0x69, (byte) 0x74, (byte) 0x68,
+ (byte) 0x20, (byte) 0x63, (byte) 0x61, (byte) 0x72, (byte) 0x72, (byte) 0x69,
+ (byte) 0x61, (byte) 0x67, (byte) 0x65, (byte) 0x20, (byte) 0x72, (byte) 0x65,
+ (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x20, (byte) 0x70,
+ (byte) 0x61, (byte) 0x64, (byte) 0x64, (byte) 0x69, (byte) 0x6E, (byte) 0x67,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
+ (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D
};
SmsCbMessage msg = createFromPdu(pdu);
- assertEquals("8-bit message body should be empty", "", msg.getMessageBody());
+ assertEquals("Unexpected 8-bit string decoded",
+ "A GSM 8-bit message with carriage return padding", msg.getMessageBody());
}
@Test
@@ -643,7 +634,7 @@
};
SmsCbMessage msg = createFromPdu(pdu);
- assertEquals("Unexpected 7-bit string decoded",
+ assertEquals("Unexpected UCS2 string decoded",
"A UCS2 message containing a \u0434 character", msg.getMessageBody());
}
@@ -673,7 +664,7 @@
};
SmsCbMessage msg = createFromPdu(pdu);
- assertEquals("Unexpected 7-bit string decoded",
+ assertEquals("Unexpected UCS2 decoded",
"A UCS2 message containing a \u0434 character", msg.getMessageBody());
}
@@ -755,7 +746,7 @@
};
SmsCbMessage msg = createFromPdu(pdu);
- assertEquals("Unexpected 7-bit string decoded",
+ assertEquals("Unexpected UCS2 string decoded",
"A UCS2 message containing a \u0434 character", msg.getMessageBody());
assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
@@ -787,7 +778,7 @@
};
SmsCbMessage msg = createFromPdu(pdu);
- assertEquals("Unexpected 7-bit string decoded",
+ assertEquals("Unexpected UCS2 string decoded",
"A UCS2 message containing a \u0434 character", msg.getMessageBody());
assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());