Merge "CatService: OPEN_CHANNEL p-cmd to send event confirmation and not T.R" into klp-dev
diff --git a/src/java/android/provider/Telephony.java b/src/java/android/provider/Telephony.java
index d6159df..8fdd49c 100644
--- a/src/java/android/provider/Telephony.java
+++ b/src/java/android/provider/Telephony.java
@@ -519,6 +519,11 @@
             public static final int RESULT_SMS_UNSUPPORTED = 4;
 
             /**
+             * Set by BroadcastReceiver. Indicates the duplicated imcoming message.
+             */
+            public static final int RESULT_SMS_DUPLICATED = 5;
+
+            /**
              * Broadcast Action: A new text based SMS message has been received
              * by the device. The intent will have the following extra
              * values:</p>
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index e75f124..d243493 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -500,7 +500,7 @@
             }
 
             tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
-                    is3gpp2());
+                    is3gpp2(), false);
         } else {
             // Create a tracker for this message segment.
             SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
@@ -509,7 +509,7 @@
 
             tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
                     is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber,
-                    concatRef.seqNumber, concatRef.msgCount);
+                    concatRef.seqNumber, concatRef.msgCount, false);
         }
 
         if (VDBG) log("created tracker: " + tracker);
@@ -520,16 +520,21 @@
      * Helper to add the tracker to the raw table and then send a message to broadcast it, if
      * successful. Returns the SMS intent status to return to the SMSC.
      * @param tracker the tracker to save to the raw table and then deliver
-     * @return {@link Intents#RESULT_SMS_HANDLED} or {@link Intents#RESULT_SMS_OUT_OF_MEMORY}
+     * @return {@link Intents#RESULT_SMS_HANDLED} or {@link Intents#RESULT_SMS_GENERIC_ERROR}
+     * or {@link Intents#RESULT_SMS_DUPLICATED}
      */
     protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker) {
-        if (addTrackerToRawTable(tracker)) {
-            // send as an ordered broadcast
+        switch(addTrackerToRawTable(tracker)) {
+        case Intents.RESULT_SMS_HANDLED:
             sendMessage(EVENT_BROADCAST_SMS, tracker);
             return Intents.RESULT_SMS_HANDLED;
-        } else {
-            // failed to save PDU to raw table: reject message
-            return Intents.RESULT_SMS_OUT_OF_MEMORY;
+
+        case Intents.RESULT_SMS_DUPLICATED:
+            return Intents.RESULT_SMS_HANDLED;
+
+        case Intents.RESULT_SMS_GENERIC_ERROR:
+        default:
+            return Intents.RESULT_SMS_GENERIC_ERROR;
         }
     }
 
@@ -670,7 +675,7 @@
      * @param tracker the tracker to add to the raw table
      * @return true on success; false on failure to write to database
      */
-    private boolean addTrackerToRawTable(InboundSmsTracker tracker) {
+    private int addTrackerToRawTable(InboundSmsTracker tracker) {
         if (tracker.getMessageCount() != 1) {
             // check for duplicate message segments
             Cursor cursor = null;
@@ -705,12 +710,12 @@
                         loge("Warning: dup message segment PDU of length " + pdu.length
                                 + " is different from existing PDU of length " + oldPdu.length);
                     }
-                    return false;   // reject message
+                    return Intents.RESULT_SMS_DUPLICATED;   // reject message
                 }
                 cursor.close();
             } catch (SQLException e) {
                 loge("Can't access multipart SMS database", e);
-                return false;       // reject message
+                return Intents.RESULT_SMS_GENERIC_ERROR;    // reject message
             } finally {
                 if (cursor != null) {
                     cursor.close();
@@ -730,10 +735,10 @@
                 // set the delete selection args for single-part message
                 tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)});
             }
