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

Commit ad34e698 authored by Hemant Gupta's avatar Hemant Gupta Committed by Andre Eisenbach
Browse files

MAP: Fix MAP server inter-op issues

 - Fix no recipient address info available when GETMessage
   and MessagesListing requested on Draft folder. Fetch
   Draft recipient address from "canonical_address" table
   based on threadId when no address available from regular
   "sms" table in telephony database.
-  Avoid dummy entry in sms database when requested to push a
   empty message. Reject empty SMS body and handle a possible
   exception from telephony stack for invalid message body.
-  Send MMS complete "size"  as attachment size fetched from
   database and subject or text length available.
-  Donot include "old_folder" info in MessageDeleted MNS event.
   As per Spec, only MessageShift event should use the later info.
-  Handle possible exception while processing  message listing.
   A case where message is saved in draft with no recipeint name,
   when we  try to fetch contact name during messagelisting, null
   number passed to ContactsProvider would cause IllegalArgumentException.
   Add null and empty check before quering contact provider.

Change-Id: I5f2234ae7e50ed719a31f463e372d2026988539c
parent e300d3f4
Loading
Loading
Loading
Loading
+97 −4
Original line number Diff line number Diff line
@@ -27,11 +27,14 @@ import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.Telephony.Mms;
import android.provider.Telephony.Sms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.CanonicalAddressesColumns;
import android.provider.Telephony.Threads;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;

