summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTammo Spalink <tammo@google.com>2009-04-24 18:27:47 +0800
committerTammo Spalink <tammo@google.com>2009-04-28 15:49:59 +0800
commit8c49d32cb9980959c402eaa243fd5129cd9942fc (patch)
tree0c89bbec072f45a3bd3828c13a4a37cd3d472ea8
parent17f213bc528cf296e133e9ec9c9e0ce5dce41781 (diff)
downloadframeworks_base-8c49d32cb9980959c402eaa243fd5129cd9942fc.zip
frameworks_base-8c49d32cb9980959c402eaa243fd5129cd9942fc.tar.gz
frameworks_base-8c49d32cb9980959c402eaa243fd5129cd9942fc.tar.bz2
enable additional cdma sms fields and user data encodings
enable ia5 and octet user data encodings properly expose parsed user data support additional bearer data subparameter types
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/SmsMessage.java40
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java339
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/sms/UserData.java27
-rw-r--r--tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java150
4 files changed, 434 insertions, 122 deletions
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 6428e90..677d609 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -40,10 +40,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Random;
-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_UNKNOWN;
import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
@@ -685,41 +681,22 @@ public class SmsMessage extends SmsMessageBase {
}
/**
- * Parses the User Data of an SMS.
+ * Copy parsed user data out from internal datastructures.
*/
private void parseUserData(UserData uData) {
- int encodingType;
-
- if (null == uData) {
+ if (uData == null) {
return;
}
- encodingType = uData.msgEncoding;
-
- // insert DCS-decoding here when type is supported by ril-library
-
userData = uData.payload;
userDataHeader = uData.userDataHeader;
-
- switch (encodingType) {
- case UserData.ENCODING_GSM_7BIT_ALPHABET:
- case UserData.ENCODING_7BIT_ASCII:
- case UserData.ENCODING_UNICODE_16:
- // user data was already decoded by wmsts-library
- messageBody = new String(userData);
- break;
-
- // data and unsupported encodings:
- case UserData.ENCODING_OCTET:
- default:
- messageBody = null;
- break;
- }
-
- if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
+ messageBody = uData.payloadStr;
if (messageBody != null) {
+ if (Config.LOGV) Log.v(LOG_TAG, "SMS message body: '" + messageBody + "'");
parseMessageBody();
+ } else if ((userData != null) && (Config.LOGV)) {
+ Log.v(LOG_TAG, "SMS payload: '" + IccUtils.bytesToHexString(userData) + "'");
}
}
@@ -727,7 +704,7 @@ public class SmsMessage extends SmsMessageBase {
* {@inheritDoc}
*/
public MessageClass getMessageClass() {
- if (BearerData.DISPLAY_IMMEDIATE == mBearerData.displayMode ) {
+ if (BearerData.DISPLAY_MODE_IMMEDIATE == mBearerData.displayMode ) {
return MessageClass.CLASS_0;
} else {
return MessageClass.UNKNOWN;
@@ -780,9 +757,6 @@ public class SmsMessage extends SmsMessageBase {
mBearerData.readAckReq = false;
mBearerData.reportReq = false;
- // Set the display mode (See C.S0015-B, v2.0, 4.5.16)
- mBearerData.displayMode = BearerData.DISPLAY_DEFAULT;
-
// number of messages: not needed for encoding!
// indicate whether a user data header is available
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 8e67387..b5952a1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -46,14 +46,14 @@ public final class BearerData{
//private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE = 0x05;
//private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE = 0x06;
//private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE = 0x07;
- //private final static byte SUBPARAM_PRIORITY_INDICATOR = 0x08;
- //private final static byte SUBPARAM_PRIVACY_INDICATOR = 0x09;
+ private final static byte SUBPARAM_PRIORITY_INDICATOR = 0x08;
+ private final static byte SUBPARAM_PRIVACY_INDICATOR = 0x09;
private final static byte SUBPARAM_REPLY_OPTION = 0x0A;
private final static byte SUBPARAM_NUMBER_OF_MESSAGES = 0x0B;
- //private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY = 0x0C;
- //private final static byte SUBPARAM_LANGUAGE_INDICATOR = 0x0D;
+ private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY = 0x0C;
+ private final static byte SUBPARAM_LANGUAGE_INDICATOR = 0x0D;
private final static byte SUBPARAM_CALLBACK_NUMBER = 0x0E;
- //private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE = 0x0F;
+ private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE = 0x0F;
//private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA = 0x10;
//private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX = 0x11;
//private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA = 0x12;
@@ -63,58 +63,102 @@ public final class BearerData{
//private final static byte SUBPARAM_ENHANCED_VMN = 0x16;
//private final static byte SUBPARAM_ENHANCED_VMN_ACK = 0x17;
- // For completeness the following fields are listed, though not used yet.
+ /**
+ * Supported message types for CDMA SMS messages
+ * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
+ */
+ public static final int MESSAGE_TYPE_DELIVER = 0x01;
+ public static final int MESSAGE_TYPE_SUBMIT = 0x02;
+ public static final int MESSAGE_TYPE_CANCELLATION = 0x03;
+ public static final int MESSAGE_TYPE_DELIVERY_ACK = 0x04;
+ public static final int MESSAGE_TYPE_USER_ACK = 0x05;
+ public static final int MESSAGE_TYPE_READ_ACK = 0x06;
+ public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
+ public static final int MESSAGE_TYPE_SUBMIT_REPORT = 0x08;
+
+ public byte messageType;
+
+ /**
+ * 16-bit value indicating the message ID, which increments modulo 65536.
+ * (Special rules apply for WAP-messages.)
+ * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+ */
+ public int messageId;
+
/**
* Supported priority modes for CDMA SMS messages
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1)
*/
- //public static final int PRIORITY_NORMAL = 0x0;
- //public static final int PRIORITY_INTERACTIVE = 0x1;
- //public static final int PRIORITY_URGENT = 0x2;
- //public static final int PRIORITY_EMERGENCY = 0x3;
+ public static final int PRIORITY_NORMAL = 0x0;
+ public static final int PRIORITY_INTERACTIVE = 0x1;
+ public static final int PRIORITY_URGENT = 0x2;
+ public static final int PRIORITY_EMERGENCY = 0x3;
+
+ public boolean priorityIndicatorSet = false;
+ public byte priority = PRIORITY_NORMAL;
/**
* Supported privacy modes for CDMA SMS messages
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1)
*/
- //public static final int PRIVACY_NOT_RESTRICTED = 0x0;
- //public static final int PRIVACY_RESTRICTED = 0x1;
- //public static final int PRIVACY_CONFIDENTIAL = 0x2;
- //public static final int PRIVACY_SECRET = 0x3;
+ public static final int PRIVACY_NOT_RESTRICTED = 0x0;
+ public static final int PRIVACY_RESTRICTED = 0x1;
+ public static final int PRIVACY_CONFIDENTIAL = 0x2;
+ public static final int PRIVACY_SECRET = 0x3;
+
+ public boolean privacyIndicatorSet = false;
+ public byte privacy = PRIVACY_NOT_RESTRICTED;
/**
- * Supported alert modes for CDMA SMS messages
+ * Supported alert priority modes for CDMA SMS messages
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1)
*/
- //public static final int ALERT_DEFAULT = 0x0;
- //public static final int ALERT_LOW_PRIO = 0x1;
- //public static final int ALERT_MEDIUM_PRIO = 0x2;
- //public static final int ALERT_HIGH_PRIO = 0x3;
+ public static final int ALERT_DEFAULT = 0x0;
+ public static final int ALERT_LOW_PRIO = 0x1;
+ public static final int ALERT_MEDIUM_PRIO = 0x2;
+ public static final int ALERT_HIGH_PRIO = 0x3;
+
+ public boolean alertIndicatorSet = false;
+ public int alert = ALERT_DEFAULT;
/**
- * Supported display modes for CDMA SMS messages
- * (See 3GPP2 C.S0015-B, v2.0, table 4.5.16-1)
+ * Supported display modes for CDMA SMS messages. Display mode is
+ * a 2-bit value used to indicate to the mobile station when to
+ * display the received message. (See 3GPP2 C.S0015-B, v2,
+ * 4.5.16)
*/
- public static final int DISPLAY_IMMEDIATE = 0x0;
- public static final int DISPLAY_DEFAULT = 0x1;
- public static final int DISPLAY_USER = 0x2;
+ public static final int DISPLAY_MODE_IMMEDIATE = 0x0;
+ public static final int DISPLAY_MODE_DEFAULT = 0x1;
+ public static final int DISPLAY_MODE_USER = 0x2;
+
+ public boolean displayModeSet = false;
+ public byte displayMode = DISPLAY_MODE_DEFAULT;
/**
- * Supported message types for CDMA SMS messages
- * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
+ * Language Indicator values. NOTE: the spec (3GPP2 C.S0015-B,
+ * v2, 4.5.14) is ambiguous as to the meaning of this field, as it
+ * refers to C.R1001-D but that reference has been crossed out.
+ * It would seem reasonable to assume the values from C.R1001-F
+ * (table 9.2-1) are to be used instead.
*/
- public static final int MESSAGE_TYPE_DELIVER = 0x01;
- public static final int MESSAGE_TYPE_SUBMIT = 0x02;
- public static final int MESSAGE_TYPE_CANCELLATION = 0x03;
- public static final int MESSAGE_TYPE_DELIVERY_ACK = 0x04;
- public static final int MESSAGE_TYPE_USER_ACK = 0x05;
- public static final int MESSAGE_TYPE_READ_ACK = 0x06;
- public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
- public static final int MESSAGE_TYPE_SUBMIT_REPORT = 0x08;
+ public static final int LANGUAGE_UNKNOWN = 0x00;
+ public static final int LANGUAGE_ENGLISH = 0x01;
+ public static final int LANGUAGE_FRENCH = 0x02;
+ public static final int LANGUAGE_SPANISH = 0x03;
+ public static final int LANGUAGE_JAPANESE = 0x04;
+ public static final int LANGUAGE_KOREAN = 0x05;
+ public static final int LANGUAGE_CHINESE = 0x06;
+ public static final int LANGUAGE_HEBREW = 0x07;
+
+ public boolean languageIndicatorSet = false;
+ public int language = LANGUAGE_UNKNOWN;
/**
- * SMS Message Status Codes
- * (See 3GPP2 C.S0015-B, v2.0, table 4.5.21-1)
+ * SMS Message Status Codes. The first component of the Message
+ * status indicates if an error has occurred and whether the error
+ * is considered permanent or temporary. The second component of
+ * the Message status indicates the cause of the error (if any).
+ * (See 3GPP2 C.S0015-B, v2.0, 4.5.21)
*/
/* no-error codes */
public static final int ERROR_NONE = 0x00;
@@ -139,19 +183,9 @@ public final class BearerData{
public static final int ERROR_UNDEFINED = 0xFF;
public static final int STATUS_UNDEFINED = 0xFF;
- /**
- * 4-bit value indicating the message type in accordance to
- * table 4.5.1-1
- * (See 3GPP2 C.S0015-B, v2, 4.5.1)
- */
- public byte messageType;
-
- /**
- * 16-bit value indicating the message ID, which increments modulo 65536.
- * (Special rules apply for WAP-messages.)
- * (See 3GPP2 C.S0015-B, v2, 4.5.1)
- */
- public int messageId;
+ public boolean messageStatusSet = false;
+ public int errorClass = ERROR_UNDEFINED;
+ public int messageStatus = STATUS_UNDEFINED;
/**
* 1-bit value that indicates whether a User Data Header is present.
@@ -178,8 +212,6 @@ public final class BearerData{
//public SmsRelTime validityPeriodRelative;
//public SmsTime deferredDeliveryTimeAbsolute;
//public SmsRelTime deferredDeliveryTimeRelative;
- //public byte priority;
- //public byte privacy;
/**
* Reply Option
@@ -199,9 +231,6 @@ public final class BearerData{
*/
public int numberOfMessages;
- //public int alert;
- //public int language;
-
/**
* 4-bit or 8-bit value that indicates the number to be dialed in reply to a
* received SMS message.
@@ -209,27 +238,6 @@ public final class BearerData{
*/
public CdmaSmsAddress callbackNumber;
- /**
- * 2-bit value that is used to indicate to the mobile station when to display
- * the received message.
- * (See 3GPP2 C.S0015-B, v2, 4.5.16)
- */
- public byte displayMode = DISPLAY_DEFAULT;
-
- /**
- * First component of the Message status, that indicates if an error has occurred
- * and whether the error is considered permanent or temporary.
- * (See 3GPP2 C.S0015-B, v2, 4.5.21)
- */
- public int errorClass = ERROR_UNDEFINED;
-
- /**
- * Second component of the Message status, that indicates if an error has occurred
- * and the cause of the error.
- * (See 3GPP2 C.S0015-B, v2, 4.5.21)
- */
- public int messageStatus = STATUS_UNDEFINED;
-
private static class CodingException extends Exception {
public CodingException(String s) {
super(s);
@@ -242,6 +250,13 @@ public final class BearerData{
builder.append("BearerData:\n");
builder.append(" messageType: " + messageType + "\n");
builder.append(" messageId: " + (int)messageId + "\n");
+ builder.append(" priority: " + (priorityIndicatorSet ? priority : "not set") + "\n");
+ builder.append(" privacy: " + (privacyIndicatorSet ? privacy : "not set") + "\n");
+ builder.append(" alert: " + (alertIndicatorSet ? alert : "not set") + "\n");
+ builder.append(" displayMode: " + (displayModeSet ? displayMode : "not set") + "\n");
+ builder.append(" language: " + (languageIndicatorSet ? language : "not set") + "\n");
+ builder.append(" errorClass: " + (messageStatusSet ? errorClass : "not set") + "\n");
+ builder.append(" messageStatus: " + (messageStatusSet ? messageStatus : "not set") + "\n");
builder.append(" hasUserDataHeader: " + hasUserDataHeader + "\n");
builder.append(" timeStamp: " + timeStamp + "\n");
builder.append(" userAckReq: " + userAckReq + "\n");
@@ -250,9 +265,6 @@ public final class BearerData{
builder.append(" reportReq: " + reportReq + "\n");
builder.append(" numberOfMessages: " + numberOfMessages + "\n");
builder.append(" callbackNumber: " + callbackNumber + "\n");
- builder.append(" displayMode: " + displayMode + "\n");
- builder.append(" errorClass: " + errorClass + "\n");
- builder.append(" messageStatus: " + messageStatus + "\n");
builder.append(" userData: " + userData + "\n");
return builder.toString();
}
@@ -387,6 +399,45 @@ public final class BearerData{
outStream.writeByteArray(6 * 8, bData.timeStamp);
}
+ private static void encodePrivacyIndicator(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException
+ {
+ outStream.write(8, 1);
+ outStream.write(2, bData.privacy);
+ outStream.skip(6);
+ }
+
+ private static void encodeLanguageIndicator(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException
+ {
+ outStream.write(8, 1);
+ outStream.write(8, bData.language);
+ }
+
+ private static void encodeDisplayMode(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException
+ {
+ outStream.write(8, 1);
+ outStream.write(2, bData.displayMode);
+ outStream.skip(6);
+ }
+
+ private static void encodePriorityIndicator(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException
+ {
+ outStream.write(8, 1);
+ outStream.write(2, bData.priority);
+ outStream.skip(6);
+ }
+
+ private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException
+ {
+ outStream.write(8, 1);
+ outStream.write(2, bData.alert);
+ outStream.skip(6);
+ }
+
/**
* Create serialized representation for BearerData object.
* (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
@@ -420,6 +471,30 @@ public final class BearerData{
outStream.write(8, SUBPARAM_MESSAGE_CENTER_TIME_STAMP);
encodeMsgCenterTimeStamp(bData, outStream);
}
+ if (bData.privacyIndicatorSet) {
+ outStream.write(8, SUBPARAM_PRIVACY_INDICATOR);
+ encodePrivacyIndicator(bData, outStream);
+ }
+ if (bData.languageIndicatorSet) {
+ outStream.write(8, SUBPARAM_LANGUAGE_INDICATOR);
+ encodeLanguageIndicator(bData, outStream);
+ }
+ if (bData.displayModeSet) {
+ outStream.write(8, SUBPARAM_MESSAGE_DISPLAY_MODE);
+ encodeDisplayMode(bData, outStream);
+ }
+ if (bData.priorityIndicatorSet) {
+ outStream.write(8, SUBPARAM_PRIORITY_INDICATOR);
+ encodePriorityIndicator(bData, outStream);
+ }
+ if (bData.alertIndicatorSet) {
+ outStream.write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY);
+ encodeMsgDeliveryAlert(bData, outStream);
+ }
+ if (bData.messageStatusSet) {
+ outStream.write(8, SUBPARAM_MESSAGE_STATUS);
+ encodeMsgStatus(bData, outStream);
+ }
return outStream.toByteArray();
} catch (BitwiseOutputStream.AccessException ex) {
Log.e(LOG_TAG, "BearerData encode failed: " + ex);
@@ -471,6 +546,33 @@ public final class BearerData{
}
}
+ private static String decodeIa5(byte[] data, int offset, int numFields) {
+ try {
+ StringBuffer strBuf = new StringBuffer(numFields);
+ BitwiseInputStream inStream = new BitwiseInputStream(data);
+ inStream.skip(offset);
+ int wantedBits = numFields * 7;
+ if (inStream.available() < wantedBits) {
+ throw new CodingException("insufficient data (wanted " + wantedBits +
+ " bits, but only have " + inStream.available() + ")");
+ }
+ for (int i = 0; i < numFields; i++) {
+ int charCode = inStream.read(7);
+ if ((charCode < UserData.IA5_MAP_BASE_INDEX) ||
+ (charCode > UserData.IA5_MAP_MAX_INDEX)) {
+ throw new CodingException("unsupported AI5 character code (" + charCode + ")");
+ }
+ strBuf.append(UserData.IA5_MAP[charCode - UserData.IA5_MAP_BASE_INDEX]);
+ }
+ return strBuf.toString();
+ } catch (BitwiseInputStream.AccessException ex) {
+ Log.e(LOG_TAG, "UserData AI5 decode failed: " + ex);
+ } catch (CodingException ex) {
+ Log.e(LOG_TAG, "UserData AI5 decode failed: " + ex);
+ }
+ return null;
+ }
+
private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
throws CodingException
{
@@ -482,18 +584,23 @@ public final class BearerData{
userData.userDataHeader = SmsHeader.parse(headerData);
}
switch (userData.msgEncoding) {
- case UserData.ENCODING_GSM_7BIT_ALPHABET:
- userData.payloadStr = GsmAlphabet.gsm7BitPackedToString(userData.payload,
- offset, userData.numFields);
+ case UserData.ENCODING_OCTET:
break;
case UserData.ENCODING_7BIT_ASCII:
userData.payloadStr = decodePayloadStr(userData.payload, offset,
userData.numFields, "US-ASCII");
break;
+ case UserData.ENCODING_IA5:
+ userData.payloadStr = decodeIa5(userData.payload, offset, userData.numFields);
+ break;
case UserData.ENCODING_UNICODE_16:
userData.payloadStr = decodePayloadStr(userData.payload, offset,
userData.numFields * 2, "UTF-16");
break;
+ case UserData.ENCODING_GSM_7BIT_ALPHABET:
+ userData.payloadStr = GsmAlphabet.gsm7BitPackedToString(userData.payload,
+ offset, userData.numFields);
+ break;
default:
throw new CodingException("unsupported user data encoding ("
+ userData.msgEncoding + ")");
@@ -592,6 +699,7 @@ public final class BearerData{
}
bData.errorClass = inStream.read(2);
bData.messageStatus = inStream.read(6);
+ bData.messageStatusSet = true;
}
private static void decodeMsgCenterTimeStamp(BearerData bData,
@@ -604,6 +712,60 @@ public final class BearerData{
bData.timeStamp = inStream.readByteArray(6 * 8);
}
+ private static void decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
+ throws BitwiseInputStream.AccessException, CodingException
+ {
+ if (inStream.read(8) != 1) {
+ throw new CodingException("PRIVACY_INDICATOR subparam size incorrect");
+ }
+ bData.privacy = inStream.read(2);
+ inStream.skip(6);
+ bData.privacyIndicatorSet = true;
+ }
+
+ private static void decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
+ throws BitwiseInputStream.AccessException, CodingException
+ {
+ if (inStream.read(8) != 1) {
+ throw new CodingException("LANGUAGE_INDICATOR subparam size incorrect");
+ }
+ bData.language = inStream.read(8);
+ bData.languageIndicatorSet = true;
+ }
+
+ private static void decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
+ throws BitwiseInputStream.AccessException, CodingException
+ {
+ if (inStream.read(8) != 1) {
+ throw new CodingException("DISPLAY_MODE subparam size incorrect");
+ }
+ bData.displayMode = inStream.read(2);
+ inStream.skip(6);
+ bData.displayModeSet = true;
+ }
+
+ private static void decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
+ throws BitwiseInputStream.AccessException, CodingException
+ {
+ if (inStream.read(8) != 1) {
+ throw new CodingException("PRIORITY_INDICATOR subparam size incorrect");
+ }
+ bData.priority = inStream.read(2);
+ inStream.skip(6);
+ bData.priorityIndicatorSet = true;
+ }
+
+ private static void decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
+ throws BitwiseInputStream.AccessException, CodingException
+ {
+ if (inStream.read(8) != 1) {
+ throw new CodingException("ALERT_ON_MESSAGE_DELIVERY subparam size incorrect");
+ }
+ bData.alert = inStream.read(2);
+ inStream.skip(6);
+ bData.alertIndicatorSet = true;
+ }
+
/**
* Create BearerData object from serialized representation.
* (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
@@ -647,6 +809,21 @@ public final class BearerData{
case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
decodeMsgCenterTimeStamp(bData, inStream);
break;
+ case SUBPARAM_PRIVACY_INDICATOR:
+ decodePrivacyIndicator(bData, inStream);
+ break;
+ case SUBPARAM_LANGUAGE_INDICATOR:
+ decodeLanguageIndicator(bData, inStream);
+ break;
+ case SUBPARAM_MESSAGE_DISPLAY_MODE:
+ decodeDisplayMode(bData, inStream);
+ break;
+ case SUBPARAM_PRIORITY_INDICATOR:
+ decodePriorityIndicator(bData, inStream);
+ break;
+ case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
+ decodeMsgDeliveryAlert(bData, inStream);
+ break;
default:
throw new CodingException("unsupported bearer data subparameter ("
+ subparamId + ")");
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index bd6fbb4..f916089 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -22,13 +22,13 @@ import com.android.internal.util.HexDump;
public class UserData{
/**
- * User data encoding types
+ * User data encoding types.
* (See 3GPP2 C.R1001-F, v1.0, table 9.1-1)
*/
public static final int ENCODING_OCTET = 0x00;
public static final int ENCODING_IS91_EXTENDED_PROTOCOL = 0x01;
public static final int ENCODING_7BIT_ASCII = 0x02;
- //public static final int ENCODING_IA5 = 0x03;
+ public static final int ENCODING_IA5 = 0x03;
public static final int ENCODING_UNICODE_16 = 0x04;
//public static final int ENCODING_SHIFT_JIS = 0x05;
//public static final int ENCODING_KOREAN = 0x06;
@@ -38,6 +38,25 @@ public class UserData{
public static final int ENCODING_GSM_DCS = 0x0A;
/**
+ * IA5 data encoding character mappings.
+ * (See CCITT Rec. T.50 Tables 1 and 3)
+ */
+ public static final char[] IA5_MAP = {
+ ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'};
+
+ /**
+ * Mapping for IA5 values less than 32 are flow control signals
+ * and not used here.
+ */
+ public static final int IA5_MAP_BASE_INDEX = 0x20;
+ public static final int IA5_MAP_MAX_INDEX = IA5_MAP_BASE_INDEX + IA5_MAP.length - 1;
+
+ /**
* Contains the data header of the user data
*/
public SmsHeader userDataHeader;
@@ -73,8 +92,8 @@ public class UserData{
builder.append(" paddingBits: " + paddingBits + "\n");
builder.append(" numFields: " + (int)numFields + "\n");
builder.append(" userDataHeader: " + userDataHeader + "\n");
- builder.append(" payload: " + HexDump.toHexString(payload));
- builder.append(" payloadStr: " + payloadStr);
+ builder.append(" payload: '" + HexDump.toHexString(payload) + "'");
+ builder.append(", payloadStr: '" + payloadStr + "'");
return builder.toString();
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index 723512c..9ff80c7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -264,10 +264,152 @@ public class CdmaSmsTest extends AndroidTestCase {
HexDump.toHexString(revBearerData.timeStamp));
}
- // XXX test messageId
+ @SmallTest
+ public void testPrivacyIndicator() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b840090140";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.privacy, BearerData.PRIVACY_RESTRICTED);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b840090180";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400901c0";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.privacy, BearerData.PRIVACY_SECRET);
+ }
+
+ @SmallTest
+ public void testPrivacyIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ String payloadStr = "test privacy indicator";
+ bearerData.userData = makeUserData(payloadStr);
+ bearerData.privacy = BearerData.PRIVACY_SECRET;
+ bearerData.privacyIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.privacyIndicatorSet, true);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_SECRET);
+ bearerData.privacy = BearerData.PRIVACY_RESTRICTED;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_RESTRICTED);
+ }
- // String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100"; sid 12
- // String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101"; sid 13
- // Log.d(LOG_TAG, "revBearerData -- " + revBearerData);
+ @SmallTest
+ public void testMsgDeliveryAlert() throws Exception {
+ String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.alert, 0);
+ assertEquals(bd1.userData.payloadStr, "Test Alert 0");
+ String pdu2 = "0003104090010d4866a794e07055965b91d140300c0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.alert, 1);
+ assertEquals(bd2.userData.payloadStr, "Test Alert 1");
+ String pdu3 = "0003104090010d4866a794e07055965b91d240300c0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.alert, 2);
+ assertEquals(bd3.userData.payloadStr, "Test Alert 2");
+ String pdu4 = "0003104090010d4866a794e07055965b91d340300c01c0";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.alert, 3);
+ assertEquals(bd4.userData.payloadStr, "Test Alert 3");
+ }
+
+ @SmallTest
+ public void testMsgDeliveryAlertFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ String payloadStr = "test message delivery alert";
+ bearerData.userData = makeUserData(payloadStr);
+ bearerData.alert = BearerData.ALERT_MEDIUM_PRIO;
+ bearerData.alertIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ bearerData.alert = BearerData.ALERT_HIGH_PRIO;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ }
+ @SmallTest
+ public void testLanguageIndicator() throws Exception {
+ String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd1.language, BearerData.LANGUAGE_ENGLISH);
+ String pdu2 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0106";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd2.language, BearerData.LANGUAGE_CHINESE);
+ }
+
+ @SmallTest
+ public void testLanguageIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ String payloadStr = "test language indicator";
+ bearerData.userData = makeUserData(payloadStr);
+ bearerData.language = BearerData.LANGUAGE_ENGLISH;
+ bearerData.languageIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ bearerData.language = BearerData.LANGUAGE_KOREAN;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ }
+
+ @SmallTest
+ public void testDisplayMode() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ //Log.d(LOG_TAG, "bd1 = " + bd1);
+ assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.displayMode, BearerData.DISPLAY_MODE_DEFAULT);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400f0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.displayMode, BearerData.DISPLAY_MODE_USER);
+ }
+
+ @SmallTest
+ public void testDisplayModeFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ String payloadStr = "test display mode";
+ bearerData.userData = makeUserData(payloadStr);
+ bearerData.displayMode = BearerData.DISPLAY_MODE_IMMEDIATE;
+ bearerData.displayModeSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ bearerData.displayMode = BearerData.DISPLAY_MODE_USER;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ }
}