OSDN Git Service

Add support for sending message with priority, link control and validity period options
authorMengjun Leng <mengju@codeaurora.org>
Mon, 13 Mar 2017 09:08:26 +0000 (17:08 +0800)
committerJayachandran Chinnakkannu <jayachandranc@google.com>
Sat, 24 Feb 2018 01:14:03 +0000 (01:14 +0000)
1. Added support for message priority(indicates the priority of a
   SMS to the network in the PDU) in 3gpp2
2. Added support for link control(indicates whether network can
   expect more messages or not so it can decide whether to retain
   the radio link or not) while sending multiple messages
3. Added support for validity period(indicates how much time the
   SMS is valid at the SMSC) support in 3gpp
4. Amended UT test cases for API changes and add UT validity period
   test case

Test: Verfied sending short SMS, long SMS, MMS, SMS with emoji on
      live network

Bug: 34962629

telephony/java/android/telephony/SmsManager.java
telephony/java/android/telephony/SmsMessage.java
telephony/java/com/android/internal/telephony/ISms.aidl
telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
telephony/java/com/android/internal/telephony/gsm/SmsMessage.java

index 9a45e7b..b44f830 100644 (file)
@@ -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);
                     }
index 6e083c2..ea74bac 100644 (file)
@@ -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}
index fe37531..a4eb424 100644 (file)
@@ -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
index 7a53ef6..14c5f4b 100644 (file)
@@ -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 &amp; 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;
 
index 1ca19e0..4f5bfa9 100644 (file)
@@ -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 &amp; port
      *
      * @param scAddress Service Centre address. null == use default