Loading src/java/com/android/internal/telephony/InboundSmsHandler.java +85 −43 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.LocalLog; import android.util.Pair; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -99,13 +100,21 @@ import java.util.Map; */ public abstract class InboundSmsHandler extends StateMachine { protected static final boolean DBG = true; private static final boolean VDBG = false; // STOPSHIP if true, logs user data protected static final boolean VDBG = false; // STOPSHIP if true, logs user data /** Query projection for checking for duplicate message segments. */ private static final String[] PDU_PROJECTION = { "pdu" private static final String[] PDU_DELETED_FLAG_PROJECTION = { "pdu", "deleted" }; /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */ private static final Map<Integer, Integer> PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING = new HashMap<Integer, Integer>() {{ put(PDU_COLUMN, 0); put(DELETED_FLAG_COLUMN, 1); }}; /** Query projection for combining concatenated message segments. */ private static final String[] PDU_SEQUENCE_PORT_PROJECTION = { "pdu", Loading Loading @@ -133,6 +142,7 @@ public abstract class InboundSmsHandler extends StateMachine { public static final int ID_COLUMN = 7; public static final int MESSAGE_BODY_COLUMN = 8; public static final int DISPLAY_ADDRESS_COLUMN = 9; public static final int DELETED_FLAG_COLUMN = 10; public static final String SELECT_BY_ID = "_id=?"; Loading Loading @@ -1183,55 +1193,47 @@ public abstract class InboundSmsHandler extends StateMachine { } /** * Function to check if message should be dropped because same message has already been * received. In certain cases it checks for similar messages instead of exact same (cases where * keeping both messages in db can cause ambiguity) * @return true if duplicate exists, false otherwise * Function to detect and handle duplicate messages. If the received message should replace an * existing message in the raw db, this function deletes the existing message. If an existing * message takes priority (for eg, existing message has already been broadcast), then this new * message should be dropped. * @return true if the message represented by the passed in tracker should be dropped, * false otherwise */ private boolean duplicateExists(InboundSmsTracker tracker) throws SQLException { String address = tracker.getAddress(); // convert to strings for query String refNumber = Integer.toString(tracker.getReferenceNumber()); String count = Integer.toString(tracker.getMessageCount()); // sequence numbers are 1-based except for CDMA WAP, which is 0-based int sequence = tracker.getSequenceNumber(); String seqNumber = Integer.toString(sequence); String date = Long.toString(tracker.getTimestamp()); String messageBody = tracker.getMessageBody(); String where; if (tracker.getMessageCount() == 1) { where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "date=? AND message_body=?"; } else { // for multi-part messages, deduping should also be done against undeleted // segments that can cause ambiguity when contacenating the segments, that is, // segments with same address, reference_number, count, sequence and message type. where = tracker.getQueryForMultiPartDuplicates(); } private boolean checkAndHandleDuplicate(InboundSmsTracker tracker) throws SQLException { Pair<String, String[]> exactMatchQuery = tracker.getExactMatchDupDetectQuery(); Cursor cursor = null; try { // Check for duplicate message segments cursor = mResolver.query(sRawUri, PDU_PROJECTION, where, new String[]{address, refNumber, count, seqNumber, date, messageBody}, null); cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, exactMatchQuery.first, exactMatchQuery.second, null); // moveToNext() returns false if no duplicates were found if (cursor != null && cursor.moveToNext()) { loge("Discarding duplicate message segment, refNumber=" + refNumber + " seqNumber=" + seqNumber + " count=" + count); if (VDBG) { loge("address=" + address + " date=" + date + " messageBody=" + messageBody); } String oldPduString = cursor.getString(PDU_COLUMN); byte[] pdu = tracker.getPdu(); byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); if (!Arrays.equals(oldPdu, tracker.getPdu())) { loge("Warning: dup message segment PDU of length " + pdu.length + " is different from existing PDU of length " + oldPdu.length); if (cursor.getCount() != 1) { loge("Exact match query returned " + cursor.getCount() + " rows"); } // if the exact matching row is marked deleted, that means this message has already // been received and processed, and can be discarded as dup if (cursor.getInt( PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(DELETED_FLAG_COLUMN)) == 1) { loge("Discarding duplicate message segment: " + tracker); logDupPduMismatch(cursor, tracker); return true; // reject message } else { // exact match duplicate is not marked deleted. If it is a multi-part segment, // the code below for inexact match will take care of it. If it is a single // part message, handle it here. if (tracker.getMessageCount() == 1) { // delete the old message segment permanently deleteFromRawTable(exactMatchQuery.first, exactMatchQuery.second, DELETE_PERMANENTLY); loge("Replacing duplicate message: " + tracker); logDupPduMismatch(cursor, tracker); } } } } finally { if (cursor != null) { Loading @@ -1239,9 +1241,49 @@ public abstract class InboundSmsHandler extends StateMachine { } } // The code above does an exact match. Multi-part message segments need an additional check // on top of that: if there is a message segment that conflicts this new one (may not be an // exact match), replace the old message segment with this one. if (tracker.getMessageCount() > 1) { Pair<String, String[]> inexactMatchQuery = tracker.getInexactMatchDupDetectQuery(); cursor = null; try { // Check for duplicate message segments cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, inexactMatchQuery.first, inexactMatchQuery.second, null); // moveToNext() returns false if no duplicates were found if (cursor != null && cursor.moveToNext()) { if (cursor.getCount() != 1) { loge("Inexact match query returned " + cursor.getCount() + " rows"); } // delete the old message segment permanently deleteFromRawTable(inexactMatchQuery.first, inexactMatchQuery.second, DELETE_PERMANENTLY); loge("Replacing duplicate message segment: " + tracker); logDupPduMismatch(cursor, tracker); } } finally { if (cursor != null) { cursor.close(); } } } return false; } private void logDupPduMismatch(Cursor cursor, InboundSmsTracker tracker) { String oldPduString = cursor.getString( PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)); byte[] pdu = tracker.getPdu(); byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); if (!Arrays.equals(oldPdu, tracker.getPdu())) { loge("Warning: dup message PDU of length " + pdu.length + " is different from existing PDU of length " + oldPdu.length); } } /** * Insert a message PDU into the raw table so we can acknowledge it immediately. * If the device crashes before the broadcast to listeners completes, it will be delivered Loading @@ -1255,7 +1297,7 @@ public abstract class InboundSmsHandler extends StateMachine { private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) { if (deDup) { try { if (duplicateExists(tracker)) { if (checkAndHandleDuplicate(tracker)) { return Intents.RESULT_SMS_DUPLICATED; // reject message } } catch (SQLException e) { Loading src/java/com/android/internal/telephony/InboundSmsTracker.java +64 −21 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony; import android.content.ContentValues; import android.database.Cursor; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; Loading Loading @@ -88,19 +89,6 @@ public class InboundSmsTracker { + "AND count=? AND (destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU + ") AND deleted=0"; @VisibleForTesting public static final String SELECT_BY_DUPLICATE_REFERENCE = "address=? AND " + "reference_number=? AND count=? AND sequence=? AND " + "((date=? AND message_body=?) OR deleted=0) AND (destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=0)"; @VisibleForTesting public static final String SELECT_BY_DUPLICATE_REFERENCE_3GPP2WAP = "address=? AND " + "reference_number=? " + "AND count=? AND sequence=? AND " + "((date=? AND message_body=?) OR deleted=0) AND " + "(destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU + ")"; /** * Create a tracker for a single-part SMS. * Loading Loading @@ -284,13 +272,15 @@ public class InboundSmsTracker { builder.append(new Date(mTimestamp)); builder.append(" destPort=").append(mDestPort); builder.append(" is3gpp2=").append(mIs3gpp2); if (mAddress != null) { if (InboundSmsHandler.VDBG) { builder.append(" address=").append(mAddress); builder.append(" timestamp=").append(mTimestamp); builder.append(" messageBody=").append(mMessageBody); } builder.append(" display_originating_addr=").append(mDisplayAddress); builder.append(" refNumber=").append(mReferenceNumber); builder.append(" seqNumber=").append(mSequenceNumber); builder.append(" msgCount=").append(mMessageCount); } if (mDeleteWhere != null) { builder.append(" deleteWhere(").append(mDeleteWhere); builder.append(") deleteArgs=(").append(Arrays.toString(mDeleteWhereArgs)); Loading Loading @@ -324,9 +314,62 @@ public class InboundSmsTracker { return mIs3gpp2WapPdu ? SELECT_BY_REFERENCE_3GPP2WAP : SELECT_BY_REFERENCE; } public String getQueryForMultiPartDuplicates() { return mIs3gpp2WapPdu ? SELECT_BY_DUPLICATE_REFERENCE_3GPP2WAP : SELECT_BY_DUPLICATE_REFERENCE; /** * Get the query to find the exact same message/message segment in the db. * @return Pair with where as Pair.first and whereArgs as Pair.second */ public Pair<String, String[]> getExactMatchDupDetectQuery() { // convert to strings for query String address = getAddress(); String refNumber = Integer.toString(getReferenceNumber()); String count = Integer.toString(getMessageCount()); String seqNumber = Integer.toString(getSequenceNumber()); String date = Long.toString(getTimestamp()); String messageBody = getMessageBody(); String where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "date=? AND message_body=?"; where = addDestPortQuery(where); String[] whereArgs = new String[]{address, refNumber, count, seqNumber, date, messageBody}; return new Pair<>(where, whereArgs); } /** * The key differences here compared to exact match are: * - this is applicable only for multi-part message segments * - this does not match date or message_body * - this matches deleted=0 (undeleted segments) * The only difference as compared to getQueryForSegments() is that this checks for sequence as * well. * @return Pair with where as Pair.first and whereArgs as Pair.second */ public Pair<String, String[]> getInexactMatchDupDetectQuery() { if (getMessageCount() == 1) return null; // convert to strings for query String address = getAddress(); String refNumber = Integer.toString(getReferenceNumber()); String count = Integer.toString(getMessageCount()); String seqNumber = Integer.toString(getSequenceNumber()); String where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "deleted=0"; where = addDestPortQuery(where); String[] whereArgs = new String[]{address, refNumber, count, seqNumber}; return new Pair<>(where, whereArgs); } private String addDestPortQuery(String where) { String whereDestPort; if (mIs3gpp2WapPdu) { whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU; } else { whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=0"; } return where + " AND (" + whereDestPort + ")"; } /** Loading tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,10 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { verify(mContext, never()).sendBroadcast(any(Intent.class)); // verify there's only 1 of the segments in the db (other should be discarded as dup) assertEquals(1, mContentProvider.getNumRows()); // verify the first one is discarded, and second message is present in the db Cursor c = mContentProvider.query(sRawUri, null, null, null, null); c.moveToFirst(); assertEquals(mMessageBodyPart2, c.getString(c.getColumnIndex("message_body"))); // State machine should go back to idle assertEquals("IdleState", getCurrentState().getName()); } Loading Loading
src/java/com/android/internal/telephony/InboundSmsHandler.java +85 −43 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.LocalLog; import android.util.Pair; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -99,13 +100,21 @@ import java.util.Map; */ public abstract class InboundSmsHandler extends StateMachine { protected static final boolean DBG = true; private static final boolean VDBG = false; // STOPSHIP if true, logs user data protected static final boolean VDBG = false; // STOPSHIP if true, logs user data /** Query projection for checking for duplicate message segments. */ private static final String[] PDU_PROJECTION = { "pdu" private static final String[] PDU_DELETED_FLAG_PROJECTION = { "pdu", "deleted" }; /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */ private static final Map<Integer, Integer> PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING = new HashMap<Integer, Integer>() {{ put(PDU_COLUMN, 0); put(DELETED_FLAG_COLUMN, 1); }}; /** Query projection for combining concatenated message segments. */ private static final String[] PDU_SEQUENCE_PORT_PROJECTION = { "pdu", Loading Loading @@ -133,6 +142,7 @@ public abstract class InboundSmsHandler extends StateMachine { public static final int ID_COLUMN = 7; public static final int MESSAGE_BODY_COLUMN = 8; public static final int DISPLAY_ADDRESS_COLUMN = 9; public static final int DELETED_FLAG_COLUMN = 10; public static final String SELECT_BY_ID = "_id=?"; Loading Loading @@ -1183,55 +1193,47 @@ public abstract class InboundSmsHandler extends StateMachine { } /** * Function to check if message should be dropped because same message has already been * received. In certain cases it checks for similar messages instead of exact same (cases where * keeping both messages in db can cause ambiguity) * @return true if duplicate exists, false otherwise * Function to detect and handle duplicate messages. If the received message should replace an * existing message in the raw db, this function deletes the existing message. If an existing * message takes priority (for eg, existing message has already been broadcast), then this new * message should be dropped. * @return true if the message represented by the passed in tracker should be dropped, * false otherwise */ private boolean duplicateExists(InboundSmsTracker tracker) throws SQLException { String address = tracker.getAddress(); // convert to strings for query String refNumber = Integer.toString(tracker.getReferenceNumber()); String count = Integer.toString(tracker.getMessageCount()); // sequence numbers are 1-based except for CDMA WAP, which is 0-based int sequence = tracker.getSequenceNumber(); String seqNumber = Integer.toString(sequence); String date = Long.toString(tracker.getTimestamp()); String messageBody = tracker.getMessageBody(); String where; if (tracker.getMessageCount() == 1) { where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "date=? AND message_body=?"; } else { // for multi-part messages, deduping should also be done against undeleted // segments that can cause ambiguity when contacenating the segments, that is, // segments with same address, reference_number, count, sequence and message type. where = tracker.getQueryForMultiPartDuplicates(); } private boolean checkAndHandleDuplicate(InboundSmsTracker tracker) throws SQLException { Pair<String, String[]> exactMatchQuery = tracker.getExactMatchDupDetectQuery(); Cursor cursor = null; try { // Check for duplicate message segments cursor = mResolver.query(sRawUri, PDU_PROJECTION, where, new String[]{address, refNumber, count, seqNumber, date, messageBody}, null); cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, exactMatchQuery.first, exactMatchQuery.second, null); // moveToNext() returns false if no duplicates were found if (cursor != null && cursor.moveToNext()) { loge("Discarding duplicate message segment, refNumber=" + refNumber + " seqNumber=" + seqNumber + " count=" + count); if (VDBG) { loge("address=" + address + " date=" + date + " messageBody=" + messageBody); } String oldPduString = cursor.getString(PDU_COLUMN); byte[] pdu = tracker.getPdu(); byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); if (!Arrays.equals(oldPdu, tracker.getPdu())) { loge("Warning: dup message segment PDU of length " + pdu.length + " is different from existing PDU of length " + oldPdu.length); if (cursor.getCount() != 1) { loge("Exact match query returned " + cursor.getCount() + " rows"); } // if the exact matching row is marked deleted, that means this message has already // been received and processed, and can be discarded as dup if (cursor.getInt( PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(DELETED_FLAG_COLUMN)) == 1) { loge("Discarding duplicate message segment: " + tracker); logDupPduMismatch(cursor, tracker); return true; // reject message } else { // exact match duplicate is not marked deleted. If it is a multi-part segment, // the code below for inexact match will take care of it. If it is a single // part message, handle it here. if (tracker.getMessageCount() == 1) { // delete the old message segment permanently deleteFromRawTable(exactMatchQuery.first, exactMatchQuery.second, DELETE_PERMANENTLY); loge("Replacing duplicate message: " + tracker); logDupPduMismatch(cursor, tracker); } } } } finally { if (cursor != null) { Loading @@ -1239,9 +1241,49 @@ public abstract class InboundSmsHandler extends StateMachine { } } // The code above does an exact match. Multi-part message segments need an additional check // on top of that: if there is a message segment that conflicts this new one (may not be an // exact match), replace the old message segment with this one. if (tracker.getMessageCount() > 1) { Pair<String, String[]> inexactMatchQuery = tracker.getInexactMatchDupDetectQuery(); cursor = null; try { // Check for duplicate message segments cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, inexactMatchQuery.first, inexactMatchQuery.second, null); // moveToNext() returns false if no duplicates were found if (cursor != null && cursor.moveToNext()) { if (cursor.getCount() != 1) { loge("Inexact match query returned " + cursor.getCount() + " rows"); } // delete the old message segment permanently deleteFromRawTable(inexactMatchQuery.first, inexactMatchQuery.second, DELETE_PERMANENTLY); loge("Replacing duplicate message segment: " + tracker); logDupPduMismatch(cursor, tracker); } } finally { if (cursor != null) { cursor.close(); } } } return false; } private void logDupPduMismatch(Cursor cursor, InboundSmsTracker tracker) { String oldPduString = cursor.getString( PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)); byte[] pdu = tracker.getPdu(); byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); if (!Arrays.equals(oldPdu, tracker.getPdu())) { loge("Warning: dup message PDU of length " + pdu.length + " is different from existing PDU of length " + oldPdu.length); } } /** * Insert a message PDU into the raw table so we can acknowledge it immediately. * If the device crashes before the broadcast to listeners completes, it will be delivered Loading @@ -1255,7 +1297,7 @@ public abstract class InboundSmsHandler extends StateMachine { private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) { if (deDup) { try { if (duplicateExists(tracker)) { if (checkAndHandleDuplicate(tracker)) { return Intents.RESULT_SMS_DUPLICATED; // reject message } } catch (SQLException e) { Loading
src/java/com/android/internal/telephony/InboundSmsTracker.java +64 −21 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony; import android.content.ContentValues; import android.database.Cursor; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; Loading Loading @@ -88,19 +89,6 @@ public class InboundSmsTracker { + "AND count=? AND (destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU + ") AND deleted=0"; @VisibleForTesting public static final String SELECT_BY_DUPLICATE_REFERENCE = "address=? AND " + "reference_number=? AND count=? AND sequence=? AND " + "((date=? AND message_body=?) OR deleted=0) AND (destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=0)"; @VisibleForTesting public static final String SELECT_BY_DUPLICATE_REFERENCE_3GPP2WAP = "address=? AND " + "reference_number=? " + "AND count=? AND sequence=? AND " + "((date=? AND message_body=?) OR deleted=0) AND " + "(destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU + ")"; /** * Create a tracker for a single-part SMS. * Loading Loading @@ -284,13 +272,15 @@ public class InboundSmsTracker { builder.append(new Date(mTimestamp)); builder.append(" destPort=").append(mDestPort); builder.append(" is3gpp2=").append(mIs3gpp2); if (mAddress != null) { if (InboundSmsHandler.VDBG) { builder.append(" address=").append(mAddress); builder.append(" timestamp=").append(mTimestamp); builder.append(" messageBody=").append(mMessageBody); } builder.append(" display_originating_addr=").append(mDisplayAddress); builder.append(" refNumber=").append(mReferenceNumber); builder.append(" seqNumber=").append(mSequenceNumber); builder.append(" msgCount=").append(mMessageCount); } if (mDeleteWhere != null) { builder.append(" deleteWhere(").append(mDeleteWhere); builder.append(") deleteArgs=(").append(Arrays.toString(mDeleteWhereArgs)); Loading Loading @@ -324,9 +314,62 @@ public class InboundSmsTracker { return mIs3gpp2WapPdu ? SELECT_BY_REFERENCE_3GPP2WAP : SELECT_BY_REFERENCE; } public String getQueryForMultiPartDuplicates() { return mIs3gpp2WapPdu ? SELECT_BY_DUPLICATE_REFERENCE_3GPP2WAP : SELECT_BY_DUPLICATE_REFERENCE; /** * Get the query to find the exact same message/message segment in the db. * @return Pair with where as Pair.first and whereArgs as Pair.second */ public Pair<String, String[]> getExactMatchDupDetectQuery() { // convert to strings for query String address = getAddress(); String refNumber = Integer.toString(getReferenceNumber()); String count = Integer.toString(getMessageCount()); String seqNumber = Integer.toString(getSequenceNumber()); String date = Long.toString(getTimestamp()); String messageBody = getMessageBody(); String where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "date=? AND message_body=?"; where = addDestPortQuery(where); String[] whereArgs = new String[]{address, refNumber, count, seqNumber, date, messageBody}; return new Pair<>(where, whereArgs); } /** * The key differences here compared to exact match are: * - this is applicable only for multi-part message segments * - this does not match date or message_body * - this matches deleted=0 (undeleted segments) * The only difference as compared to getQueryForSegments() is that this checks for sequence as * well. * @return Pair with where as Pair.first and whereArgs as Pair.second */ public Pair<String, String[]> getInexactMatchDupDetectQuery() { if (getMessageCount() == 1) return null; // convert to strings for query String address = getAddress(); String refNumber = Integer.toString(getReferenceNumber()); String count = Integer.toString(getMessageCount()); String seqNumber = Integer.toString(getSequenceNumber()); String where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + "deleted=0"; where = addDestPortQuery(where); String[] whereArgs = new String[]{address, refNumber, count, seqNumber}; return new Pair<>(where, whereArgs); } private String addDestPortQuery(String where) { String whereDestPort; if (mIs3gpp2WapPdu) { whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU; } else { whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=0"; } return where + " AND (" + whereDestPort + ")"; } /** Loading
tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,10 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { verify(mContext, never()).sendBroadcast(any(Intent.class)); // verify there's only 1 of the segments in the db (other should be discarded as dup) assertEquals(1, mContentProvider.getNumRows()); // verify the first one is discarded, and second message is present in the db Cursor c = mContentProvider.query(sRawUri, null, null, null, null); c.moveToFirst(); assertEquals(mMessageBodyPart2, c.getString(c.getColumnIndex("message_body"))); // State machine should go back to idle assertEquals("IdleState", getCurrentState().getName()); } Loading