Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86475934 authored by fionaxu's avatar fionaxu Committed by Chen Xu
Browse files

fix multi-part sms issue

- sending multi-part SMS via Email was broken in NYC since we are using display
originating address to group multi-part messages.
- In a common case, only the fist SMS comes with the right email
displaying address, thus fails to group sms together.
- Fix is keep using originating_address to aggregate Multi-part SMS and introduce a new column:
display_address in the raw table to check blocking addresses for both
phone number and email address

Bug: 34118154
Test: Manual & telephony unit tests
Change-Id: Iaf8d1692f5e12b155578acd646cc244035dde774
Merged-In: CHANGE-ID Ibd902e5ccbad34c0e1e97d7c699258dc4d2c867a
parent e8bc7318
Loading
Loading
Loading
Loading
+40 −8
Original line number Original line Diff line number Diff line
@@ -79,7 +79,9 @@ import com.android.internal.util.StateMachine;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;


/**
/**
 * This class broadcasts incoming SMS messages to interested apps after storing them in
 * This class broadcasts incoming SMS messages to interested apps after storing them in
@@ -114,9 +116,19 @@ public abstract class InboundSmsHandler extends StateMachine {
    private static final String[] PDU_SEQUENCE_PORT_PROJECTION = {
    private static final String[] PDU_SEQUENCE_PORT_PROJECTION = {
            "pdu",
            "pdu",
            "sequence",
            "sequence",
            "destination_port"
            "destination_port",
            "display_originating_addr"
    };
    };


    /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */
    private static final Map<Integer, Integer> PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING =
            new HashMap<Integer, Integer>() {{
                put(PDU_COLUMN, 0);
                put(SEQUENCE_COLUMN, 1);
                put(DESTINATION_PORT_COLUMN, 2);
                put(DISPLAY_ADDRESS_COLUMN, 3);
    }};

    public static final int PDU_COLUMN = 0;
    public static final int PDU_COLUMN = 0;
    public static final int SEQUENCE_COLUMN = 1;
    public static final int SEQUENCE_COLUMN = 1;
    public static final int DESTINATION_PORT_COLUMN = 2;
    public static final int DESTINATION_PORT_COLUMN = 2;
@@ -126,6 +138,7 @@ public abstract class InboundSmsHandler extends StateMachine {
    public static final int ADDRESS_COLUMN = 6;
    public static final int ADDRESS_COLUMN = 6;
    public static final int ID_COLUMN = 7;
    public static final int ID_COLUMN = 7;
    public static final int MESSAGE_BODY_COLUMN = 8;
    public static final int MESSAGE_BODY_COLUMN = 8;
    public static final int DISPLAY_ADDRESS_COLUMN = 9;


    public static final String SELECT_BY_ID = "_id=?";
    public static final String SELECT_BY_ID = "_id=?";
    public static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND " +
    public static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND " +
@@ -674,7 +687,8 @@ public abstract class InboundSmsHandler extends StateMachine {


            tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
            tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
                    sms.getTimestampMillis(), destPort, is3gpp2(), false,
                    sms.getTimestampMillis(), destPort, is3gpp2(), false,
                    sms.getDisplayOriginatingAddress(), sms.getMessageBody());
                    sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
                    sms.getMessageBody());
        } else {
        } else {
            // Create a tracker for this message segment.
            // Create a tracker for this message segment.
            SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
            SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
@@ -682,7 +696,7 @@ public abstract class InboundSmsHandler extends StateMachine {
            int destPort = (portAddrs != null ? portAddrs.destPort : -1);
            int destPort = (portAddrs != null ? portAddrs.destPort : -1);


            tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
            tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
                    sms.getTimestampMillis(), destPort, is3gpp2(),
                    sms.getTimestampMillis(), destPort, is3gpp2(), sms.getOriginatingAddress(),
                    sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber,
                    sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber,
                    concatRef.msgCount, false, sms.getMessageBody());
                    concatRef.msgCount, false, sms.getMessageBody());
        }
        }
