Merge change 133 into donut
* changes: Initial code for cdma sms encode and decode, in java, with simple tests.
This commit is contained in:
@@ -20,20 +20,7 @@ import android.util.Log;
|
||||
import com.android.internal.telephony.SmsHeader;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static android.telephony.SmsMessage.ENCODING_7BIT;
|
||||
import static android.telephony.SmsMessage.ENCODING_16BIT;
|
||||
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;
|
||||
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
|
||||
import static android.telephony.SmsMessage.MessageClass;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_ABBREVIATED;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_ALPHANUMERIC;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_INTERNATIONAL;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_NATIONAL;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_NETWORK;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_SUBSCRIBER;
|
||||
import static com.android.internal.telephony.SmsAddress.TON_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Base class declaring the specific methods and members for SmsMessage.
|
||||
@@ -385,4 +372,3 @@ public abstract class SmsMessageBase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.android.internal.telephony.SmsHeader;
|
||||
import com.android.internal.telephony.SmsMessageBase;
|
||||
import com.android.internal.telephony.cdma.sms.BearerData;
|
||||
import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
|
||||
import com.android.internal.telephony.cdma.sms.SmsDataCoding;
|
||||
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
|
||||
import com.android.internal.telephony.cdma.sms.UserData;
|
||||
|
||||
@@ -50,23 +49,6 @@ import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
|
||||
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
|
||||
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
|
||||
import static android.telephony.SmsMessage.MessageClass;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_NONE;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_TEMPORARY;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_PERMANENT;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVER;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_SUBMIT;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_CANCELLATION;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVERY_ACK;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_USER_ACK;
|
||||
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_READ_ACK;
|
||||
import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_ADDRESS_MAX;
|
||||
import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_SUBADDRESS_MAX;
|
||||
import static com.android.internal.telephony.cdma.sms.SmsEnvelope.SMS_BEARER_DATA_MAX;
|
||||
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_7BIT_ASCII;
|
||||
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
|
||||
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_IA5;
|
||||
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_OCTET;
|
||||
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_UNICODE_16;
|
||||
|
||||
/**
|
||||
* A Short Message Service message.
|
||||
@@ -186,7 +168,7 @@ public class SmsMessage extends SmsMessageBase {
|
||||
|
||||
// ignore subaddress
|
||||
p.readInt(); //p_cur->sSubAddress.subaddressType
|
||||
p.readByte(); //p_cur->sSubAddress.odd
|
||||
p.readInt(); //p_cur->sSubAddress.odd
|
||||
count = p.readByte(); //p_cur->sSubAddress.number_of_digits
|
||||
//p_cur->sSubAddress.digits[digitCount] :
|
||||
for (int index=0; index < count; index++) {
|
||||
@@ -309,15 +291,15 @@ public class SmsMessage extends SmsMessageBase {
|
||||
int septetCount = GsmAlphabet.countGsmSeptets(message, true);
|
||||
// User Data (and length)
|
||||
|
||||
uData.userData = message.getBytes();
|
||||
uData.payload = message.getBytes();
|
||||
|
||||
if (uData.userData.length > MAX_USER_DATA_SEPTETS) {
|
||||
if (uData.payload.length > MAX_USER_DATA_SEPTETS) {
|
||||
// Message too long
|
||||
return null;
|
||||
}
|
||||
|
||||
// desired TP-Data-Coding-Scheme
|
||||
uData.userDataEncoding = UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
|
||||
uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
|
||||
|
||||
// paddingBits not needed for UD_ENCODING_GSM_7BIT_ALPHABET
|
||||
|
||||
@@ -341,15 +323,15 @@ public class SmsMessage extends SmsMessageBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
uData.userData = textPart;
|
||||
uData.payload = textPart;
|
||||
|
||||
if (uData.userData.length > MAX_USER_DATA_BYTES) {
|
||||
if (uData.payload.length > MAX_USER_DATA_BYTES) {
|
||||
// Message too long
|
||||
return null;
|
||||
}
|
||||
|
||||
// TP-Data-Coding-Scheme
|
||||
uData.userDataEncoding = UserData.UD_ENCODING_UNICODE_16;
|
||||
uData.msgEncoding = UserData.ENCODING_UNICODE_16;
|
||||
|
||||
// sms header
|
||||
if(headerData != null) {
|
||||
@@ -425,8 +407,8 @@ public class SmsMessage extends SmsMessageBase {
|
||||
|
||||
// TP-Data-Coding-Scheme
|
||||
// No class, 8 bit data
|
||||
uData.userDataEncoding = UserData.UD_ENCODING_OCTET;
|
||||
uData.userData = data;
|
||||
uData.msgEncoding = UserData.ENCODING_OCTET;
|
||||
uData.payload = data;
|
||||
|
||||
byte[] msgData = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
|
||||
true, true);
|
||||
@@ -619,21 +601,21 @@ public class SmsMessage extends SmsMessageBase {
|
||||
* Parses a SMS message from its BearerData stream. (mobile-terminated only)
|
||||
*/
|
||||
protected void parseSms() {
|
||||
mBearerData = SmsDataCoding.decodeCdmaSms(mEnvelope.bearerData);
|
||||
messageRef = mBearerData.messageID;
|
||||
mBearerData = BearerData.decode(mEnvelope.bearerData);
|
||||
messageRef = mBearerData.messageId;
|
||||
|
||||
// TP-Message-Type-Indicator
|
||||
// (See 3GPP2 C.S0015-B, v2, 4.5.1)
|
||||
int messageType = mBearerData.messageType;
|
||||
|
||||
switch (messageType) {
|
||||
case MESSAGE_TYPE_USER_ACK:
|
||||
case MESSAGE_TYPE_READ_ACK:
|
||||
case MESSAGE_TYPE_DELIVER:
|
||||
case BearerData.MESSAGE_TYPE_USER_ACK:
|
||||
case BearerData.MESSAGE_TYPE_READ_ACK:
|
||||
case BearerData.MESSAGE_TYPE_DELIVER:
|
||||
// Deliver (mobile-terminated only)
|
||||
parseSmsDeliver();
|
||||
break;
|
||||
case MESSAGE_TYPE_DELIVERY_ACK:
|
||||
case BearerData.MESSAGE_TYPE_DELIVERY_ACK:
|
||||
parseSmsDeliveryAck();
|
||||
break;
|
||||
|
||||
@@ -699,22 +681,22 @@ public class SmsMessage extends SmsMessageBase {
|
||||
return;
|
||||
}
|
||||
|
||||
encodingType = uData.userDataEncoding;
|
||||
encodingType = uData.msgEncoding;
|
||||
|
||||
// insert DCS-decoding here when type is supported by ril-library
|
||||
|
||||
userData = uData.userData;
|
||||
userData = uData.payload;
|
||||
userDataHeader = uData.userDataHeader;
|
||||
|
||||
switch (encodingType) {
|
||||
case UD_ENCODING_GSM_7BIT_ALPHABET:
|
||||
case UD_ENCODING_UNICODE_16:
|
||||
case UserData.ENCODING_GSM_7BIT_ALPHABET:
|
||||
case UserData.ENCODING_UNICODE_16:
|
||||
// user data was already decoded by wmsts-library
|
||||
messageBody = new String(userData);
|
||||
break;
|
||||
|
||||
// data and unsupported encodings:
|
||||
case UD_ENCODING_OCTET:
|
||||
case UserData.ENCODING_OCTET:
|
||||
default:
|
||||
messageBody = null;
|
||||
break;
|
||||
@@ -771,7 +753,7 @@ public class SmsMessage extends SmsMessageBase {
|
||||
if (useNewId) {
|
||||
setNextMessageId();
|
||||
}
|
||||
mBearerData.messageID = nextMessageId;
|
||||
mBearerData.messageId = nextMessageId;
|
||||
|
||||
// Set the reply options (See C.S0015-B, v2.0, 4.5.11)
|
||||
if(statusReportRequested) {
|
||||
@@ -795,7 +777,7 @@ public class SmsMessage extends SmsMessageBase {
|
||||
// ** encode BearerData **
|
||||
byte[] encodedBearerData = null;
|
||||
try {
|
||||
encodedBearerData = SmsDataCoding.encodeCdmaSms(mBearerData);
|
||||
encodedBearerData = BearerData.encode(mBearerData);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "doGetSubmitPdu: EncodeCdmaSMS function in JNI interface failed: "
|
||||
+ e.getMessage());
|
||||
|
||||
@@ -16,7 +16,52 @@
|
||||
|
||||
package com.android.internal.telephony.cdma.sms;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.telephony.GsmAlphabet;
|
||||
import com.android.internal.telephony.SmsHeader;
|
||||
import com.android.internal.telephony.cdma.sms.UserData;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
import com.android.internal.util.BitwiseInputStream;
|
||||
import com.android.internal.util.BitwiseOutputStream;
|
||||
|
||||
/**
|
||||
* XXX
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class BearerData{
|
||||
private final static String LOG_TAG = "SMS";
|
||||
|
||||
/**
|
||||
* Bearer Data Subparameter Indentifiers
|
||||
* (See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
|
||||
*/
|
||||
private final static byte SUBPARAM_MESSAGE_IDENTIFIER = 0x00;
|
||||
private final static byte SUBPARAM_USER_DATA = 0x01;
|
||||
private final static byte SUBPARAM_USER_REPONSE_CODE = 0x02;
|
||||
private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP = 0x03;
|
||||
//private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE = 0x04;
|
||||
//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_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_CALLBACK_NUMBER = 0x0E;
|
||||
//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;
|
||||
//private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13;
|
||||
private final static byte SUBPARAM_MESSAGE_STATUS = 0x14;
|
||||
//private final static byte SUBPARAM_TP_FAILURE_CAUSE = 0x15;
|
||||
//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.
|
||||
/**
|
||||
@@ -94,9 +139,6 @@ public final class BearerData{
|
||||
public static final int ERROR_UNDEFINED = 0xFF;
|
||||
public static final int STATUS_UNDEFINED = 0xFF;
|
||||
|
||||
/** Bit-mask indicating used fields for SmsDataCoding */
|
||||
public int mask;
|
||||
|
||||
/**
|
||||
* 4-bit value indicating the message type in accordance to
|
||||
* table 4.5.1-1
|
||||
@@ -109,7 +151,7 @@ public final class BearerData{
|
||||
* (Special rules apply for WAP-messages.)
|
||||
* (See 3GPP2 C.S0015-B, v2, 4.5.1)
|
||||
*/
|
||||
public int messageID;
|
||||
public int messageId;
|
||||
|
||||
/**
|
||||
* 1-bit value that indicates whether a User Data Header is present.
|
||||
@@ -188,5 +230,440 @@ public final class BearerData{
|
||||
*/
|
||||
public int messageStatus = STATUS_UNDEFINED;
|
||||
|
||||
}
|
||||
private static class CodingException extends Exception {
|
||||
public CodingException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("BearerData:\n");
|
||||
builder.append(" messageType: " + messageType + "\n");
|
||||
builder.append(" messageId: " + (int)messageId + "\n");
|
||||
builder.append(" hasUserDataHeader: " + hasUserDataHeader + "\n");
|
||||
builder.append(" timeStamp: " + timeStamp + "\n");
|
||||
builder.append(" userAckReq: " + userAckReq + "\n");
|
||||
builder.append(" deliveryAckReq: " + deliveryAckReq + "\n");
|
||||
builder.append(" readAckReq: " + readAckReq + "\n");
|
||||
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();
|
||||
}
|
||||
|
||||
private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
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 encodeUserData(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
|
||||
byte[] headerData = null;
|
||||
if (bData.hasUserDataHeader) {
|
||||
headerData = bData.userData.userDataHeader.toByteArray();
|
||||
dataBits += headerData.length * 8;
|
||||
}
|
||||
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);
|
||||
if (headerData != null) outStream.writeByteArray(headerData.length * 8, headerData);
|
||||
outStream.writeByteArray(dataBits, bData.userData.payload);
|
||||
if (paddingBits > 0) outStream.write(paddingBits, 0);
|
||||
}
|
||||
|
||||
private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
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 byte[] encodeDtmfSmsAddress(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 encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException {
|
||||
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 encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException, CodingException
|
||||
{
|
||||
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 encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
outStream.write(8, 1);
|
||||
outStream.write(2, bData.errorClass);
|
||||
outStream.write(6, bData.messageStatus);
|
||||
}
|
||||
|
||||
private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
outStream.write(8, 1);
|
||||
outStream.write(8, bData.numberOfMessages);
|
||||
}
|
||||
|
||||
private static void encodeMsgCenterTimeStamp(BearerData bData, BitwiseOutputStream outStream)
|
||||
throws BitwiseOutputStream.AccessException
|
||||
{
|
||||
outStream.write(8, 6);
|
||||
outStream.writeByteArray(6 * 8, bData.timeStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create serialized representation for BearerData object.
|
||||
* (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
|
||||
*
|
||||
* @param bearerData an instance of BearerData.
|
||||
*
|
||||
* @return data byta array of raw encoded SMS bearer data.
|
||||
*/
|
||||
public static byte[] encode(BearerData bData) {
|
||||
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.timeStamp != null) {
|
||||
outStream.write(8, SUBPARAM_MESSAGE_CENTER_TIME_STAMP);
|
||||
encodeMsgCenterTimeStamp(bData, outStream);
|
||||
}
|
||||
return outStream.toByteArray();
|
||||
} catch (BitwiseOutputStream.AccessException ex) {
|
||||
Log.e(LOG_TAG, "BearerData encode failed: " + ex);
|
||||
} catch (CodingException ex) {
|
||||
Log.e(LOG_TAG, "BearerData encode failed: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void decodeMessageId(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
if (inStream.read(8) != 3) {
|
||||
throw new CodingException("MESSAGE_IDENTIFIER subparam size incorrect");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private static void decodeUserData(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException
|
||||
{
|
||||
byte paramBytes = inStream.read(8);
|
||||
bData.userData = new UserData();
|
||||
bData.userData.msgEncoding = inStream.read(5);
|
||||
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 = (paramBytes * 8) - consumedBits;
|
||||
bData.userData.payload = inStream.readByteArray(dataBits);
|
||||
}
|
||||
|
||||
private static String decodePayloadStr(byte[] data, int offset, int numFields, String format)
|
||||
throws CodingException
|
||||
{
|
||||
try {
|
||||
return new String(data, offset, numFields, format);
|
||||
} catch (java.io.UnsupportedEncodingException ex) {
|
||||
throw new CodingException("invalid ASCII user data code");
|
||||
}
|
||||
}
|
||||
|
||||
private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
|
||||
throws CodingException
|
||||
{
|
||||
int offset = 0;
|
||||
if (hasUserDataHeader) {
|
||||
int UdhLen = userData.payload[0];
|
||||
byte[] headerData = new byte[UdhLen];
|
||||
System.arraycopy(userData.payload, 1, headerData, 0, UdhLen);
|
||||
userData.userDataHeader = SmsHeader.parse(headerData);
|
||||
}
|
||||
switch (userData.msgEncoding) {
|
||||
case UserData.ENCODING_GSM_7BIT_ALPHABET:
|
||||
userData.payloadStr = GsmAlphabet.gsm7BitPackedToString(userData.payload,
|
||||
offset, userData.numFields);
|
||||
break;
|
||||
case UserData.ENCODING_7BIT_ASCII:
|
||||
userData.payloadStr = decodePayloadStr(userData.payload, offset,
|
||||
userData.numFields, "US-ASCII");
|
||||
break;
|
||||
case UserData.ENCODING_UNICODE_16:
|
||||
userData.payloadStr = decodePayloadStr(userData.payload, offset,
|
||||
userData.numFields * 2, "UTF-16");
|
||||
break;
|
||||
default:
|
||||
throw new CodingException("unsupported user data encoding ("
|
||||
+ userData.msgEncoding + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private static void decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
byte paramBytes = inStream.read(8);
|
||||
if (paramBytes != 1) {
|
||||
throw new CodingException("REPLY_OPTION subparam size incorrect");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private static void decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
if (inStream.read(8) != 1) {
|
||||
throw new CodingException("NUMBER_OF_MESSAGES subparam size incorrect");
|
||||
}
|
||||
bData.numberOfMessages = inStream.read(8);
|
||||
}
|
||||
|
||||
private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
|
||||
throws CodingException
|
||||
{
|
||||
/* 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 decodeSmsAddress(CdmaSmsAddress addr) throws CodingException {
|
||||
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 void decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
byte paramBytes = inStream.read(8);
|
||||
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 = (paramBytes * 8) - 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;
|
||||
}
|
||||
|
||||
private static void decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
if (inStream.read(8) != 1) {
|
||||
throw new CodingException("MESSAGE_STATUS subparam size incorrect");
|
||||
}
|
||||
bData.errorClass = inStream.read(2);
|
||||
bData.messageStatus = inStream.read(6);
|
||||
}
|
||||
|
||||
private static void decodeMsgCenterTimeStamp(BearerData bData,
|
||||
BitwiseInputStream inStream)
|
||||
throws BitwiseInputStream.AccessException, CodingException
|
||||
{
|
||||
if (inStream.read(8) != 6) {
|
||||
throw new CodingException("MESSAGE_CENTER_TIME_STAMP subparam size incorrect");
|
||||
}
|
||||
bData.timeStamp = inStream.readByteArray(6 * 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create BearerData object from serialized representation.
|
||||
* (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
|
||||
*
|
||||
* @param smsData byte array of raw encoded SMS bearer data.
|
||||
*
|
||||
* @return an instance of BearerData.
|
||||
*/
|
||||
public static BearerData decode(byte[] smsData) {
|
||||
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;
|
||||
if ((foundSubparamMask & subparamIdBit) != 0) {
|
||||
throw new CodingException("illegal duplicate subparameter (" +
|
||||
subparamId + ")");
|
||||
}
|
||||
foundSubparamMask |= subparamIdBit;
|
||||
switch (subparamId) {
|
||||
case SUBPARAM_MESSAGE_IDENTIFIER:
|
||||
decodeMessageId(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_USER_DATA:
|
||||
decodeUserData(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_REPLY_OPTION:
|
||||
decodeReplyOption(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_NUMBER_OF_MESSAGES:
|
||||
decodeMsgCount(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_CALLBACK_NUMBER:
|
||||
decodeCallbackNumber(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_MESSAGE_STATUS:
|
||||
decodeMsgStatus(bData, inStream);
|
||||
break;
|
||||
case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
|
||||
decodeMsgCenterTimeStamp(bData, inStream);
|
||||
break;
|
||||
default:
|
||||
throw new CodingException("unsupported bearer data subparameter ("
|
||||
+ subparamId + ")");
|
||||
}
|
||||
}
|
||||
if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
|
||||
throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
|
||||
}
|
||||
if (bData.userData != null) {
|
||||
decodeUserDataPayload(bData.userData, bData.hasUserDataHeader);
|
||||
}
|
||||
return bData;
|
||||
} catch (BitwiseInputStream.AccessException ex) {
|
||||
Log.e(LOG_TAG, "BearerData decode failed: " + ex);
|
||||
} catch (CodingException ex) {
|
||||
Log.e(LOG_TAG, "BearerData decode failed: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.internal.telephony.cdma.sms;
|
||||
|
||||
import com.android.internal.telephony.SmsAddress;
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
public class CdmaSmsAddress extends SmsAddress {
|
||||
/**
|
||||
@@ -95,4 +96,18 @@ public class CdmaSmsAddress extends SmsAddress {
|
||||
public CdmaSmsAddress(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("CdmaSmsAddress:\n");
|
||||
builder.append(" digitMode: " + digitMode + "\n");
|
||||
builder.append(" numberMode: " + numberMode + "\n");
|
||||
builder.append(" numberPlan: " + numberPlan + "\n");
|
||||
builder.append(" numberOfDigits: " + numberOfDigits + "\n");
|
||||
builder.append(" ton: " + ton + "\n");
|
||||
builder.append(" address: " + address + "\n");
|
||||
builder.append(" origBytes: " + HexDump.toHexString(origBytes) + "\n");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.telephony.cdma.sms;
|
||||
|
||||
import com.android.internal.telephony.SmsHeader;
|
||||
|
||||
/*
|
||||
* The SMSDataCoding class encodes and decodes CDMA SMS messages.
|
||||
*/
|
||||
public class SmsDataCoding {
|
||||
private final static String TAG = "CDMA_SMS_JNI";
|
||||
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_NULL = 0x00000000;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_MSG_ID = 0x00000001;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_USER_DATA = 0x00000002;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_USER_RESP = 0x00000004;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_MC_TIME = 0x00000008;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_VALID_ABS = 0x00000010;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_VALID_REL = 0x00000020;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_DEFER_ABS = 0x00000040;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_DEFER_REL = 0x00000080;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_PRIORITY = 0x00000100;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_PRIVACY = 0x00000200;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_REPLY_OPTION = 0x00000400;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS = 0x00000800;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_ALERT = 0x00001000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_LANGUAGE = 0x00002000;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_CALLBACK = 0x00004000;
|
||||
private final static int CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE = 0x00008000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_SCPT_DATA = 0x00010000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_SCPT_RESULT = 0x00020000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_DEPOSIT_INDEX = 0x00040000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_DELIVERY_STATUS = 0x00080000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_IP_ADDRESS = 0x10000000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_RSN_NO_NOTIFY = 0x20000000;
|
||||
// private final static int CDMA_SMS_WMS_MASK_BD_OTHER = 0x40000000;
|
||||
|
||||
/**
|
||||
* Successful operation.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* General failure.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_FAILURE = 1;
|
||||
|
||||
/**
|
||||
* Data length is out of length.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_DATA_LEN_OUT_OF_RANGE = 2;
|
||||
|
||||
/**
|
||||
* Class name unknown.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_CLASS_UNKNOWN = 3;
|
||||
|
||||
/**
|
||||
* Field ID unknown.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_FIELD_ID_UNKNOWN = 4;
|
||||
|
||||
/**
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
private static final int JNI_CDMA_SMS_OUT_OF_MEMORY = 5;
|
||||
|
||||
/**
|
||||
* Encode SMS.
|
||||
*
|
||||
* @param bearerData an instance of BearerData.
|
||||
*
|
||||
* @return the encoded SMS as byte[].
|
||||
*/
|
||||
public static byte[] encodeCdmaSms(BearerData bearerData) {
|
||||
byte[] encodedSms;
|
||||
|
||||
if( nativeCdmaSmsConstructClientBD() == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
// check bearer data and generate bit mask
|
||||
generateBearerDataBitMask(bearerData);
|
||||
encodedSms = startEncoding(bearerData);
|
||||
|
||||
if( nativeCdmaSmsDestructClientBD() == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
return encodedSms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode SMS.
|
||||
*
|
||||
* @param SmsData the encoded SMS.
|
||||
*
|
||||
* @return an instance of BearerData.
|
||||
*/
|
||||
public static BearerData decodeCdmaSms(byte[] SmsData) {
|
||||
BearerData bearerData;
|
||||
|
||||
if( nativeCdmaSmsConstructClientBD() == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
bearerData = startDecoding(SmsData);
|
||||
|
||||
if( nativeCdmaSmsDestructClientBD() == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
return bearerData;
|
||||
}
|
||||
|
||||
private static void generateBearerDataBitMask(BearerData bearerData) {
|
||||
// initial
|
||||
bearerData.mask = CDMA_SMS_WMS_MASK_BD_NULL;
|
||||
|
||||
// check message type
|
||||
if (bearerData.messageType != 0){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_MSG_ID;
|
||||
}
|
||||
|
||||
// check mUserData
|
||||
if (bearerData.userData != null){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_USER_DATA;
|
||||
}
|
||||
|
||||
// check mTimeStamp
|
||||
if (bearerData.timeStamp != null){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_MC_TIME;
|
||||
}
|
||||
|
||||
// check mNumberOfMessages
|
||||
if (bearerData.numberOfMessages > 0){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS;
|
||||
}
|
||||
|
||||
// check mCallbackNumber
|
||||
if(bearerData.callbackNumber != null){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_CALLBACK;
|
||||
}
|
||||
|
||||
// check DisplayMode
|
||||
if(bearerData.displayMode == BearerData.DISPLAY_DEFAULT ||
|
||||
bearerData.displayMode == BearerData.DISPLAY_IMMEDIATE ||
|
||||
bearerData.displayMode == BearerData.DISPLAY_USER){
|
||||
bearerData.mask |= CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] startEncoding(BearerData bearerData) {
|
||||
int m_id;
|
||||
byte[] m_data;
|
||||
int dataLength;
|
||||
byte[] encodedSms;
|
||||
int nbrOfHeaders = 0;
|
||||
|
||||
if( nativeCdmaSmsSetBearerDataPrimitives(bearerData) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((bearerData.mask & CDMA_SMS_WMS_MASK_BD_USER_DATA) == CDMA_SMS_WMS_MASK_BD_USER_DATA){
|
||||
if( nativeCdmaSmsSetUserData(bearerData.userData) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
if (bearerData.userData.userDataHeader != null){
|
||||
nbrOfHeaders = bearerData.userData.userDataHeader.nbrOfHeaders;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nbrOfHeaders; i++) {
|
||||
m_id = bearerData.userData.userDataHeader.getElements().get(i).getID();
|
||||
m_data = bearerData.userData.userDataHeader.getElements().get(i).getData();
|
||||
dataLength = m_data.length;
|
||||
if( nativeCdmaSmsSetUserDataHeader(m_id, m_data, dataLength, i)
|
||||
== JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((bearerData.mask & CDMA_SMS_WMS_MASK_BD_CALLBACK) == CDMA_SMS_WMS_MASK_BD_CALLBACK) {
|
||||
if( nativeCdmaSmsSetSmsAddress(bearerData.callbackNumber) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* call native method to encode SMS */
|
||||
encodedSms = nativeCdmaSmsEncodeSms();
|
||||
|
||||
return encodedSms;
|
||||
}
|
||||
|
||||
private static BearerData startDecoding(byte[] SmsData) {
|
||||
BearerData bData = new BearerData();
|
||||
byte[] udhData;
|
||||
|
||||
/* call native method to decode SMS */
|
||||
if( nativeCdmaSmsDecodeSms(SmsData) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
if( nativeCdmaSmsGetBearerDataPrimitives(bData) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((bData.mask & CDMA_SMS_WMS_MASK_BD_USER_DATA) == CDMA_SMS_WMS_MASK_BD_USER_DATA) {
|
||||
bData.userData = new UserData();
|
||||
if( nativeCdmaSmsGetUserData(bData.userData) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
|
||||
udhData = nativeCdmaSmsGetUserDataHeader();
|
||||
if (udhData != null) {
|
||||
bData.userData.userDataHeader = SmsHeader.parse(udhData);
|
||||
}
|
||||
}
|
||||
|
||||
if ((bData.mask & CDMA_SMS_WMS_MASK_BD_CALLBACK) == CDMA_SMS_WMS_MASK_BD_CALLBACK) {
|
||||
bData.callbackNumber = new CdmaSmsAddress();
|
||||
if( nativeCdmaSmsGetSmsAddress(bData.callbackNumber) == JNI_CDMA_SMS_FAILURE){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return bData;
|
||||
}
|
||||
|
||||
// native methods
|
||||
|
||||
/**
|
||||
* native method: Allocate memory for clientBD structure
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsConstructClientBD();
|
||||
|
||||
/**
|
||||
* native method: Free memory used for clientBD structure
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsDestructClientBD();
|
||||
|
||||
/**
|
||||
* native method: fill clientBD structure with bearerData primitives
|
||||
*
|
||||
* @param bearerData an instance of BearerData.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsSetBearerDataPrimitives(BearerData bearerData);
|
||||
|
||||
/**
|
||||
* native method: fill bearerData primitives with clientBD variables
|
||||
*
|
||||
* @param bearerData an instance of BearerData.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsGetBearerDataPrimitives(BearerData bearerData);
|
||||
|
||||
/**
|
||||
* native method: fill clientBD.user_data with UserData primitives
|
||||
*
|
||||
* @param userData an instance of UserData.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsSetUserData(UserData userData);
|
||||
|
||||
/**
|
||||
* native method: fill UserData primitives with clientBD.user_data
|
||||
*
|
||||
* @param userData an instance of UserData.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsGetUserData(UserData userData);
|
||||
|
||||
/**
|
||||
* native method: fill clientBD.user_data.headers with UserDataHeader primitives
|
||||
*
|
||||
* @param ID ID of element.
|
||||
* @param data element data.
|
||||
* @param dataLength data length
|
||||
* @param index index of element
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsSetUserDataHeader(
|
||||
int ID, byte[] data, int dataLength, int index);
|
||||
|
||||
/**
|
||||
* native method: fill UserDataHeader primitives with clientBD.user_data.headers
|
||||
*
|
||||
* @return user data headers
|
||||
*/
|
||||
private static native byte[] nativeCdmaSmsGetUserDataHeader();
|
||||
|
||||
/**
|
||||
* native method: fill clientBD.callback with SmsAddress primitives
|
||||
*
|
||||
* @param smsAddr an instance of SmsAddress.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsSetSmsAddress(CdmaSmsAddress smsAddr);
|
||||
|
||||
/**
|
||||
* native method: fill SmsAddress primitives with clientBD.callback
|
||||
*
|
||||
* @param smsAddr an instance of SmsAddress.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsGetSmsAddress(CdmaSmsAddress smsAddr);
|
||||
|
||||
/**
|
||||
* native method: call encoding functions and get encoded SMS
|
||||
*
|
||||
* @return the encoded SMS
|
||||
*/
|
||||
private static native byte[] nativeCdmaSmsEncodeSms();
|
||||
|
||||
/**
|
||||
* native method: call decode functions
|
||||
*
|
||||
* @param encodedSMS encoded SMS.
|
||||
*
|
||||
* @return #JNI_CDMA_SMS_SUCCESS if succeed.
|
||||
* #JNI_CDMA_SMS_FAILURE if fail.
|
||||
*/
|
||||
private static native int nativeCdmaSmsDecodeSms(byte[] encodedSMS);
|
||||
|
||||
/**
|
||||
* Load the shared library to link the native methods.
|
||||
*/
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("cdma_sms_jni");
|
||||
}
|
||||
catch (UnsatisfiedLinkError ule) {
|
||||
System.err.println("WARNING: Could not load cdma_sms_jni.so");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,24 +17,25 @@
|
||||
package com.android.internal.telephony.cdma.sms;
|
||||
|
||||
import com.android.internal.telephony.SmsHeader;
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
public class UserData{
|
||||
|
||||
/**
|
||||
* Supported user data encoding types
|
||||
* User data encoding types
|
||||
* (See 3GPP2 C.R1001-F, v1.0, table 9.1-1)
|
||||
*/
|
||||
public static final int UD_ENCODING_OCTET = 0x00;
|
||||
//public static final int UD_ENCODING_EXTENDED_PROTOCOL = 0x01;
|
||||
public static final int UD_ENCODING_7BIT_ASCII = 0x02;
|
||||
public static final int UD_ENCODING_IA5 = 0x03;
|
||||
public static final int UD_ENCODING_UNICODE_16 = 0x04;
|
||||
//public static final int UD_ENCODING_SHIFT_JIS = 0x05;
|
||||
//public static final int UD_ENCODING_KOREAN = 0x06;
|
||||
//public static final int UD_ENCODING_LATIN_HEBREW = 0x07;
|
||||
//public static final int UD_ENCODING_LATIN = 0x08;
|
||||
public static final int UD_ENCODING_GSM_7BIT_ALPHABET = 0x09;
|
||||
//public static final int UD_ENCODING_GSM_DCS = 0x0A;
|
||||
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_UNICODE_16 = 0x04;
|
||||
//public static final int ENCODING_SHIFT_JIS = 0x05;
|
||||
//public static final int ENCODING_KOREAN = 0x06;
|
||||
//public static final int ENCODING_LATIN_HEBREW = 0x07;
|
||||
//public static final int ENCODING_LATIN = 0x08;
|
||||
public static final int ENCODING_GSM_7BIT_ALPHABET = 0x09;
|
||||
public static final int ENCODING_GSM_DCS = 0x0A;
|
||||
|
||||
/**
|
||||
* Contains the data header of the user data
|
||||
@@ -44,20 +45,37 @@ public class UserData{
|
||||
/**
|
||||
* Contains the data encoding type for the SMS message
|
||||
*/
|
||||
public int userDataEncoding;
|
||||
public int msgEncoding;
|
||||
|
||||
// needed when encoding is IS91 or DCS (not supported yet):
|
||||
//public int messageType;
|
||||
// XXX needed when encoding is IS91 or DCS (not supported yet):
|
||||
public int msgType;
|
||||
|
||||
/**
|
||||
* Number of invalid bits in the last byte of data.
|
||||
*/
|
||||
public int paddingBits;
|
||||
|
||||
public int numFields;
|
||||
|
||||
/**
|
||||
* Contains the user data of a SMS message
|
||||
* (See 3GPP2 C.S0015-B, v2, 4.5.2)
|
||||
*/
|
||||
public byte[] userData;
|
||||
public byte[] payload;
|
||||
public String payloadStr;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("UserData:\n");
|
||||
builder.append(" msgEncoding: " + msgEncoding + "\n");
|
||||
builder.append(" msgType: " + msgType + "\n");
|
||||
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);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user