@@ -693,6 +696,14 @@ public class BluetoothMapContent {
                size = subject.length();
            } else if (fi.mMsgType == FilterInfo.TYPE_MMS) {
                size = c.getInt(fi.mMmsColSize);
                //MMS complete size = attachment_size + subject length
                String subject = e.getSubject();
                if (subject == null || subject.length() == 0 ) {
                    // Handle setSubject if not done case
                    setSubject(e, c, fi, ap);
                }
                if (subject != null && subject.length() != 0 )
                    size += subject.length();
            } else if (fi.mMsgType == FilterInfo.TYPE_EMAIL ||
                       fi.mMsgType == FilterInfo.TYPE_IM) {
                size = c.getInt(fi.mMessageColSize);
@@ -923,11 +934,18 @@ public class BluetoothMapContent {
            String address = null;
            if (fi.mMsgType == FilterInfo.TYPE_SMS) {
                int msgType = c.getInt(fi.mSmsColType);
                if (msgType == 1) {
                if (msgType == Sms.MESSAGE_TYPE_INBOX ) {
                    address = fi.mPhoneNum;
                } else {
                    address = c.getString(c.getColumnIndex(Sms.ADDRESS));
                }
                if ((address == null) && msgType == Sms.MESSAGE_TYPE_DRAFT) {
                    //Fetch address for Drafts folder from "canonical_address" table
                    int threadIdInd = c.getColumnIndex(Sms.THREAD_ID);
                    String threadIdStr = c.getString(threadIdInd);
                    address = getCanonicalAddressSms(mResolver, Integer.valueOf(threadIdStr));
                    if(V)  Log.v(TAG, "threadId = " + threadIdStr + " adress:" + address +"\n");
                }
            } else if (fi.mMsgType == FilterInfo.TYPE_MMS) {
                long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
                address = getAddressMms(mResolver, id, MMS_TO);
@@ -1271,6 +1289,10 @@ public class BluetoothMapContent {
     *       caching. */
    public static String getContactNameFromPhone(String phone, ContentResolver resolver) {
        String name = null;
        //Handle possible exception for empty phone address
        if (TextUtils.isEmpty(phone)) {
            return name;
        }

        Uri uri = Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
                Uri.encode(phone));
@@ -1293,6 +1315,71 @@ public class BluetoothMapContent {
        }
        return name;
    }
    /**
     * Get SMS RecipientAddresses for DRAFT folder based on threadId
     *
    */
    static public String getCanonicalAddressSms(ContentResolver r,  int threadId) {
       String [] RECIPIENT_ID_PROJECTION = { Threads.RECIPIENT_IDS };
        /*
         1. Get Recipient Ids from Threads.CONTENT_URI
         2. Get Recipient Address for corresponding Id from canonical-addresses table.
        */

        //Uri sAllCanonical = Uri.parse("content://mms-sms/canonical-addresses");
        Uri sAllCanonical =
                MmsSms.CONTENT_URI.buildUpon().appendPath("canonical-addresses").build();
        Uri sAllThreadsUri =
                Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
        Cursor cr = null;
        String recipientAddress = "";
        String recipientIds = null;
        String whereClause = "_id="+threadId;
        if (V) Log.v(TAG, "whereClause is "+ whereClause);
        try {
            cr = r.query(sAllThreadsUri, RECIPIENT_ID_PROJECTION, whereClause, null, null);
            if (cr != null && cr.moveToFirst()) {
                recipientIds = cr.getString(0);
                if (V) Log.v(TAG, "cursor.getCount(): " + cr.getCount() + "recipientIds: "
                        + recipientIds + "selection: "+ whereClause );
            }
        } finally {
            if(cr != null) {
                cr.close();
                cr = null;
            }
        }
        if (V) Log.v(TAG, "recipientIds with spaces: "+ recipientIds +"\n");
        if(recipientIds != null) {
            String recipients[] = null;
            whereClause = "";
            recipients = recipientIds.split(" ");
            for (String id: recipients) {
                if(whereClause.length() != 0)
                    whereClause +=" OR ";
                whereClause +="_id="+id;
            }
            if (V) Log.v(TAG, "whereClause is "+ whereClause);
            try {
                cr = r.query(sAllCanonical , null, whereClause, null, null);
                if (cr != null && cr.moveToFirst()) {
                    do {
                        //TODO: Multiple Recipeints are appended with ";" for now.
                        if(recipientAddress.length() != 0 )
                           recipientAddress+=";";
                        recipientAddress += cr.getString(
                                cr.getColumnIndex(CanonicalAddressesColumns.ADDRESS));
                    } while(cr.moveToNext());
                }
           } finally {
               if(cr != null)
                   cr.close();
           }
        }

        if(V) Log.v(TAG,"Final recipientAddress : "+ recipientAddress);
        return recipientAddress;
     }

    static public String getAddressMms(ContentResolver r, long id, int type) {
        String selection = new String("msg_id=" + id + " AND type=" + type);
@@ -3224,10 +3311,13 @@ public class BluetoothMapContent {
    }

    private String setVCardFromPhoneNumber(BluetoothMapbMessage message,
            String phone,
            boolean incoming) {
            String phone, boolean incoming) {
        String contactId = null, contactName = null;
        String[] phoneNumbers = new String[1];
        //Handle possible exception for empty phone address
        if (TextUtils.isEmpty(phone)) {
            return contactName;
        }
        //
        // Use only actual phone number, because the MCE cannot know which
        // number the message is from.
@@ -3328,7 +3418,10 @@ public class BluetoothMapContent {
                msgBody = c.getString(c.getColumnIndex(Sms.BODY));

                String phone = c.getString(c.getColumnIndex(Sms.ADDRESS));

                if ((phone == null) && type == Sms.MESSAGE_TYPE_DRAFT) {
                    //Fetch address for Drafts folder from "canonical_address" table
                    phone  = getCanonicalAddressSms(mResolver, threadId);
                }
                time = c.getLong(c.getColumnIndex(Sms.DATE));
                if(type == 1) // Inbox message needs to set the vCard as originator
                    setVCardFromPhoneNumber(message, phone, true);
+60 −49
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Xml;
import android.text.TextUtils;

import org.xmlpull.v1.XmlSerializer;

@@ -1371,9 +1372,9 @@ public class BluetoothMapContentObserver {
                                    // We shall only use the folder attribute, but can't remember
                                    // wether to set it to "deleted" or the name of the folder
                                    // from which the message have been deleted.
                                    // "old_folder" used only for MessageShift event
                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
                                            BluetoothMapContract.FOLDER_NAME_DELETED,
                                            getSmsFolderName(msg.type), mSmsType);
                                            getSmsFolderName(msg.type), null, mSmsType);
                                    sendEvent(evt);
                                    msg.threadId = threadId;
                                } else { // Undelete
@@ -1403,9 +1404,9 @@ public class BluetoothMapContentObserver {
            }

            for (Msg msg : getMsgListSms().values()) {
                // "old_folder" used only for MessageShift event
                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
                        BluetoothMapContract.FOLDER_NAME_DELETED,
                        getSmsFolderName(msg.type), mSmsType);
                        getSmsFolderName(msg.type), null, mSmsType);
                sendEvent(evt);
                listChanged = true;
            }
@@ -1526,9 +1527,9 @@ public class BluetoothMapContentObserver {
                                        + msg.threadId);
                                listChanged = true;
                                if(threadId == DELETED_THREAD_ID) { // Message deleted
                                    // "old_folder" used only for MessageShift event
                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
                                            BluetoothMapContract.FOLDER_NAME_DELETED,
                                            getMmsFolderName(msg.type), TYPE.MMS);
                                            getMmsFolderName(msg.type), null, TYPE.MMS);
                                    sendEvent(evt);
                                    msg.threadId = threadId;
                                } else { // Undelete
@@ -1558,9 +1559,9 @@ public class BluetoothMapContentObserver {
                if (c != null) c.close();
            }
            for (Msg msg : getMsgListMms().values()) {
                // "old_folder" used only for MessageShift event
                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
                        BluetoothMapContract.FOLDER_NAME_DELETED,
                        getMmsFolderName(msg.type), TYPE.MMS);
                        getMmsFolderName(msg.type), null, TYPE.MMS);
                sendEvent(evt);
                listChanged = true;
            }
@@ -1669,8 +1670,9 @@ public class BluetoothMapContentObserver {
                                 */
                                if(deletedFolder != null && deletedFolder.getFolderId()
                                        == folderId) {
                                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, newFolder,
                                            oldFolder, mAccount.getType());
                                    // "old_folder" used only for MessageShift event
                                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
                                            null, mAccount.getType());
                                    sendEvent(evt);
                                } else if(sentFolder != null
                                        && sentFolder.getFolderId() == folderId
@@ -1741,8 +1743,9 @@ public class BluetoothMapContentObserver {
                 */
                if (!msg.transparent) {

                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, null, oldFolder,
                            mAccount.getType());
                    // "old_folder" used only for MessageShift event
                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
                            null, mAccount.getType());
                    sendEvent(evt);
                }
            }