@@ -728,10 +742,12 @@ public abstract class InboundSmsHandler extends StateMachine {
        int messageCount = tracker.getMessageCount();
        int messageCount = tracker.getMessageCount();
        byte[][] pdus;
        byte[][] pdus;
        int destPort = tracker.getDestPort();
        int destPort = tracker.getDestPort();
        boolean block = false;


        if (messageCount == 1) {
        if (messageCount == 1) {
            // single-part message
            // single-part message
            pdus = new byte[][]{tracker.getPdu()};
            pdus = new byte[][]{tracker.getPdu()};
            block = BlockChecker.isBlocked(mContext, tracker.getDisplayAddress());
        } else {
        } else {
            // multi-part message
            // multi-part message
            Cursor cursor = null;
            Cursor cursor = null;
@@ -760,20 +776,36 @@ public abstract class InboundSmsHandler extends StateMachine {
                pdus = new byte[messageCount][];
                pdus = new byte[messageCount][];
                while (cursor.moveToNext()) {
                while (cursor.moveToNext()) {
                    // subtract offset to convert sequence to 0-based array index
                    // subtract offset to convert sequence to 0-based array index
                    int index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset();
                    int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                            .get(SEQUENCE_COLUMN)) - tracker.getIndexOffset();


                    pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN));
                    pdus[index] = HexDump.hexStringToByteArray(cursor.getString(
                            PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)));


                    // Read the destination port from the first segment (needed for CDMA WAP PDU).
                    // Read the destination port from the first segment (needed for CDMA WAP PDU).
                    // It's not a bad idea to prefer the port from the first segment in other cases.
                    // It's not a bad idea to prefer the port from the first segment in other cases.
                    if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) {
                    if (index == 0 && !cursor.isNull(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                        int port = cursor.getInt(DESTINATION_PORT_COLUMN);
                            .get(DESTINATION_PORT_COLUMN))) {
                        int port = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                                .get(DESTINATION_PORT_COLUMN));
                        // strip format flags and convert to real port number, or -1
                        // strip format flags and convert to real port number, or -1
                        port = InboundSmsTracker.getRealDestPort(port);
                        port = InboundSmsTracker.getRealDestPort(port);
                        if (port != -1) {
                        if (port != -1) {
                            destPort = port;
                            destPort = port;
                        }
                        }
                    }
                    }
                    // check if display address should be blocked or not
                    if (!block) {
                        // Depending on the nature of the gateway, the display origination address
                        // is either derived from the content of the SMS TP-OA field, or the TP-OA
                        // field contains a generic gateway address and the from address is added
                        // at the beginning in the message body. In that case only the first SMS
                        // (part of Multi-SMS) comes with the display originating address which
                        // could be used for block checking purpose.
                        block = BlockChecker.isBlocked(mContext,
                                cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                                        .get(DISPLAY_ADDRESS_COLUMN)));
                    }
                }
                }
            } catch (SQLException e) {
            } catch (SQLException e) {
                loge("Can't access multipart SMS database", e);
                loge("Can't access multipart SMS database", e);
@@ -827,7 +859,7 @@ public abstract class InboundSmsHandler extends StateMachine {
            }
            }
        }
        }


        if (BlockChecker.isBlocked(mContext, tracker.getAddress())) {
        if (block) {
            deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
            deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
                    DELETE_PERMANENTLY);
                    DELETE_PERMANENTLY);
            return false;
            return false;