-            return true;
+            return Intents.RESULT_SMS_HANDLED;
         } catch (Exception e) {
             loge("error parsing URI for new row: " + newUri, e);
-            return false;
+            return Intents.RESULT_SMS_GENERIC_ERROR;
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/InboundSmsTracker.java b/src/java/com/android/internal/telephony/InboundSmsTracker.java
index 6043355..693d9fa 100644
--- a/src/java/com/android/internal/telephony/InboundSmsTracker.java
+++ b/src/java/com/android/internal/telephony/InboundSmsTracker.java
@@ -36,6 +36,7 @@
     private final long mTimestamp;
     private final int mDestPort;
     private final boolean mIs3gpp2;
+    private final boolean mIs3gpp2WapPdu;
 
     // Fields for concatenating multi-part SMS messages
     private final String mAddress;
@@ -56,6 +57,9 @@
     /** Destination port flag bit to indicate 3GPP2 format message. */
     private static final int DEST_PORT_FLAG_3GPP2 = (1 << 18);
 
+    /** Destination port flag bit to indicate 3GPP2 format WAP message. */
+    private static final int DEST_PORT_FLAG_3GPP2_WAP_PDU = (1 << 19);
+
     /** Destination port mask (16-bit unsigned value on GSM and CDMA). */
     private static final int DEST_PORT_MASK = 0xffff;
 
@@ -65,12 +69,15 @@
      * @param timestamp the message timestamp
      * @param destPort the destination port
      * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
+     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
      */
-    InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2) {
+    InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
+            boolean is3gpp2WapPdu) {
         mPdu = pdu;
         mTimestamp = timestamp;
         mDestPort = destPort;
         mIs3gpp2 = is3gpp2;
+        mIs3gpp2WapPdu = is3gpp2WapPdu;
         // fields for multi-part SMS
         mAddress = null;
         mReferenceNumber = -1;
@@ -93,13 +100,16 @@
      * @param referenceNumber the concatenated reference number
      * @param sequenceNumber the sequence number of this segment (0-based)
      * @param messageCount the total number of segments
+     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
      */
     public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
-            String address, int referenceNumber, int sequenceNumber, int messageCount) {
+            String address, int referenceNumber, int sequenceNumber, int messageCount,
+            boolean is3gpp2WapPdu) {
         mPdu = pdu;
         mTimestamp = timestamp;
         mDestPort = destPort;
         mIs3gpp2 = is3gpp2;
+        mIs3gpp2WapPdu = is3gpp2WapPdu;
         // fields for multi-part SMS
         mAddress = address;
         mReferenceNumber = referenceNumber;
@@ -118,6 +128,7 @@
         if (cursor.isNull(InboundSmsHandler.DESTINATION_PORT_COLUMN)) {
             mDestPort = -1;
             mIs3gpp2 = isCurrentFormat3gpp2;
+            mIs3gpp2WapPdu = false;
         } else {
             int destPort = cursor.getInt(InboundSmsHandler.DESTINATION_PORT_COLUMN);
             if ((destPort & DEST_PORT_FLAG_3GPP) != 0) {
@@ -127,6 +138,7 @@
             } else {
                 mIs3gpp2 = isCurrentFormat3gpp2;
             }
+            mIs3gpp2WapPdu = ((destPort & DEST_PORT_FLAG_3GPP2_WAP_PDU) != 0);
             mDestPort = getRealDestPort(destPort);
         }
 
@@ -179,6 +191,9 @@
         } else {
             destPort |= DEST_PORT_FLAG_3GPP;
         }
+        if (mIs3gpp2WapPdu) {
+            destPort |= DEST_PORT_FLAG_3GPP2_WAP_PDU;
+        }
         values.put("destination_port", destPort);
         if (mAddress != null) {
             values.put("address", mAddress);
@@ -252,17 +267,13 @@
         return mIs3gpp2 ? SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
     }
 
-    boolean isWapPush() {
-        return (mDestPort == SmsHeader.PORT_WAP_PUSH);
-    }
-
     /**
-     * Sequence numbers for concatenated messages start at 1. The exception is CDMA WAP push
+     * Sequence numbers for concatenated messages start at 1. The exception is CDMA WAP PDU
      * messages, which use a 0-based index.
      * @return the offset to use to convert between mIndex and the sequence number
      */
     int getIndexOffset() {
-        return (mIs3gpp2 && isWapPush()) ? 0 : 1;
+        return (mIs3gpp2 && mIs3gpp2WapPdu) ? 0 : 1;
     }
 
     String getAddress() {
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
index 28d091f..99e790f 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
@@ -305,7 +305,7 @@
         System.arraycopy(pdu, index, userData, 0, pdu.length - index);
 
         InboundSmsTracker tracker = new InboundSmsTracker(userData, timestamp, destinationPort,
-                true, address, referenceNumber, segment, totalSegments);
+                true, address, referenceNumber, segment, totalSegments, true);
 
         return addTrackerToRawTableAndSendMessage(tracker);
     }