@@ -2505,6 +2508,11 @@ public class BluetoothMapContentObserver {
                        if(msgBody == null)
                            msgBody = ((BluetoothMapbMessageSms) msg).getSmsBody();

                        if (TextUtils.isEmpty(msgBody)) {
                            Log.d(TAG, "PushMsg: Empty msgBody ");
                            /* not allowed to push empty message */
                            throw new IllegalArgumentException("push EMPTY message: Invalid Body");
                        }
                        /* We need to lock the SMS list while updating the database,
                         * to avoid sending events on MCE initiated operation. */
                        Uri contentUri = Uri.parse(Sms.CONTENT_URI+ "/" + folder);
@@ -2914,6 +2922,7 @@ public class BluetoothMapContentObserver {
         *       The correct solution would be to create a service that will start based on
         *       the intent, if BT is turned off. */

        if (parts != null && parts.size() > 0) {
            for (int i = 0; i < msgInfo.parts; i++) {
                Intent intentDelivery, intentSent;

@@ -2922,7 +2931,8 @@ public class BluetoothMapContentObserver {
                 * thereby get an intent for each msg part.
                 * setType is needed to create different intents for each message id/ time stamp,
                 * as the extras are not used when comparing. */
            intentDelivery.setType("message/" + Long.toString(msgInfo.id) + msgInfo.timestamp + i);
                intentDelivery.setType("message/" + Long.toString(msgInfo.id) +
                        msgInfo.timestamp + i);
                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_HANDLE, msgInfo.id);
                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_TIMESTAMP, msgInfo.timestamp);
                PendingIntent pendingIntentDelivery = PendingIntent.getBroadcast(mContext, 0,
@@ -2952,6 +2962,7 @@ public class BluetoothMapContentObserver {
            smsMng.sendMultipartTextMessage(msgInfo.phone, null, parts, sentIntents,
                    deliveryIntents);
        }
    }

    private class SmsBroadcastReceiver extends BroadcastReceiver {
        private final String[] ID_PROJECTION = new String[] { Sms._ID };