BearerDatapublic final class BearerData extends Object An object to encode and decode CDMA SMS bearer data. |
Fields Summary |
---|
private static final String | LOG_TAG | private static final byte | SUBPARAM_MESSAGE_IDENTIFIERBearer Data Subparameter Identifiers
(See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
NOTE: Commented subparameter types are not implemented. | private static final byte | SUBPARAM_USER_DATA | private static final byte | SUBPARAM_USER_RESPONSE_CODE | private static final byte | SUBPARAM_MESSAGE_CENTER_TIME_STAMP | private static final byte | SUBPARAM_VALIDITY_PERIOD_ABSOLUTE | private static final byte | SUBPARAM_VALIDITY_PERIOD_RELATIVE | private static final byte | SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE | private static final byte | SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE | private static final byte | SUBPARAM_PRIORITY_INDICATOR | private static final byte | SUBPARAM_PRIVACY_INDICATOR | private static final byte | SUBPARAM_REPLY_OPTION | private static final byte | SUBPARAM_NUMBER_OF_MESSAGES | private static final byte | SUBPARAM_ALERT_ON_MESSAGE_DELIVERY | private static final byte | SUBPARAM_LANGUAGE_INDICATOR | private static final byte | SUBPARAM_CALLBACK_NUMBER | private static final byte | SUBPARAM_MESSAGE_DISPLAY_MODE | private static final byte | SUBPARAM_MESSAGE_DEPOSIT_INDEX | private static final byte | SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA | private static final byte | SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS | private static final byte | SUBPARAM_MESSAGE_STATUS | private static final byte | SUBPARAM_ID_LAST_DEFINED | public static final int | MESSAGE_TYPE_DELIVERSupported message types for CDMA SMS messages
(See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1) | public static final int | MESSAGE_TYPE_SUBMIT | public static final int | MESSAGE_TYPE_CANCELLATION | public static final int | MESSAGE_TYPE_DELIVERY_ACK | public static final int | MESSAGE_TYPE_USER_ACK | public static final int | MESSAGE_TYPE_READ_ACK | public static final int | MESSAGE_TYPE_DELIVER_REPORT | public static final int | MESSAGE_TYPE_SUBMIT_REPORT | public int | messageType | public int | messageId16-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 static final int | PRIORITY_NORMALSupported priority modes for CDMA SMS messages
(See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1) | public static final int | PRIORITY_INTERACTIVE | public static final int | PRIORITY_URGENT | public static final int | PRIORITY_EMERGENCY | public boolean | priorityIndicatorSet | public int | priority | public static final int | PRIVACY_NOT_RESTRICTEDSupported privacy modes for CDMA SMS messages
(See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1) | public static final int | PRIVACY_RESTRICTED | public static final int | PRIVACY_CONFIDENTIAL | public static final int | PRIVACY_SECRET | public boolean | privacyIndicatorSet | public int | privacy | public static final int | ALERT_DEFAULTSupported alert priority modes for CDMA SMS messages
(See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1) | public static final int | ALERT_LOW_PRIO | public static final int | ALERT_MEDIUM_PRIO | public static final int | ALERT_HIGH_PRIO | public boolean | alertIndicatorSet | public int | alert | public static final int | DISPLAY_MODE_IMMEDIATESupported 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_DEFAULT | public static final int | DISPLAY_MODE_USER | public boolean | displayModeSet | public int | displayMode | public static final int | LANGUAGE_UNKNOWNLanguage 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_ENGLISH | public static final int | LANGUAGE_FRENCH | public static final int | LANGUAGE_SPANISH | public static final int | LANGUAGE_JAPANESE | public static final int | LANGUAGE_KOREAN | public static final int | LANGUAGE_CHINESE | public static final int | LANGUAGE_HEBREW | public boolean | languageIndicatorSet | public int | language | public static final int | ERROR_NONESMS 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) | public static final int | STATUS_ACCEPTED | public static final int | STATUS_DEPOSITED_TO_INTERNET | public static final int | STATUS_DELIVERED | public static final int | STATUS_CANCELLED | public static final int | ERROR_TEMPORARY | public static final int | STATUS_NETWORK_CONGESTION | public static final int | STATUS_NETWORK_ERROR | public static final int | STATUS_UNKNOWN_ERROR | public static final int | ERROR_PERMANENT | public static final int | STATUS_CANCEL_FAILED | public static final int | STATUS_BLOCKED_DESTINATION | public static final int | STATUS_TEXT_TOO_LONG | public static final int | STATUS_DUPLICATE_MESSAGE | public static final int | STATUS_INVALID_DESTINATION | public static final int | STATUS_MESSAGE_EXPIRED | public static final int | ERROR_UNDEFINED | public static final int | STATUS_UNDEFINED | public boolean | messageStatusSet | public int | errorClass | public int | messageStatus | public boolean | hasUserDataHeader1-bit value that indicates whether a User Data Header (UDH) is present.
(See 3GPP2 C.S0015-B, v2, 4.5.1)
NOTE: during encoding, this value will be set based on the
presence of a UDH in the structured data, any existing setting
will be overwritten. | public UserData | userDataprovides the information for the user data
(e.g. padding bits, user data, user data header, etc)
(See 3GPP2 C.S.0015-B, v2, 4.5.2) | public boolean | userResponseCodeSetThe User Response Code subparameter is used in the SMS User
Acknowledgment Message to respond to previously received short
messages. This message center-specific element carries the
identifier of a predefined response. (See 3GPP2 C.S.0015-B, v2,
4.5.3) | public int | userResponseCode | public TimeStamp | msgCenterTimeStamp | public TimeStamp | validityPeriodAbsolute | public TimeStamp | deferredDeliveryTimeAbsolute | public static final int | RELATIVE_TIME_MINS_LIMITRelative time is specified as one byte, the value of which
falls into a series of ranges, as specified below. The idea is
that shorter time intervals allow greater precision -- the
value means minutes from zero until the MINS_LIMIT (inclusive),
upon which it means hours until the HOURS_LIMIT, and so
forth. (See 3GPP2 C.S0015-B, v2, 4.5.6-1) | public static final int | RELATIVE_TIME_HOURS_LIMIT | public static final int | RELATIVE_TIME_DAYS_LIMIT | public static final int | RELATIVE_TIME_WEEKS_LIMIT | public static final int | RELATIVE_TIME_INDEFINITE | public static final int | RELATIVE_TIME_NOW | public static final int | RELATIVE_TIME_MOBILE_INACTIVE | public static final int | RELATIVE_TIME_RESERVED | public boolean | validityPeriodRelativeSet | public int | validityPeriodRelative | public boolean | deferredDeliveryTimeRelativeSet | public int | deferredDeliveryTimeRelative | public boolean | userAckReqThe Reply Option subparameter contains 1-bit values which
indicate whether SMS acknowledgment is requested or not. (See
3GPP2 C.S0015-B, v2, 4.5.11) | public boolean | deliveryAckReq | public boolean | readAckReq | public boolean | reportReq | public int | numberOfMessagesThe Number of Messages subparameter (8-bit value) is a decimal
number in the 0 to 99 range representing the number of messages
stored at the Voice Mail System. This element is used by the
Voice Mail Notification service. (See 3GPP2 C.S0015-B, v2,
4.5.12) | public int | depositIndexThe Message Deposit Index subparameter is assigned by the
message center as a unique index to the contents of the User
Data subparameter in each message sent to a particular mobile
station. The mobile station, when replying to a previously
received short message which included a Message Deposit Index
subparameter, may include the Message Deposit Index of the
received message to indicate to the message center that the
original contents of the message are to be included in the
reply. (See 3GPP2 C.S0015-B, v2, 4.5.18) | public CdmaSmsAddress | callbackNumber4-bit or 8-bit value that indicates the number to be dialed in reply to a
received SMS message.
(See 3GPP2 C.S0015-B, v2, 4.5.15) | public android.telephony.SmsCbCmasInfo | cmasWarningInfoCMAS warning notification information. | public ArrayList | serviceCategoryProgramDataThe Service Category Program Data subparameter is used to enable and disable
SMS broadcast service categories to display. If this subparameter is present,
this field will contain a list of one or more
{@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the
operation(s) to perform. | public ArrayList | serviceCategoryProgramResultsThe Service Category Program Results subparameter informs the message center
of the results of a Service Category Program Data request. |
Methods Summary |
---|
public static com.android.internal.telephony.GsmAlphabet.TextEncodingDetails | calcTextEncodingDetails(java.lang.CharSequence msg, boolean force7BitEncoding, boolean isEntireMsg)Calculate the message text encoding length, fragmentation, and other details.
TextEncodingDetails ted;
int septets = countAsciiSeptets(msg, force7BitEncoding);
if (septets != -1 && septets <= SmsConstants.MAX_USER_DATA_SEPTETS) {
ted = new TextEncodingDetails();
ted.msgCount = 1;
ted.codeUnitCount = septets;
ted.codeUnitsRemaining = SmsConstants.MAX_USER_DATA_SEPTETS - septets;
ted.codeUnitSize = SmsConstants.ENCODING_7BIT;
} else {
ted = com.android.internal.telephony.gsm.SmsMessage.calculateLength(
msg, force7BitEncoding);
if (ted.msgCount == 1 && ted.codeUnitSize == SmsConstants.ENCODING_7BIT &&
isEntireMsg) {
// We don't support single-segment EMS, so calculate for 16-bit
// TODO: Consider supporting single-segment EMS
ted.codeUnitCount = msg.length();
int octets = ted.codeUnitCount * 2;
if (octets > SmsConstants.MAX_USER_DATA_BYTES) {
// If EMS is not supported, break down EMS into single segment SMS
// and add page info " x/y".
// In the case of UCS2 encoding type, we need 8 bytes for this
// but we only have 6 bytes from UDH, so truncate the limit for
// each segment by 2 bytes (1 char).
int max_user_data_bytes_with_header =
SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
if (!android.telephony.SmsMessage.hasEmsSupport()) {
// make sure total number of segments is less than 10
if (octets <= 9 * (max_user_data_bytes_with_header - 2))
max_user_data_bytes_with_header -= 2;
}
ted.msgCount = (octets + (max_user_data_bytes_with_header - 1)) /
max_user_data_bytes_with_header;
ted.codeUnitsRemaining = ((ted.msgCount *
max_user_data_bytes_with_header) - octets) / 2;
} else {
ted.msgCount = 1;
ted.codeUnitsRemaining = (SmsConstants.MAX_USER_DATA_BYTES - octets)/2;
}
ted.codeUnitSize = SmsConstants.ENCODING_16BIT;
}
}
return ted;
| private static int | countAsciiSeptets(java.lang.CharSequence msg, boolean force)
int msgLen = msg.length();
if (force) return msgLen;
for (int i = 0; i < msgLen; i++) {
if (UserData.charToAscii.get(msg.charAt(i), -1) == -1) {
return -1;
}
}
return msgLen;
| public static com.android.internal.telephony.cdma.sms.BearerData | decode(byte[] smsData)Create BearerData object from serialized representation.
(See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
return decode(smsData, 0);
| public static com.android.internal.telephony.cdma.sms.BearerData | decode(byte[] smsData, int serviceCategory)Create BearerData object from serialized representation.
(See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
try {
BitwiseInputStream inStream = new BitwiseInputStream(smsData);
BearerData bData = new BearerData();
int foundSubparamMask = 0;
while (inStream.available() > 0) {
int subparamId = inStream.read(8);
int subparamIdBit = 1 << subparamId;
// int is 4 bytes. This duplicate check has a limit to Id number up to 32 (4*8)
// as 32th bit is the max bit in int.
// Per 3GPP2 C.S0015-B Table 4.5-1 Bearer Data Subparameter Identifiers:
// last defined subparam ID is 23 (00010111 = 0x17 = 23).
// Only do duplicate subparam ID check if subparam is within defined value as
// reserved subparams are just skipped.
if ((foundSubparamMask & subparamIdBit) != 0 &&
(subparamId >= SUBPARAM_MESSAGE_IDENTIFIER &&
subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
throw new CodingException("illegal duplicate subparameter (" +
subparamId + ")");
}
boolean decodeSuccess;
switch (subparamId) {
case SUBPARAM_MESSAGE_IDENTIFIER:
decodeSuccess = decodeMessageId(bData, inStream);
break;
case SUBPARAM_USER_DATA:
decodeSuccess = decodeUserData(bData, inStream);
break;
case SUBPARAM_USER_RESPONSE_CODE:
decodeSuccess = decodeUserResponseCode(bData, inStream);
break;
case SUBPARAM_REPLY_OPTION:
decodeSuccess = decodeReplyOption(bData, inStream);
break;
case SUBPARAM_NUMBER_OF_MESSAGES:
decodeSuccess = decodeMsgCount(bData, inStream);
break;
case SUBPARAM_CALLBACK_NUMBER:
decodeSuccess = decodeCallbackNumber(bData, inStream);
break;
case SUBPARAM_MESSAGE_STATUS:
decodeSuccess = decodeMsgStatus(bData, inStream);
break;
case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream);
break;
case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE:
decodeSuccess = decodeValidityAbs(bData, inStream);
break;
case SUBPARAM_VALIDITY_PERIOD_RELATIVE:
decodeSuccess = decodeValidityRel(bData, inStream);
break;
case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE:
decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream);
break;
case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE:
decodeSuccess = decodeDeferredDeliveryRel(bData, inStream);
break;
case SUBPARAM_PRIVACY_INDICATOR:
decodeSuccess = decodePrivacyIndicator(bData, inStream);
break;
case SUBPARAM_LANGUAGE_INDICATOR:
decodeSuccess = decodeLanguageIndicator(bData, inStream);
break;
case SUBPARAM_MESSAGE_DISPLAY_MODE:
decodeSuccess = decodeDisplayMode(bData, inStream);
break;
case SUBPARAM_PRIORITY_INDICATOR:
decodeSuccess = decodePriorityIndicator(bData, inStream);
break;
case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
decodeSuccess = decodeMsgDeliveryAlert(bData, inStream);
break;
case SUBPARAM_MESSAGE_DEPOSIT_INDEX:
decodeSuccess = decodeDepositIndex(bData, inStream);
break;
case SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA:
decodeSuccess = decodeServiceCategoryProgramData(bData, inStream);
break;
default:
decodeSuccess = decodeReserved(bData, inStream, subparamId);
}
if (decodeSuccess &&
(subparamId >= SUBPARAM_MESSAGE_IDENTIFIER &&
subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
foundSubparamMask |= subparamIdBit;
}
}
if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
}
if (bData.userData != null) {
if (isCmasAlertCategory(serviceCategory)) {
decodeCmasUserData(bData, serviceCategory);
} else if (bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) {
if ((foundSubparamMask ^
(1 << SUBPARAM_MESSAGE_IDENTIFIER) ^
(1 << SUBPARAM_USER_DATA))
!= 0) {
Rlog.e(LOG_TAG, "IS-91 must occur without extra subparams (" +
foundSubparamMask + ")");
}
decodeIs91(bData);
} else {
decodeUserDataPayload(bData.userData, bData.hasUserDataHeader);
}
}
return bData;
} catch (BitwiseInputStream.AccessException ex) {
Rlog.e(LOG_TAG, "BearerData decode failed: " + ex);
} catch (CodingException ex) {
Rlog.e(LOG_TAG, "BearerData decode failed: " + ex);
}
return null;
| private static java.lang.String | decode7bitAscii(byte[] data, int offset, int numFields)
try {
offset *= 8;
StringBuffer strBuf = new StringBuffer(numFields);
BitwiseInputStream inStream = new BitwiseInputStream(data);
int wantedBits = (offset * 8) + (numFields * 7);
if (inStream.available() < wantedBits) {
throw new CodingException("insufficient data (wanted " + wantedBits +
" bits, but only have " + inStream.available() + ")");
}
inStream.skip(offset);
for (int i = 0; i < numFields; i++) {
int charCode = inStream.read(7);
if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) &&
(charCode <= UserData.ASCII_MAP_MAX_INDEX)) {
strBuf.append(UserData.ASCII_MAP[charCode - UserData.ASCII_MAP_BASE_INDEX]);
} else if (charCode == UserData.ASCII_NL_INDEX) {
strBuf.append('\n");
} else if (charCode == UserData.ASCII_CR_INDEX) {
strBuf.append('\r");
} else {
/* For other charCodes, they are unprintable, and so simply use SPACE. */
strBuf.append(' ");
}
}
return strBuf.toString();
} catch (BitwiseInputStream.AccessException ex) {
throw new CodingException("7bit ASCII decode failed: " + ex);
}
| private static java.lang.String | decode7bitGsm(byte[] data, int offset, int numFields)
// Start reading from the next 7-bit aligned boundary after offset.
int offsetBits = offset * 8;
int offsetSeptets = (offsetBits + 6) / 7;
numFields -= offsetSeptets;
int paddingBits = (offsetSeptets * 7) - offsetBits;
String result = GsmAlphabet.gsm7BitPackedToString(data, offset, numFields, paddingBits,
0, 0);
if (result == null) {
throw new CodingException("7bit GSM decoding failed");
}
return result;
| private static boolean | decodeCallbackNumber(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8; //at least
int paramBits = inStream.read(8) * 8;
if (paramBits < EXPECTED_PARAM_SIZE) {
inStream.skip(paramBits);
return false;
}
CdmaSmsAddress addr = new CdmaSmsAddress();
addr.digitMode = inStream.read(1);
byte fieldBits = 4;
byte consumedBits = 1;
if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
addr.ton = inStream.read(3);
addr.numberPlan = inStream.read(4);
fieldBits = 8;
consumedBits += 7;
}
addr.numberOfDigits = inStream.read(8);
consumedBits += 8;
int remainingBits = paramBits - consumedBits;
int dataBits = addr.numberOfDigits * fieldBits;
int paddingBits = remainingBits - dataBits;
if (remainingBits < dataBits) {
throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" +
"remainingBits + " + remainingBits + ", dataBits + " +
dataBits + ", paddingBits + " + paddingBits + ")");
}
addr.origBytes = inStream.readByteArray(dataBits);
inStream.skip(paddingBits);
decodeSmsAddress(addr);
bData.callbackNumber = addr;
return true;
| private static java.lang.String | decodeCharset(byte[] data, int offset, int numFields, int width, java.lang.String charset)
if (numFields < 0 || (numFields * width + offset) > data.length) {
// Try to decode the max number of characters in payload
int padding = offset % width;
int maxNumFields = (data.length - offset - padding) / width;
if (maxNumFields < 0) {
throw new CodingException(charset + " decode failed: offset out of range");
}
Rlog.e(LOG_TAG, charset + " decode error: offset = " + offset + " numFields = "
+ numFields + " data.length = " + data.length + " maxNumFields = "
+ maxNumFields);
numFields = maxNumFields;
}
try {
return new String(data, offset, numFields * width, charset);
} catch (java.io.UnsupportedEncodingException ex) {
throw new CodingException(charset + " decode failed: " + ex);
}
| private static void | decodeCmasUserData(com.android.internal.telephony.cdma.sms.BearerData bData, int serviceCategory)CMAS message decoding.
(See TIA-1149-0-1, CMAS over CDMA)
BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
if (inStream.available() < 8) {
throw new CodingException("emergency CB with no CMAE_protocol_version");
}
int protocolVersion = inStream.read(8);
if (protocolVersion != 0) {
throw new CodingException("unsupported CMAE_protocol_version " + protocolVersion);
}
int messageClass = serviceCategoryToCmasMessageClass(serviceCategory);
int category = SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN;
int responseType = SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN;
int severity = SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
int urgency = SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
int certainty = SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
while (inStream.available() >= 16) {
int recordType = inStream.read(8);
int recordLen = inStream.read(8);
switch (recordType) {
case 0: // Type 0 elements (Alert text)
UserData alertUserData = new UserData();
alertUserData.msgEncoding = inStream.read(5);
alertUserData.msgEncodingSet = true;
alertUserData.msgType = 0;
int numFields; // number of chars to decode
switch (alertUserData.msgEncoding) {
case UserData.ENCODING_OCTET:
case UserData.ENCODING_LATIN:
numFields = recordLen - 1; // subtract 1 byte for encoding
break;
case UserData.ENCODING_IA5:
case UserData.ENCODING_7BIT_ASCII:
case UserData.ENCODING_GSM_7BIT_ALPHABET:
numFields = ((recordLen * 8) - 5) / 7; // subtract 5 bits for encoding
break;
case UserData.ENCODING_UNICODE_16:
numFields = (recordLen - 1) / 2;
break;
default:
numFields = 0; // unsupported encoding
}
alertUserData.numFields = numFields;
alertUserData.payload = inStream.readByteArray(recordLen * 8 - 5);
decodeUserDataPayload(alertUserData, false);
bData.userData = alertUserData;
break;
case 1: // Type 1 elements
category = inStream.read(8);
responseType = inStream.read(8);
severity = inStream.read(4);
urgency = inStream.read(4);
certainty = inStream.read(4);
inStream.skip(recordLen * 8 - 28);
break;
default:
Rlog.w(LOG_TAG, "skipping unsupported CMAS record type " + recordType);
inStream.skip(recordLen * 8);
break;
}
}
bData.cmasWarningInfo = new SmsCbCmasInfo(messageClass, category, responseType, severity,
urgency, certainty);
| private static boolean | decodeDeferredDeliveryAbs(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 6 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.deferredDeliveryTimeAbsolute = TimeStamp.fromByteArray(
inStream.readByteArray(6 * 8));
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeDeferredDeliveryRel(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.validityPeriodRelative = inStream.read(8);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.validityPeriodRelativeSet = decodeSuccess;
return decodeSuccess;
| private static boolean | decodeDepositIndex(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 2 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.depositIndex = (inStream.read(8) << 8) | inStream.read(8);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeDisplayMode(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.displayMode = inStream.read(2);
inStream.skip(6);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "DISPLAY_MODE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.displayModeSet = decodeSuccess;
return decodeSuccess;
| private static java.lang.String | decodeDtmfSmsAddress(byte[] rawData, int numFields)
/* DTMF 4-bit digit encoding, defined in at
* 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
StringBuffer strBuf = new StringBuffer(numFields);
for (int i = 0; i < numFields; i++) {
int val = 0x0F & (rawData[i / 2] >>> (4 - ((i % 2) * 4)));
if ((val >= 1) && (val <= 9)) strBuf.append(Integer.toString(val, 10));
else if (val == 10) strBuf.append('0");
else if (val == 11) strBuf.append('*");
else if (val == 12) strBuf.append('#");
else throw new CodingException("invalid SMS address DTMF code (" + val + ")");
}
return strBuf.toString();
| private static void | decodeIs91(com.android.internal.telephony.cdma.sms.BearerData bData)
switch (bData.userData.msgType) {
case UserData.IS91_MSG_TYPE_VOICEMAIL_STATUS:
decodeIs91VoicemailStatus(bData);
break;
case UserData.IS91_MSG_TYPE_CLI:
decodeIs91Cli(bData);
break;
case UserData.IS91_MSG_TYPE_SHORT_MESSAGE_FULL:
case UserData.IS91_MSG_TYPE_SHORT_MESSAGE:
decodeIs91ShortMessage(bData);
break;
default:
throw new CodingException("unsupported IS-91 message type (" +
bData.userData.msgType + ")");
}
| private static void | decodeIs91Cli(com.android.internal.telephony.cdma.sms.BearerData bData)IS-91 CLI message (callback number) decoding
(See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
Protocol Summary: The data payload may contain 1-32 digits,
encoded using standard 4-bit DTMF, which are treated as a
callback number.
BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
int dataLen = inStream.available() / 4; // 4-bit packed DTMF digit encoding.
int numFields = bData.userData.numFields;
if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
throw new CodingException("IS-91 voicemail status decoding failed");
}
CdmaSmsAddress addr = new CdmaSmsAddress();
addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
addr.origBytes = bData.userData.payload;
addr.numberOfDigits = (byte)numFields;
decodeSmsAddress(addr);
bData.callbackNumber = addr;
| private static void | decodeIs91ShortMessage(com.android.internal.telephony.cdma.sms.BearerData bData)IS-91 Short Message decoding
(See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
(For character encodings, see TIA/EIA/IS-91, Annex B)
Protocol Summary: The user data payload may contain 1-14
characters, which are treated as normal text user data payload.
Note that the characters encoding is 6-bit packed.
BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
int dataLen = inStream.available() / 6; // 6-bit packed character encoding.
int numFields = bData.userData.numFields;
// dataLen may be > 14 characters due to octet padding
if ((numFields > 14) || (dataLen < numFields)) {
throw new CodingException("IS-91 short message decoding failed");
}
StringBuffer strbuf = new StringBuffer(dataLen);
for (int i = 0; i < numFields; i++) {
strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
}
bData.userData.payloadStr = strbuf.toString();
| private static void | decodeIs91VoicemailStatus(com.android.internal.telephony.cdma.sms.BearerData bData)IS-91 Voice Mail message decoding
(See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
(For character encodings, see TIA/EIA/IS-91, Annex B)
Protocol Summary: The user data payload may contain 3-14
characters. The first two characters are parsed as a number
and indicate the number of voicemails. The third character is
either a SPACE or '!' to indicate normal or urgent priority,
respectively. Any following characters are treated as normal
text user data payload.
Note that the characters encoding is 6-bit packed.
BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
int dataLen = inStream.available() / 6; // 6-bit packed character encoding.
int numFields = bData.userData.numFields;
if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
throw new CodingException("IS-91 voicemail status decoding failed");
}
try {
StringBuffer strbuf = new StringBuffer(dataLen);
while (inStream.available() >= 6) {
strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
}
String data = strbuf.toString();
bData.numberOfMessages = Integer.parseInt(data.substring(0, 2));
char prioCode = data.charAt(2);
if (prioCode == ' ") {
bData.priority = PRIORITY_NORMAL;
} else if (prioCode == '!") {
bData.priority = PRIORITY_URGENT;
} else {
throw new CodingException("IS-91 voicemail status decoding failed: " +
"illegal priority setting (" + prioCode + ")");
}
bData.priorityIndicatorSet = true;
bData.userData.payloadStr = data.substring(3, numFields - 3);
} catch (java.lang.NumberFormatException ex) {
throw new CodingException("IS-91 voicemail status decoding failed: " + ex);
} catch (java.lang.IndexOutOfBoundsException ex) {
throw new CodingException("IS-91 voicemail status decoding failed: " + ex);
}
| private static boolean | decodeLanguageIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.language = inStream.read(8);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "LANGUAGE_INDICATOR decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.languageIndicatorSet = decodeSuccess;
return decodeSuccess;
| private static java.lang.String | decodeLatin(byte[] data, int offset, int numFields)
return decodeCharset(data, offset, numFields, 1, "ISO-8859-1");
| private static boolean | decodeMessageId(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 3 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.messageType = inStream.read(4);
bData.messageId = inStream.read(8) << 8;
bData.messageId |= inStream.read(8);
bData.hasUserDataHeader = (inStream.read(1) == 1);
inStream.skip(3);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeMsgCenterTimeStamp(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 6 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.msgCenterTimeStamp = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeMsgCount(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.numberOfMessages = IccUtils.cdmaBcdByteToInt((byte)inStream.read(8));
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeMsgDeliveryAlert(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.alert = inStream.read(2);
inStream.skip(6);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.alertIndicatorSet = decodeSuccess;
return decodeSuccess;
| private static boolean | decodeMsgStatus(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.errorClass = inStream.read(2);
bData.messageStatus = inStream.read(6);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "MESSAGE_STATUS decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.messageStatusSet = decodeSuccess;
return decodeSuccess;
| private static boolean | decodePriorityIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.priority = inStream.read(2);
inStream.skip(6);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "PRIORITY_INDICATOR decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.priorityIndicatorSet = decodeSuccess;
return decodeSuccess;
| private static boolean | decodePrivacyIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.privacy = inStream.read(2);
inStream.skip(6);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "PRIVACY_INDICATOR decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.privacyIndicatorSet = decodeSuccess;
return decodeSuccess;
| private static boolean | decodeReplyOption(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.userAckReq = (inStream.read(1) == 1);
bData.deliveryAckReq = (inStream.read(1) == 1);
bData.readAckReq = (inStream.read(1) == 1);
bData.reportReq = (inStream.read(1) == 1);
inStream.skip(4);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "REPLY_OPTION decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeReserved(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream, int subparamId)
boolean decodeSuccess = false;
int subparamLen = inStream.read(8); // SUBPARAM_LEN
int paramBits = subparamLen * 8;
if (paramBits <= inStream.available()) {
decodeSuccess = true;
inStream.skip(paramBits);
}
Rlog.d(LOG_TAG, "RESERVED bearer data subparameter " + subparamId + " decode "
+ (decodeSuccess ? "succeeded" : "failed") + " (param bits = " + paramBits + ")");
if (!decodeSuccess) {
throw new CodingException("RESERVED bearer data subparameter " + subparamId
+ " had invalid SUBPARAM_LEN " + subparamLen);
}
return decodeSuccess;
| private static boolean | decodeServiceCategoryProgramData(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
if (inStream.available() < 13) {
throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only "
+ inStream.available() + " bits available");
}
int paramBits = inStream.read(8) * 8;
int msgEncoding = inStream.read(5);
paramBits -= 5;
if (inStream.available() < paramBits) {
throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only "
+ inStream.available() + " bits available (" + paramBits + " bits expected)");
}
ArrayList<CdmaSmsCbProgramData> programDataList = new ArrayList<CdmaSmsCbProgramData>();
final int CATEGORY_FIELD_MIN_SIZE = 6 * 8;
boolean decodeSuccess = false;
while (paramBits >= CATEGORY_FIELD_MIN_SIZE) {
int operation = inStream.read(4);
int category = (inStream.read(8) << 8) | inStream.read(8);
int language = inStream.read(8);
int maxMessages = inStream.read(8);
int alertOption = inStream.read(4);
int numFields = inStream.read(8);
paramBits -= CATEGORY_FIELD_MIN_SIZE;
int textBits = getBitsForNumFields(msgEncoding, numFields);
if (paramBits < textBits) {
throw new CodingException("category name is " + textBits + " bits in length,"
+ " but there are only " + paramBits + " bits available");
}
UserData userData = new UserData();
userData.msgEncoding = msgEncoding;
userData.msgEncodingSet = true;
userData.numFields = numFields;
userData.payload = inStream.readByteArray(textBits);
paramBits -= textBits;
decodeUserDataPayload(userData, false);
String categoryName = userData.payloadStr;
CdmaSmsCbProgramData programData = new CdmaSmsCbProgramData(operation, category,
language, maxMessages, alertOption, categoryName);
programDataList.add(programData);
decodeSuccess = true;
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "SERVICE_CATEGORY_PROGRAM_DATA decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ')");
}
inStream.skip(paramBits);
bData.serviceCategoryProgramData = programDataList;
return decodeSuccess;
| private static java.lang.String | decodeShiftJis(byte[] data, int offset, int numFields)
return decodeCharset(data, offset, numFields, 1, "Shift_JIS");
| private static void | decodeSmsAddress(CdmaSmsAddress addr)
if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
try {
/* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
* just 7-bit ASCII encoding, with the MSB being zero. */
addr.address = new String(addr.origBytes, 0, addr.origBytes.length, "US-ASCII");
} catch (java.io.UnsupportedEncodingException ex) {
throw new CodingException("invalid SMS address ASCII code");
}
} else {
addr.address = decodeDtmfSmsAddress(addr.origBytes, addr.numberOfDigits);
}
| private static boolean | decodeUserData(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
int paramBits = inStream.read(8) * 8;
bData.userData = new UserData();
bData.userData.msgEncoding = inStream.read(5);
bData.userData.msgEncodingSet = true;
bData.userData.msgType = 0;
int consumedBits = 5;
if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
(bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
bData.userData.msgType = inStream.read(8);
consumedBits += 8;
}
bData.userData.numFields = inStream.read(8);
consumedBits += 8;
int dataBits = paramBits - consumedBits;
bData.userData.payload = inStream.readByteArray(dataBits);
return true;
| private static void | decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
int offset = 0;
if (hasUserDataHeader) {
int udhLen = userData.payload[0] & 0x00FF;
offset += udhLen + 1;
byte[] headerData = new byte[udhLen];
System.arraycopy(userData.payload, 1, headerData, 0, udhLen);
userData.userDataHeader = SmsHeader.fromByteArray(headerData);
}
switch (userData.msgEncoding) {
case UserData.ENCODING_OCTET:
/*
* Octet decoding depends on the carrier service.
*/
boolean decodingtypeUTF8 = Resources.getSystem()
.getBoolean(com.android.internal.R.bool.config_sms_utf8_support);
// Strip off any padding bytes, meaning any differences between the length of the
// array and the target length specified by numFields. This is to avoid any
// confusion by code elsewhere that only considers the payload array length.
byte[] payload = new byte[userData.numFields];
int copyLen = userData.numFields < userData.payload.length
? userData.numFields : userData.payload.length;
System.arraycopy(userData.payload, 0, payload, 0, copyLen);
userData.payload = payload;
if (!decodingtypeUTF8) {
// There are many devices in the market that send 8bit text sms (latin encoded) as
// octet encoded.
userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
} else {
userData.payloadStr = decodeUtf8(userData.payload, offset, userData.numFields);
}
break;
case UserData.ENCODING_IA5:
case UserData.ENCODING_7BIT_ASCII:
userData.payloadStr = decode7bitAscii(userData.payload, offset, userData.numFields);
break;
case UserData.ENCODING_UNICODE_16:
userData.payloadStr = decodeUtf16(userData.payload, offset, userData.numFields);
break;
case UserData.ENCODING_GSM_7BIT_ALPHABET:
userData.payloadStr = decode7bitGsm(userData.payload, offset, userData.numFields);
break;
case UserData.ENCODING_LATIN:
userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
break;
case UserData.ENCODING_SHIFT_JIS:
userData.payloadStr = decodeShiftJis(userData.payload, offset, userData.numFields);
break;
default:
throw new CodingException("unsupported user data encoding ("
+ userData.msgEncoding + ")");
}
| private static boolean | decodeUserResponseCode(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.userResponseCode = inStream.read(8);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "USER_RESPONSE_CODE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.userResponseCodeSet = decodeSuccess;
return decodeSuccess;
| private static java.lang.String | decodeUtf16(byte[] data, int offset, int numFields)
// Subtract header and possible padding byte (at end) from num fields.
int padding = offset % 2;
numFields -= (offset + padding) / 2;
return decodeCharset(data, offset, numFields, 2, "utf-16be");
| private static java.lang.String | decodeUtf8(byte[] data, int offset, int numFields)
return decodeCharset(data, offset, numFields, 1, "UTF-8");
| private static boolean | decodeValidityAbs(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 6 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.validityPeriodAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
return decodeSuccess;
| private static boolean | decodeValidityRel(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseInputStream inStream)
final int EXPECTED_PARAM_SIZE = 1 * 8;
boolean decodeSuccess = false;
int paramBits = inStream.read(8) * 8;
if (paramBits >= EXPECTED_PARAM_SIZE) {
paramBits -= EXPECTED_PARAM_SIZE;
decodeSuccess = true;
bData.deferredDeliveryTimeRelative = inStream.read(8);
}
if ((! decodeSuccess) || (paramBits > 0)) {
Rlog.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " +
(decodeSuccess ? "succeeded" : "failed") +
" (extra bits = " + paramBits + ")");
}
inStream.skip(paramBits);
bData.deferredDeliveryTimeRelativeSet = decodeSuccess;
return decodeSuccess;
| public static byte[] | encode(com.android.internal.telephony.cdma.sms.BearerData bData)Create serialized representation for BearerData object.
(See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
bData.hasUserDataHeader = ((bData.userData != null) &&
(bData.userData.userDataHeader != null));
try {
BitwiseOutputStream outStream = new BitwiseOutputStream(200);
outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
encodeMessageId(bData, outStream);
if (bData.userData != null) {
outStream.write(8, SUBPARAM_USER_DATA);
encodeUserData(bData, outStream);
}
if (bData.callbackNumber != null) {
outStream.write(8, SUBPARAM_CALLBACK_NUMBER);
encodeCallbackNumber(bData, outStream);
}
if (bData.userAckReq || bData.deliveryAckReq || bData.readAckReq || bData.reportReq) {
outStream.write(8, SUBPARAM_REPLY_OPTION);
encodeReplyOption(bData, outStream);
}
if (bData.numberOfMessages != 0) {
outStream.write(8, SUBPARAM_NUMBER_OF_MESSAGES);
encodeMsgCount(bData, outStream);
}
if (bData.validityPeriodRelativeSet) {
outStream.write(8, SUBPARAM_VALIDITY_PERIOD_RELATIVE);
encodeValidityPeriodRel(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);
}
if (bData.serviceCategoryProgramResults != null) {
outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
encodeScpResults(bData, outStream);
}
return outStream.toByteArray();
} catch (BitwiseOutputStream.AccessException ex) {
Rlog.e(LOG_TAG, "BearerData encode failed: " + ex);
} catch (CodingException ex) {
Rlog.e(LOG_TAG, "BearerData encode failed: " + ex);
}
return null;
| private static void | encode16bitEms(UserData uData, byte[] udhData)
byte[] payload = encodeUtf16(uData.payloadStr);
int udhBytes = udhData.length + 1; // Add length octet.
int udhCodeUnits = (udhBytes + 1) / 2;
int payloadCodeUnits = payload.length / 2;
uData.msgEncoding = UserData.ENCODING_UNICODE_16;
uData.msgEncodingSet = true;
uData.numFields = udhCodeUnits + payloadCodeUnits;
uData.payload = new byte[uData.numFields * 2];
uData.payload[0] = (byte)udhData.length;
System.arraycopy(udhData, 0, uData.payload, 1, udhData.length);
System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length);
| private static byte[] | encode7bitAscii(java.lang.String msg, boolean force)
try {
BitwiseOutputStream outStream = new BitwiseOutputStream(msg.length());
int msgLen = msg.length();
for (int i = 0; i < msgLen; i++) {
int charCode = UserData.charToAscii.get(msg.charAt(i), -1);
if (charCode == -1) {
if (force) {
outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR);
} else {
throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")");
}
} else {
outStream.write(7, charCode);
}
}
return outStream.toByteArray();
} catch (BitwiseOutputStream.AccessException ex) {
throw new CodingException("7bit ASCII encode failed: " + ex);
}
| private static void | encode7bitEms(UserData uData, byte[] udhData, boolean force)
int udhBytes = udhData.length + 1; // Add length octet.
int udhSeptets = ((udhBytes * 8) + 6) / 7;
Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, udhSeptets, force);
uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
uData.msgEncodingSet = true;
uData.numFields = gcr.septets;
uData.payload = gcr.data;
uData.payload[0] = (byte)udhData.length;
System.arraycopy(udhData, 0, uData.payload, 1, udhData.length);
| private static com.android.internal.telephony.cdma.sms.BearerData$Gsm7bitCodingResult | encode7bitGsm(java.lang.String msg, int septetOffset, boolean force)
try {
/*
* TODO(cleanup): It would be nice if GsmAlphabet provided
* an option to produce just the data without prepending
* the septet count, as this function is really just a
* wrapper to strip that off. Not to mention that the
* septet count is generally known prior to invocation of
* the encoder. Note that it cannot be derived from the
* resulting array length, since that cannot distinguish
* if the last contains either 1 or 8 valid bits.
*
* TODO(cleanup): The BitwiseXStreams could also be
* extended with byte-wise reversed endianness read/write
* routines to allow a corresponding implementation of
* stringToGsm7BitPacked, and potentially directly support
* access to the main bitwise stream from encode/decode.
*/
byte[] fullData = GsmAlphabet.stringToGsm7BitPacked(msg, septetOffset, !force, 0, 0);
Gsm7bitCodingResult result = new Gsm7bitCodingResult();
result.data = new byte[fullData.length - 1];
System.arraycopy(fullData, 1, result.data, 0, fullData.length - 1);
result.septets = fullData[0] & 0x00FF;
return result;
} catch (com.android.internal.telephony.EncodeException ex) {
throw new CodingException("7bit GSM encode failed: " + ex);
}
| private static void | encodeCallbackNumber(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
CdmaSmsAddress addr = bData.callbackNumber;
encodeCdmaSmsAddress(addr);
int paramBits = 9;
int dataBits = 0;
if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
paramBits += 7;
dataBits = addr.numberOfDigits * 8;
} else {
dataBits = addr.numberOfDigits * 4;
}
paramBits += dataBits;
int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
int paddingBits = (paramBytes * 8) - paramBits;
outStream.write(8, paramBytes);
outStream.write(1, addr.digitMode);
if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
outStream.write(3, addr.ton);
outStream.write(4, addr.numberPlan);
}
outStream.write(8, addr.numberOfDigits);
outStream.writeByteArray(dataBits, addr.origBytes);
if (paddingBits > 0) outStream.write(paddingBits, 0);
| private static void | encodeCdmaSmsAddress(CdmaSmsAddress addr)
if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
try {
addr.origBytes = addr.address.getBytes("US-ASCII");
} catch (java.io.UnsupportedEncodingException ex) {
throw new CodingException("invalid SMS address, cannot convert to ASCII");
}
} else {
addr.origBytes = encodeDtmfSmsAddress(addr.address);
}
| private static void | encodeDisplayMode(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(2, bData.displayMode);
outStream.skip(6);
| private static byte[] | encodeDtmfSmsAddress(java.lang.String address)
int digits = address.length();
int dataBits = digits * 4;
int dataBytes = (dataBits / 8);
dataBytes += (dataBits % 8) > 0 ? 1 : 0;
byte[] rawData = new byte[dataBytes];
for (int i = 0; i < digits; i++) {
char c = address.charAt(i);
int val = 0;
if ((c >= '1") && (c <= '9")) val = c - '0";
else if (c == '0") val = 10;
else if (c == '*") val = 11;
else if (c == '#") val = 12;
else return null;
rawData[i / 2] |= val << (4 - ((i % 2) * 4));
}
return rawData;
| private static void | encodeEmsUserDataPayload(UserData uData)
byte[] headerData = SmsHeader.toByteArray(uData.userDataHeader);
if (uData.msgEncodingSet) {
if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) {
encode7bitEms(uData, headerData, true);
} else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
encode16bitEms(uData, headerData);
} else {
throw new CodingException("unsupported EMS user data encoding (" +
uData.msgEncoding + ")");
}
} else {
try {
encode7bitEms(uData, headerData, false);
} catch (CodingException ex) {
encode16bitEms(uData, headerData);
}
}
| private static void | encodeLanguageIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(8, bData.language);
| private static void | encodeMessageId(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 3);
outStream.write(4, bData.messageType);
outStream.write(8, bData.messageId >> 8);
outStream.write(8, bData.messageId);
outStream.write(1, bData.hasUserDataHeader ? 1 : 0);
outStream.skip(3);
| private static void | encodeMsgCount(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(8, bData.numberOfMessages);
| private static void | encodeMsgDeliveryAlert(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(2, bData.alert);
outStream.skip(6);
| private static void | encodeMsgStatus(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(2, bData.errorClass);
outStream.write(6, bData.messageStatus);
| private static void | encodePriorityIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(2, bData.priority);
outStream.skip(6);
| private static void | encodePrivacyIndicator(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(2, bData.privacy);
outStream.skip(6);
| private static void | encodeReplyOption(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(1, bData.userAckReq ? 1 : 0);
outStream.write(1, bData.deliveryAckReq ? 1 : 0);
outStream.write(1, bData.readAckReq ? 1 : 0);
outStream.write(1, bData.reportReq ? 1 : 0);
outStream.write(4, 0);
| private static void | encodeScpResults(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
ArrayList<CdmaSmsCbProgramResults> results = bData.serviceCategoryProgramResults;
outStream.write(8, (results.size() * 4)); // 4 octets per program result
for (CdmaSmsCbProgramResults result : results) {
int category = result.getCategory();
outStream.write(8, category >> 8);
outStream.write(8, category);
outStream.write(8, result.getLanguage());
outStream.write(4, result.getCategoryResult());
outStream.skip(4);
}
| private static byte[] | encodeShiftJis(java.lang.String msg)
try {
return msg.getBytes("Shift_JIS");
} catch (java.io.UnsupportedEncodingException ex) {
throw new CodingException("Shift-JIS encode failed: " + ex);
}
| private static void | encodeUserData(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
/*
* TODO(cleanup): Do we really need to set userData.payload as
* a side effect of encoding? If not, we could avoid data
* copies by passing outStream directly.
*/
encodeUserDataPayload(bData.userData);
bData.hasUserDataHeader = bData.userData.userDataHeader != null;
if (bData.userData.payload.length > SmsConstants.MAX_USER_DATA_BYTES) {
throw new CodingException("encoded user data too large (" +
bData.userData.payload.length +
" > " + SmsConstants.MAX_USER_DATA_BYTES + " bytes)");
}
/*
* TODO(cleanup): figure out what the right answer is WRT paddingBits field
*
* userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7);
* userData.paddingBits = 0; // XXX this seems better, but why?
*
*/
int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
int paramBits = dataBits + 13;
if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
(bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
paramBits += 8;
}
int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
int paddingBits = (paramBytes * 8) - paramBits;
outStream.write(8, paramBytes);
outStream.write(5, bData.userData.msgEncoding);
if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
(bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
outStream.write(8, bData.userData.msgType);
}
outStream.write(8, bData.userData.numFields);
outStream.writeByteArray(dataBits, bData.userData.payload);
if (paddingBits > 0) outStream.write(paddingBits, 0);
| private static void | encodeUserDataPayload(UserData uData)
if ((uData.payloadStr == null) && (uData.msgEncoding != UserData.ENCODING_OCTET)) {
Rlog.e(LOG_TAG, "user data with null payloadStr");
uData.payloadStr = "";
}
if (uData.userDataHeader != null) {
encodeEmsUserDataPayload(uData);
return;
}
if (uData.msgEncodingSet) {
if (uData.msgEncoding == UserData.ENCODING_OCTET) {
if (uData.payload == null) {
Rlog.e(LOG_TAG, "user data with octet encoding but null payload");
uData.payload = new byte[0];
uData.numFields = 0;
} else {
uData.numFields = uData.payload.length;
}
} else {
if (uData.payloadStr == null) {
Rlog.e(LOG_TAG, "non-octet user data with null payloadStr");
uData.payloadStr = "";
}
if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) {
Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, 0, true);
uData.payload = gcr.data;
uData.numFields = gcr.septets;
} else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) {
uData.payload = encode7bitAscii(uData.payloadStr, true);
uData.numFields = uData.payloadStr.length();
} else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
uData.payload = encodeUtf16(uData.payloadStr);
uData.numFields = uData.payloadStr.length();
} else if (uData.msgEncoding == UserData.ENCODING_SHIFT_JIS) {
uData.payload = encodeShiftJis(uData.payloadStr);
uData.numFields = uData.payload.length;
} else {
throw new CodingException("unsupported user data encoding (" +
uData.msgEncoding + ")");
}
}
} else {
try {
uData.payload = encode7bitAscii(uData.payloadStr, false);
uData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
} catch (CodingException ex) {
uData.payload = encodeUtf16(uData.payloadStr);
uData.msgEncoding = UserData.ENCODING_UNICODE_16;
}
uData.numFields = uData.payloadStr.length();
uData.msgEncodingSet = true;
}
| private static byte[] | encodeUtf16(java.lang.String msg)
try {
return msg.getBytes("utf-16be");
} catch (java.io.UnsupportedEncodingException ex) {
throw new CodingException("UTF-16 encode failed: " + ex);
}
| private static void | encodeValidityPeriodRel(com.android.internal.telephony.cdma.sms.BearerData bData, com.android.internal.util.BitwiseOutputStream outStream)
outStream.write(8, 1);
outStream.write(8, bData.validityPeriodRelative);
| private static int | getBitsForNumFields(int msgEncoding, int numFields)Calculates the number of bits to read for the specified number of encoded characters.
switch (msgEncoding) {
case UserData.ENCODING_OCTET:
case UserData.ENCODING_SHIFT_JIS:
case UserData.ENCODING_KOREAN:
case UserData.ENCODING_LATIN:
case UserData.ENCODING_LATIN_HEBREW:
return numFields * 8;
case UserData.ENCODING_IA5:
case UserData.ENCODING_7BIT_ASCII:
case UserData.ENCODING_GSM_7BIT_ALPHABET:
return numFields * 7;
case UserData.ENCODING_UNICODE_16:
return numFields * 16;
default:
throw new CodingException("unsupported message encoding (" + msgEncoding + ')");
}
| public java.lang.String | getLanguage()Returns the language indicator as a two-character ISO 639 string.
return getLanguageCodeForValue(language);
| private static java.lang.String | getLanguageCodeForValue(int languageValue)Converts a CDMA language indicator value to an ISO 639 two character language code.
switch (languageValue) {
case LANGUAGE_ENGLISH:
return "en";
case LANGUAGE_FRENCH:
return "fr";
case LANGUAGE_SPANISH:
return "es";
case LANGUAGE_JAPANESE:
return "ja";
case LANGUAGE_KOREAN:
return "ko";
case LANGUAGE_CHINESE:
return "zh";
case LANGUAGE_HEBREW:
return "he";
default:
return null;
}
| private static boolean | isCmasAlertCategory(int category)
return category >= SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT
&& category <= SmsEnvelope.SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE;
| private static int | serviceCategoryToCmasMessageClass(int serviceCategory)
switch (serviceCategory) {
case SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT:
return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT:
return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT;
case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT:
return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT;
case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY:
return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE:
return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST;
default:
return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN;
}
| public java.lang.String | toString()
StringBuilder builder = new StringBuilder();
builder.append("BearerData ");
builder.append("{ messageType=" + messageType);
builder.append(", messageId=" + messageId);
builder.append(", priority=" + (priorityIndicatorSet ? priority : "unset"));
builder.append(", privacy=" + (privacyIndicatorSet ? privacy : "unset"));
builder.append(", alert=" + (alertIndicatorSet ? alert : "unset"));
builder.append(", displayMode=" + (displayModeSet ? displayMode : "unset"));
builder.append(", language=" + (languageIndicatorSet ? language : "unset"));
builder.append(", errorClass=" + (messageStatusSet ? errorClass : "unset"));
builder.append(", msgStatus=" + (messageStatusSet ? messageStatus : "unset"));
builder.append(", msgCenterTimeStamp=" +
((msgCenterTimeStamp != null) ? msgCenterTimeStamp : "unset"));
builder.append(", validityPeriodAbsolute=" +
((validityPeriodAbsolute != null) ? validityPeriodAbsolute : "unset"));
builder.append(", validityPeriodRelative=" +
((validityPeriodRelativeSet) ? validityPeriodRelative : "unset"));
builder.append(", deferredDeliveryTimeAbsolute=" +
((deferredDeliveryTimeAbsolute != null) ? deferredDeliveryTimeAbsolute : "unset"));
builder.append(", deferredDeliveryTimeRelative=" +
((deferredDeliveryTimeRelativeSet) ? deferredDeliveryTimeRelative : "unset"));
builder.append(", userAckReq=" + userAckReq);
builder.append(", deliveryAckReq=" + deliveryAckReq);
builder.append(", readAckReq=" + readAckReq);
builder.append(", reportReq=" + reportReq);
builder.append(", numberOfMessages=" + numberOfMessages);
builder.append(", callbackNumber=" + callbackNumber);
builder.append(", depositIndex=" + depositIndex);
builder.append(", hasUserDataHeader=" + hasUserDataHeader);
builder.append(", userData=" + userData);
builder.append(" }");
return builder.toString();
|
|