+30 −7
Original line number Original line Diff line number Diff line
@@ -38,10 +38,9 @@ public class InboundSmsTracker {
    private final boolean mIs3gpp2;
    private final boolean mIs3gpp2;
    private final boolean mIs3gpp2WapPdu;
    private final boolean mIs3gpp2WapPdu;
    private final String mMessageBody;
    private final String mMessageBody;
    // Copied from SmsMessageBase#getDisplayOriginatingAddress used for blocking messages.
    private final String mAddress;


    // Fields for concatenating multi-part SMS messages
    // Fields for concatenating multi-part SMS messages
    private final String mAddress;
    private final int mReferenceNumber;
    private final int mReferenceNumber;
    private final int mSequenceNumber;
    private final int mSequenceNumber;
    private final int mMessageCount;
    private final int mMessageCount;
@@ -50,6 +49,16 @@ public class InboundSmsTracker {
    private String mDeleteWhere;
    private String mDeleteWhere;
    private String[] mDeleteWhereArgs;
    private String[] mDeleteWhereArgs;


    /**
     * Copied from SmsMessageBase#getDisplayOriginatingAddress used for blocking messages.
     * DisplayAddress could be email address if this message was from an email gateway, otherwise
     * same as mAddress. Email gateway might set a generic gateway address as the mAddress which
     * could not be used for blocking check and append the display email address at the beginning
     * of the message body. In that case, display email address is only available for the first SMS
     * in the Multi-part SMS.
     */
    private final String mDisplayAddress;

    /** Destination port flag bit for no destination port. */
    /** Destination port flag bit for no destination port. */
    private static final int DEST_PORT_FLAG_NO_PORT = (1 << 16);
    private static final int DEST_PORT_FLAG_NO_PORT = (1 << 16);


@@ -73,10 +82,12 @@ public class InboundSmsTracker {
     * @param destPort the destination port
     * @param destPort the destination port
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     * @param address originating address, or email if this message was from an email gateway
     * @param address originating address
     * @param displayAddress email address if this message was from an email gateway, otherwise same
     *                       as originating address
     */
     */
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
            boolean is3gpp2WapPdu, String address, String messageBody) {
            boolean is3gpp2WapPdu, String address, String displayAddress, String messageBody) {
        mPdu = pdu;
        mPdu = pdu;
        mTimestamp = timestamp;
        mTimestamp = timestamp;
        mDestPort = destPort;
        mDestPort = destPort;
@@ -84,6 +95,7 @@ public class InboundSmsTracker {
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mMessageBody = messageBody;
        mMessageBody = messageBody;
        mAddress = address;
        mAddress = address;
        mDisplayAddress = displayAddress;
        // fields for multi-part SMS
        // fields for multi-part SMS
        mReferenceNumber = -1;
        mReferenceNumber = -1;
        mSequenceNumber = getIndexOffset();     // 0 or 1, depending on type
        mSequenceNumber = getIndexOffset();     // 0 or 1, depending on type
@@ -102,22 +114,26 @@ public class InboundSmsTracker {
     * @param destPort the destination port
     * @param destPort the destination port
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param address originating address, or email if this message was from an email gateway
     * @param address originating address, or email if this message was from an email gateway
     * @param displayAddress email address if this message was from an email gateway, otherwise same
     *                       as originating address
     * @param referenceNumber the concatenated reference number
     * @param referenceNumber the concatenated reference number
     * @param sequenceNumber the sequence number of this segment (0-based)
     * @param sequenceNumber the sequence number of this segment (0-based)
     * @param messageCount the total number of segments
     * @param messageCount the total number of segments
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     */
     */
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
            String address, int referenceNumber, int sequenceNumber, int messageCount,
            String address, String displayAddress, int referenceNumber, int sequenceNumber,
            boolean is3gpp2WapPdu, String messageBody) {
            int messageCount, boolean is3gpp2WapPdu, String messageBody) {
        mPdu = pdu;
        mPdu = pdu;
        mTimestamp = timestamp;
        mTimestamp = timestamp;
        mDestPort = destPort;
        mDestPort = destPort;
        mIs3gpp2 = is3gpp2;
        mIs3gpp2 = is3gpp2;
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mMessageBody = messageBody;
        mMessageBody = messageBody;
        mAddress = address;
        // fields used for check blocking message
        mDisplayAddress = displayAddress;
        // fields for multi-part SMS
        // fields for multi-part SMS
        mAddress = address;
        mReferenceNumber = referenceNumber;
        mReferenceNumber = referenceNumber;
        mSequenceNumber = sequenceNumber;
        mSequenceNumber = sequenceNumber;
        mMessageCount = messageCount;
        mMessageCount = messageCount;
@@ -150,6 +166,7 @@ public class InboundSmsTracker {


        mTimestamp = cursor.getLong(InboundSmsHandler.DATE_COLUMN);
        mTimestamp = cursor.getLong(InboundSmsHandler.DATE_COLUMN);
        mAddress = cursor.getString(InboundSmsHandler.ADDRESS_COLUMN);
        mAddress = cursor.getString(InboundSmsHandler.ADDRESS_COLUMN);
        mDisplayAddress = cursor.getString(InboundSmsHandler.DISPLAY_ADDRESS_COLUMN);


        if (cursor.isNull(InboundSmsHandler.COUNT_COLUMN)) {
        if (cursor.isNull(InboundSmsHandler.COUNT_COLUMN)) {
            // single-part message
            // single-part message
@@ -203,6 +220,7 @@ public class InboundSmsTracker {
        values.put("destination_port", destPort);
        values.put("destination_port", destPort);
        if (mAddress != null) {
        if (mAddress != null) {
            values.put("address", mAddress);
            values.put("address", mAddress);
            values.put("display_originating_addr", mDisplayAddress);
            values.put("reference_number", mReferenceNumber);
            values.put("reference_number", mReferenceNumber);
            values.put("sequence", mSequenceNumber);
            values.put("sequence", mSequenceNumber);
            values.put("count", mMessageCount);
            values.put("count", mMessageCount);
@@ -241,6 +259,7 @@ public class InboundSmsTracker {
        builder.append(" is3gpp2=").append(mIs3gpp2);
        builder.append(" is3gpp2=").append(mIs3gpp2);
        if (mAddress != null) {
        if (mAddress != null) {
            builder.append(" address=").append(mAddress);
            builder.append(" address=").append(mAddress);
            builder.append(" display_originating_addr=").append(mDisplayAddress);
            builder.append(" refNumber=").append(mReferenceNumber);
            builder.append(" refNumber=").append(mReferenceNumber);
            builder.append(" seqNumber=").append(mSequenceNumber);
            builder.append(" seqNumber=").append(mSequenceNumber);
            builder.append(" msgCount=").append(mMessageCount);
            builder.append(" msgCount=").append(mMessageCount);
@@ -287,6 +306,10 @@ public class InboundSmsTracker {
        return mAddress;
        return mAddress;
    }
    }


    public String getDisplayAddress() {
        return mDisplayAddress;
    }

    public String getMessageBody() {
    public String getMessageBody() {
        return mMessageBody;
        return mMessageBody;
    }
    }
+2 −1
Original line number Original line Diff line number Diff line
@@ -60,7 +60,8 @@ public class SmsBroadcastUndelivered {
            "count",
            "count",
            "address",
            "address",
            "_id",
            "_id",
            "message_body"
            "message_body",
            "display_originating_addr"
    };
    };


    private static SmsBroadcastUndelivered instance;
    private static SmsBroadcastUndelivered instance;
+6 −5
Original line number Original line Diff line number Diff line
@@ -92,19 +92,20 @@ public class TelephonyComponentFactory {
     * Create a tracker for a single-part SMS.
     * Create a tracker for a single-part SMS.
     */
     */
    public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
    public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
            boolean is3gpp2, boolean is3gpp2WapPdu, String address, String messageBody) {
            boolean is3gpp2, boolean is3gpp2WapPdu, String address, String displayAddr,
            String messageBody) {
        return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, is3gpp2WapPdu, address,
        return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, is3gpp2WapPdu, address,
                messageBody);
                displayAddr, messageBody);
    }
    }


    /**
    /**
     * Create a tracker for a multi-part SMS.
     * Create a tracker for a multi-part SMS.
     */
     */
    public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
    public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
            boolean is3gpp2, String address, int referenceNumber, int sequenceNumber,
            boolean is3gpp2, String address, String displayAddr, int referenceNumber, int sequenceNumber,
            int messageCount, boolean is3gpp2WapPdu, String messageBody) {
            int messageCount, boolean is3gpp2WapPdu, String messageBody) {
        return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, address, referenceNumber,
        return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, address, displayAddr,
                sequenceNumber, messageCount, is3gpp2WapPdu, messageBody);
                referenceNumber, sequenceNumber, messageCount, is3gpp2WapPdu, messageBody);
    }
    }


    /**
    /**
+5 −4
Original line number Original line Diff line number Diff line
@@ -170,7 +170,8 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {


        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
            return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
            return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
                    sms.getOriginatingAddress(), sms.getTimestampMillis());
                    sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
                    sms.getTimestampMillis());
        }
        }


        return dispatchNormalMessage(smsb);
        return dispatchNormalMessage(smsb);
@@ -257,7 +258,7 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
     *         {@link Activity#RESULT_OK} if the message has been broadcast
     *         {@link Activity#RESULT_OK} if the message has been broadcast
     *         to applications
     *         to applications
     */
     */
    private int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address,
    private int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address, String dispAddr,
            long timestamp) {
            long timestamp) {
        int index = 0;
        int index = 0;


@@ -302,8 +303,8 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
        System.arraycopy(pdu, index, userData, 0, pdu.length - index);
        System.arraycopy(pdu, index, userData, 0, pdu.length - index);


        InboundSmsTracker tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(
        InboundSmsTracker tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(
                userData, timestamp, destinationPort, true, address, referenceNumber, segment,
                userData, timestamp, destinationPort, true, address, dispAddr, referenceNumber,
                totalSegments, true, HexDump.toHexString(userData));
                segment, totalSegments, true, HexDump.toHexString(userData));


        // de-duping is done only for text messages
        // de-duping is done only for text messages
        return addTrackerToRawTableAndSendMessage(tracker, false /* don't de-dup */);
        return addTrackerToRawTableAndSendMessage(tracker, false /* don't de-dup */);
Loading