am d306052
: Merge change 542 into donut
Merge commit 'd30605200b8b0f10e4740a9d7266d240023e69cd' * commit 'd30605200b8b0f10e4740a9d7266d240023e69cd': enable additional cdma sms fields and user data encodings
This commit is contained in:
committed by
The Android Open Source Project
commit
c36349034a
@ -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
|
||||
|
@ -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,42 +63,6 @@ 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 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Supported alert 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;
|
||||
|
||||
/**
|
||||
* Supported display modes for CDMA SMS messages
|
||||
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.16-1)
|
||||
*/
|
||||
public static final int DISPLAY_IMMEDIATE = 0x0;
|
||||
public static final int DISPLAY_DEFAULT = 0x1;
|
||||
public static final int DISPLAY_USER = 0x2;
|
||||
|
||||
/**
|
||||
* Supported message types for CDMA SMS messages
|
||||
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
|
||||
@ -112,9 +76,89 @@ public final class BearerData{
|
||||
public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
|
||||
public static final int MESSAGE_TYPE_SUBMIT_REPORT = 0x08;
|
||||
|
||||
public byte messageType;
|
||||
|
||||
/**
|
||||
* SMS Message Status Codes
|
||||
* (See 3GPP2 C.S0015-B, v2.0, table 4.5.21-1)
|
||||
* 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 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 boolean privacyIndicatorSet = false;
|
||||
public byte privacy = PRIVACY_NOT_RESTRICTED;
|
||||
|
||||
/**
|
||||
* 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 boolean alertIndicatorSet = false;
|
||||
public int alert = ALERT_DEFAULT;
|
||||
|
||||
/**
|
||||
* 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_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;
|
||||
|
||||
/**
|
||||
* 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 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. 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 + ")");
|
||||
|
@ -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;
|
||||
@ -37,6 +37,25 @@ public class UserData{
|
||||
public static final int ENCODING_GSM_7BIT_ALPHABET = 0x09;
|
||||
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
|
||||
*/
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100"; sid 12
|
||||
// String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101"; sid 13
|
||||
// Log.d(LOG_TAG, "revBearerData -- " + revBearerData);
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user