diff options
5 files changed, 539 insertions, 6 deletions
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 9a45e7b9cc36..b44f830c45fe 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -391,6 +391,112 @@ public final class SmsManager { } /** + * Send a text based SMS with messaging options. + * + * @param destinationAddress the address to send the message to + * @param scAddress is the service center address or null to use + * the current default SMSC + * @param text the body of the message to send + * @param sentIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is successfully sent, or failed. + * The result code will be <code>Activity.RESULT_OK</code> for success, + * or one of these errors:<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include + * the extra "errorCode" containing a radio technology specific value, + * generally only useful for troubleshooting.<br> + * The per-application based SMS control checks sentIntent. If sentIntent + * is NULL the caller will be checked against all unknown applications, + * which cause smaller number of SMS to be sent in checking period. + * @param deliveryIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is delivered to the recipient. The + * raw pdu of the status report is in the extended data ("pdu"). + * @param priority Priority level of the message + * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 + * --------------------------------- + * PRIORITY | Level of Priority + * --------------------------------- + * '00' | Normal + * '01' | Interactive + * '10' | Urgent + * '11' | Emergency + * ---------------------------------- + * Any Other values included Negative considered as Invalid Priority Indicator of the message. + * @param expectMore is a boolean to indicate the sending messages through same link or not. + * @param validityPeriod Validity Period of the message in mins. + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * Validity Period(Minimum) -> 5 mins + * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). + * Any Other values included Negative considered as Invalid Validity Period of the message. + * + * @throws IllegalArgumentException if destinationAddress or text are empty + * {@hide} + */ + public void sendTextMessage( + String destinationAddress, String scAddress, String text, + PendingIntent sentIntent, PendingIntent deliveryIntent, + int priority, boolean expectMore, int validityPeriod) { + sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, + true /* persistMessage*/, priority, expectMore, validityPeriod); + } + + private void sendTextMessageInternal( + String destinationAddress, String scAddress, String text, + PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, + int priority, boolean expectMore, int validityPeriod) { + if (TextUtils.isEmpty(destinationAddress)) { + throw new IllegalArgumentException("Invalid destinationAddress"); + } + + if (TextUtils.isEmpty(text)) { + throw new IllegalArgumentException("Invalid message body"); + } + + if (priority < 0x00 || priority > 0x03) { + throw new IllegalArgumentException("Invalid priority"); + } + + if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { + throw new IllegalArgumentException("Invalid validity period"); + } + + try { + ISms iccISms = getISmsServiceOrThrow(); + if (iccISms != null) { + iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(), + ActivityThread.currentPackageName(), destinationAddress, scAddress, text, + sentIntent, deliveryIntent, persistMessage, priority, expectMore, + validityPeriod); + } + } catch (RemoteException ex) { + // ignore it + } + } + + /** + * Send a text based SMS without writing it into the SMS Provider. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier + * privileges. + * </p> + * + * @see #sendTextMessage(String, String, String, PendingIntent, + * PendingIntent, int, boolean, int) + * @hide + */ + public void sendTextMessageWithoutPersisting( + String destinationAddress, String scAddress, String text, + PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, + boolean expectMore, int validityPeriod) { + sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, + false /* persistMessage */, priority, expectMore, validityPeriod); + } + + /** + * * Inject an SMS PDU into the android application framework. * * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier @@ -545,6 +651,140 @@ public final class SmsManager { } /** + * Send a multi-part text based SMS with messaging options. The callee should have already + * divided the message into correctly sized parts by calling + * <code>divideMessage</code>. + * + * <p class="note"><strong>Note:</strong> Using this method requires that your app has the + * {@link android.Manifest.permission#SEND_SMS} permission.</p> + * + * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if + * <em>and only if</em> an app is not selected as the default SMS app, the system automatically + * writes messages sent using this method to the SMS Provider (the default SMS app is always + * responsible for writing its sent messages to the SMS Provider). For information about + * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> + * + * @param destinationAddress the address to send the message to + * @param scAddress is the service center address or null to use + * the current default SMSC + * @param parts an <code>ArrayList</code> of strings that, in order, + * comprise the original message + * @param sentIntents if not null, an <code>ArrayList</code> of + * <code>PendingIntent</code>s (one for each message part) that is + * broadcast when the corresponding message part has been sent. + * The result code will be <code>Activity.RESULT_OK</code> for success, + * or one of these errors:<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include + * the extra "errorCode" containing a radio technology specific value, + * generally only useful for troubleshooting.<br> + * The per-application based SMS control checks sentIntent. If sentIntent + * is NULL the caller will be checked against all unknown applications, + * which cause smaller number of SMS to be sent in checking period. + * @param deliveryIntents if not null, an <code>ArrayList</code> of + * <code>PendingIntent</code>s (one for each message part) that is + * broadcast when the corresponding message part has been delivered + * to the recipient. The raw pdu of the status report is in the + * extended data ("pdu"). + * @param priority Priority level of the message + * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 + * --------------------------------- + * PRIORITY | Level of Priority + * --------------------------------- + * '00' | Normal + * '01' | Interactive + * '10' | Urgent + * '11' | Emergency + * ---------------------------------- + * Any Other values included Negative considered as Invalid Priority Indicator of the message. + * @param expectMore is a boolean to indicate the sending messages through same link or not. + * @param validityPeriod Validity Period of the message in mins. + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * Validity Period(Minimum) -> 5 mins + * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). + * Any Other values included Negative considered as Invalid Validity Period of the message. + * + * @throws IllegalArgumentException if destinationAddress or data are empty + * {@hide} + */ + public void sendMultipartTextMessage( + String destinationAddress, String scAddress, ArrayList<String> parts, + ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, + int priority, boolean expectMore, int validityPeriod) { + sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, + deliveryIntents, true /* persistMessage*/); + } + + private void sendMultipartTextMessageInternal( + String destinationAddress, String scAddress, List<String> parts, + List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, + boolean persistMessage, int priority, boolean expectMore, int validityPeriod) { + if (TextUtils.isEmpty(destinationAddress)) { + throw new IllegalArgumentException("Invalid destinationAddress"); + } + if (parts == null || parts.size() < 1) { + throw new IllegalArgumentException("Invalid message body"); + } + + if (priority < 0x00 || priority > 0x03) { + throw new IllegalArgumentException("Invalid priority"); + } + + if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { + throw new IllegalArgumentException("Invalid validity period"); + } + + if (parts.size() > 1) { + try { + ISms iccISms = getISmsServiceOrThrow(); + if (iccISms != null) { + iccISms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), + ActivityThread.currentPackageName(), destinationAddress, scAddress, + parts, sentIntents, deliveryIntents, persistMessage, priority, + expectMore, validityPeriod); + } + } catch (RemoteException ex) { + // ignore it + } + } else { + PendingIntent sentIntent = null; + PendingIntent deliveryIntent = null; + if (sentIntents != null && sentIntents.size() > 0) { + sentIntent = sentIntents.get(0); + } + if (deliveryIntents != null && deliveryIntents.size() > 0) { + deliveryIntent = deliveryIntents.get(0); + } + sendTextMessageInternal(destinationAddress, scAddress, parts.get(0), + sentIntent, deliveryIntent, persistMessage, priority, expectMore, + validityPeriod); + } + } + + /** + * Send a multi-part text based SMS without writing it into the SMS Provider. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier + * privileges. + * </p> + * + * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, + * ArrayList, int, boolean, int) + * @hide + **/ + public void sendMultipartTextMessageWithoutPersisting( + String destinationAddress, String scAddress, List<String> parts, + List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, + int priority, boolean expectMore, int validityPeriod) { + sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, + deliveryIntents, false /* persistMessage*/, priority, expectMore, + validityPeriod); + } + + /** * Send a data based SMS to a specific application port. * * <p class="note"><strong>Note:</strong> Using this method requires that your app has the @@ -1007,7 +1247,7 @@ public final class SmsManager { * <code>getAllMessagesFromIcc</code> * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. */ - private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { + private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); if (records != null) { int count = records.size(); @@ -1015,7 +1255,8 @@ public final class SmsManager { SmsRawData data = records.get(i); // List contains all records, including "free" records (null) if (data != null) { - SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); + SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes(), + getSubscriptionId()); if (sms != null) { messages.add(sms); } diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index 6e083c21cd5b..ea74bac7208f 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -268,6 +268,31 @@ public class SmsMessage { } /** + * Create an SmsMessage from an SMS EF record. + * + * @param index Index of SMS record. This should be index in ArrayList + * returned by SmsManager.getAllMessagesFromSim + 1. + * @param data Record data. + * @param subId Subscription Id of the SMS + * @return An SmsMessage representing the record. + * + * @hide + */ + public static SmsMessage createFromEfRecord(int index, byte[] data, int subId) { + SmsMessageBase wrappedMessage; + + if (isCdmaVoice(subId)) { + wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord( + index, data); + } else { + wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord( + index, data); + } + + return wrappedMessage != null ? new SmsMessage(wrappedMessage) : null; + } + + /** * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the * length in bytes (not hex chars) less the SMSC header * @@ -827,6 +852,7 @@ public class SmsMessage { int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(subId); return (PHONE_TYPE_CDMA == activePhone); } + /** * Decide if the carrier supports long SMS. * {@hide} diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index fe37531c0611..a4eb424ab66e 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -187,6 +187,57 @@ interface ISms { in PendingIntent deliveryIntent, in boolean persistMessage); /** + * Send an SMS with options using Subscription Id. + * + * @param subId the subId on which the SMS has to be sent. + * @param destAddr the address to send the message to + * @param scAddr the SMSC to send the message through, or NULL for the + * default SMSC + * @param text the body of the message to send + * @param sentIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is sucessfully sent, or failed. + * The result code will be <code>Activity.RESULT_OK<code> for success, + * or one of these errors:<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include + * the extra "errorCode" containing a radio technology specific value, + * generally only useful for troubleshooting.<br> + * The per-application based SMS control checks sentIntent. If sentIntent + * is NULL the caller will be checked against all unknown applications, + * which cause smaller number of SMS to be sent in checking period. + * @param deliveryIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is delivered to the recipient. The + * raw pdu of the status report is in the extended data ("pdu"). + * @param persistMessageForNonDefaultSmsApp whether the sent message should + * be automatically persisted in the SMS db. It only affects messages sent + * by a non-default SMS app. Currently only the carrier app can set this + * parameter to false to skip auto message persistence. + * @param priority Priority level of the message + * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 + * --------------------------------- + * PRIORITY | Level of Priority + * --------------------------------- + * '00' | Normal + * '01' | Interactive + * '10' | Urgent + * '11' | Emergency + * ---------------------------------- + * Any Other values included Negative considered as Invalid Priority Indicator of the message. + * @param expectMore is a boolean to indicate the sending message is multi segmented or not. + * @param validityPeriod Validity Period of the message in mins. + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * Validity Period(Minimum) -> 5 mins + * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). + * Any Other values included Negative considered as Invalid Validity Period of the message. + */ + void sendTextForSubscriberWithOptions(in int subId, String callingPkg, in String destAddr, + in String scAddr, in String text, in PendingIntent sentIntent, + in PendingIntent deliveryIntent, in boolean persistMessageForNonDefaultSmsApp, + in int priority, in boolean expectMore, in int validityPeriod); + + /** * Inject an SMS PDU into the android platform. * * @param subId the subId on which the SMS has to be injected. @@ -234,6 +285,56 @@ interface ISms { in List<PendingIntent> deliveryIntents, in boolean persistMessageForNonDefaultSmsApp); /** + * Send a multi-part text based SMS with options using Subscription Id. + * + * @param subId the subId on which the SMS has to be sent. + * @param destinationAddress the address to send the message to + * @param scAddress is the service center address or null to use + * the current default SMSC + * @param parts an <code>ArrayList</code> of strings that, in order, + * comprise the original message + * @param sentIntents if not null, an <code>ArrayList</code> of + * <code>PendingIntent</code>s (one for each message part) that is + * broadcast when the corresponding message part has been sent. + * The result code will be <code>Activity.RESULT_OK<code> for success, + * or one of these errors: + * <code>RESULT_ERROR_GENERIC_FAILURE</code> + * <code>RESULT_ERROR_RADIO_OFF</code> + * <code>RESULT_ERROR_NULL_PDU</code>. + * @param deliveryIntents if not null, an <code>ArrayList</code> of + * <code>PendingIntent</code>s (one for each message part) that is + * broadcast when the corresponding message part has been delivered + * to the recipient. The raw pdu of the status report is in the + * extended data ("pdu"). + * @param persistMessageForNonDefaultSmsApp whether the sent message should + * be automatically persisted in the SMS db. It only affects messages sent + * by a non-default SMS app. Currently only the carrier app can set this + * parameter to false to skip auto message persistence. + * @param priority Priority level of the message + * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 + * --------------------------------- + * PRIORITY | Level of Priority + * --------------------------------- + * '00' | Normal + * '01' | Interactive + * '10' | Urgent + * '11' | Emergency + * ---------------------------------- + * Any Other values included Negative considered as Invalid Priority Indicator of the message. + * @param expectMore is a boolean to indicate the sending message is multi segmented or not. + * @param validityPeriod Validity Period of the message in mins. + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * Validity Period(Minimum) -> 5 mins + * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). + * Any Other values included Negative considered as Invalid Validity Period of the message. + */ + void sendMultipartTextForSubscriberWithOptions(in int subId, String callingPkg, + in String destinationAddress, in String scAddress, in List<String> parts, + in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents, + in boolean persistMessageForNonDefaultSmsApp, in int priority, in boolean expectMore, + in int validityPeriod); + + /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier and RAN type. The RAN type specify this message ID * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 7a53ef63e2a8..14c5f4bebebb 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -99,6 +99,15 @@ public class SmsMessage extends SmsMessageBase { private static final int RETURN_NO_ACK = 0; private static final int RETURN_ACK = 1; + /** + * Supported priority modes for CDMA SMS messages + * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1) + */ + private static final int PRIORITY_NORMAL = 0x0; + private static final int PRIORITY_INTERACTIVE = 0x1; + private static final int PRIORITY_URGENT = 0x2; + private static final int PRIORITY_EMERGENCY = 0x3; + private SmsEnvelope mEnvelope; private BearerData mBearerData; @@ -211,6 +220,26 @@ public class SmsMessage extends SmsMessageBase { */ public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader) { + return getSubmitPdu(scAddr, destAddr, message, statusReportRequested, smsHeader, -1); + } + + /** + * Get an SMS-SUBMIT PDU for a destination address and a message + * + * @param scAddr Service Centre address. Null means use default. + * @param destAddr Address of the recipient. + * @param message String representation of the message payload. + * @param statusReportRequested Indicates whether a report is requested for this message. + * @param smsHeader Array containing the data for the User Data Header, preceded + * by the Element Identifiers. + * @param priority Priority level of the message + * @return a <code>SubmitPdu</code> containing the encoded SC + * address, if applicable, and the encoded message. + * Returns null on encode error. + * @hide + */ + public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, + boolean statusReportRequested, SmsHeader smsHeader, int priority) { /** * TODO(cleanup): Do we really want silent failure like this? @@ -224,7 +253,7 @@ public class SmsMessage extends SmsMessageBase { UserData uData = new UserData(); uData.payloadStr = message; uData.userDataHeader = smsHeader; - return privateGetSubmitPdu(destAddr, statusReportRequested, uData); + return privateGetSubmitPdu(destAddr, statusReportRequested, uData, priority); } /** @@ -282,6 +311,22 @@ public class SmsMessage extends SmsMessageBase { } /** + * Get an SMS-SUBMIT PDU for a data message to a destination address & port + * + * @param destAddr the address of the destination for the message + * @param userData the data for the message + * @param statusReportRequested Indicates whether a report is requested for this message. + * @param priority Priority level of the message + * @return a <code>SubmitPdu</code> containing the encoded SC + * address, if applicable, and the encoded message. + * Returns null on encode error. + */ + public static SubmitPdu getSubmitPdu(String destAddr, UserData userData, + boolean statusReportRequested, int priority) { + return privateGetSubmitPdu(destAddr, statusReportRequested, userData, priority); + } + + /** * Note: This function is a GSM specific functionality which is not supported in CDMA mode. */ @Override @@ -764,6 +809,15 @@ public class SmsMessage extends SmsMessageBase { */ private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, UserData userData) { + return privateGetSubmitPdu(destAddrStr, statusReportRequested, userData, -1); + } + + /** + * Creates BearerData and Envelope from parameters for a Submit SMS. + * @return byte stream for SubmitPdu. + */ + private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, + UserData userData, int priority) { /** * TODO(cleanup): give this function a more meaningful name. @@ -792,6 +846,10 @@ public class SmsMessage extends SmsMessageBase { bearerData.userAckReq = false; bearerData.readAckReq = false; bearerData.reportReq = false; + if (priority >= PRIORITY_NORMAL && priority <= PRIORITY_EMERGENCY) { + bearerData.priorityIndicatorSet = true; + bearerData.priority = priority; + } bearerData.userData = userData; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 1ca19e01d6c8..4f5bfa919135 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -89,6 +89,18 @@ public class SmsMessage extends SmsMessageBase { private int mVoiceMailCount = 0; + private static final int VALIDITY_PERIOD_FORMAT_NONE = 0x00; + private static final int VALIDITY_PERIOD_FORMAT_ENHANCED = 0x01; + private static final int VALIDITY_PERIOD_FORMAT_RELATIVE = 0x02; + private static final int VALIDITY_PERIOD_FORMAT_ABSOLUTE = 0x03; + + //Validity Period min - 5 mins + private static final int VALIDITY_PERIOD_MIN = 5; + //Validity Period max - 63 weeks + private static final int VALIDITY_PERIOD_MAX = 635040; + + private static final int INVALID_VALIDITY_PERIOD = -1; + public static class SubmitPdu extends SubmitPduBase { } @@ -202,6 +214,45 @@ public class SmsMessage extends SmsMessageBase { } /** + * Get Encoded Relative Validty Period Value from Validity period in mins. + * + * @param validityPeriod Validity period in mins. + * + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * ||relValidityPeriod (TP-VP) || || validityPeriod || + * + * 0 to 143 ---> (TP-VP + 1) x 5 minutes + * + * 144 to 167 ---> 12 hours + ((TP-VP -143) x 30 minutes) + * + * 168 to 196 ---> (TP-VP - 166) x 1 day + * + * 197 to 255 ---> (TP-VP - 192) x 1 week + * + * @return relValidityPeriod Encoded Relative Validity Period Value. + * @hide + */ + public static int getRelativeValidityPeriod(int validityPeriod) { + int relValidityPeriod = INVALID_VALIDITY_PERIOD; + + if (validityPeriod < VALIDITY_PERIOD_MIN || validityPeriod > VALIDITY_PERIOD_MAX) { + Rlog.e(LOG_TAG,"Invalid Validity Period" + validityPeriod); + return relValidityPeriod; + } + + if (validityPeriod <= 720) { + relValidityPeriod = (validityPeriod / 5) - 1; + } else if (validityPeriod <= 1440) { + relValidityPeriod = ((validityPeriod - 720) / 30) + 143; + } else if (validityPeriod <= 43200) { + relValidityPeriod = (validityPeriod / 1440) + 166; + } else if (validityPeriod <= 635040) { + relValidityPeriod = (validityPeriod / 10080) + 192; + } + return relValidityPeriod; + } + + /** * Get an SMS-SUBMIT PDU for a destination address and a message * * @param scAddress Service Centre address. Null means use default. @@ -236,6 +287,29 @@ public class SmsMessage extends SmsMessageBase { String destinationAddress, String message, boolean statusReportRequested, byte[] header, int encoding, int languageTable, int languageShiftTable) { + return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, + header, encoding, languageTable, languageShiftTable, -1); + } + + /** + * Get an SMS-SUBMIT PDU for a destination address and a message using the + * specified encoding. + * + * @param scAddress Service Centre address. Null means use default. + * @param encoding Encoding defined by constants in + * com.android.internal.telephony.SmsConstants.ENCODING_* + * @param languageTable + * @param languageShiftTable + * @param validityPeriod Validity Period of the message in Minutes. + * @return a <code>SubmitPdu</code> containing the encoded SC + * address, if applicable, and the encoded message. + * Returns null on encode error. + * @hide + */ + public static SubmitPdu getSubmitPdu(String scAddress, + String destinationAddress, String message, + boolean statusReportRequested, byte[] header, int encoding, + int languageTable, int languageShiftTable, int validityPeriod) { // Perform null parameter checks. if (message == null || destinationAddress == null) { @@ -272,8 +346,19 @@ public class SmsMessage extends SmsMessageBase { } SubmitPdu ret = new SubmitPdu(); - // MTI = SMS-SUBMIT, UDHI = header != null - byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00)); + + int validityPeriodFormat = VALIDITY_PERIOD_FORMAT_NONE; + int relativeValidityPeriod = INVALID_VALIDITY_PERIOD; + + // TP-Validity-Period-Format (TP-VPF) in 3GPP TS 23.040 V6.8.1 section 9.2.3.3 + //bit 4:3 = 10 - TP-VP field present - relative format + if((relativeValidityPeriod = getRelativeValidityPeriod(validityPeriod)) >= 0) { + validityPeriodFormat = VALIDITY_PERIOD_FORMAT_RELATIVE; + } + + byte mtiByte = (byte)(0x01 | (validityPeriodFormat << 0x03) | + (header != null ? 0x40 : 0x00)); + ByteArrayOutputStream bo = getSubmitPduHead( scAddress, destinationAddress, mtiByte, statusReportRequested, ret); @@ -338,7 +423,11 @@ public class SmsMessage extends SmsMessageBase { bo.write(0x08); } - // (no TP-Validity-Period) + if (validityPeriodFormat == VALIDITY_PERIOD_FORMAT_RELATIVE) { + // ( TP-Validity-Period - relative format) + bo.write(relativeValidityPeriod); + } + bo.write(userData, 0, userData.length); ret.encodedMessage = bo.toByteArray(); return ret; @@ -388,6 +477,24 @@ public class SmsMessage extends SmsMessageBase { } /** + * Get an SMS-SUBMIT PDU for a destination address and a message + * + * @param scAddress Service Centre address. Null means use default. + * @param destinationAddress the address of the destination for the message + * @param statusReportRequested staus report of the message Requested + * @param validityPeriod Validity Period of the message in Minutes. + * @return a <code>SubmitPdu</code> containing the encoded SC + * address, if applicable, and the encoded message. + * Returns null on encode error. + */ + public static SubmitPdu getSubmitPdu(String scAddress, + String destinationAddress, String message, + boolean statusReportRequested, int validityPeriod) { + return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, + null, ENCODING_UNKNOWN, 0, 0, validityPeriod); + } + + /** * Get an SMS-SUBMIT PDU for a data message to a destination address & port * * @param scAddress Service Centre address. null == use default |