1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/* 2fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Copyright (C) 2013 Samsung System LSI 3fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Licensed under the Apache License, Version 2.0 (the "License"); 4fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* you may not use this file except in compliance with the License. 5fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* You may obtain a copy of the License at 6fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 7fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* http://www.apache.org/licenses/LICENSE-2.0 8fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 9fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Unless required by applicable law or agreed to in writing, software 10fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* distributed under the License is distributed on an "AS IS" BASIS, 11fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* See the License for the specific language governing permissions and 13fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* limitations under the License. 14fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*/ 15fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepackage com.android.bluetooth.map; 16fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 17fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.ByteArrayInputStream; 18fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.FileNotFoundException; 19fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.IOException; 20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.OutputStream; 21fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.StringWriter; 22fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.UnsupportedEncodingException; 23fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.ArrayList; 24fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.Arrays; 25fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.Collections; 26fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.HashMap; 27fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.HashSet; 28fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.Map; 29fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.Set; 30fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 31fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport org.xmlpull.v1.XmlSerializer; 32fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 33fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.app.Activity; 34fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.app.PendingIntent; 35fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.BroadcastReceiver; 36fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentResolver; 37fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentUris; 38fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentValues; 39fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Context; 40fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Intent; 41fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.IntentFilter; 42fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.database.ContentObserver; 43fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.database.Cursor; 44fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.net.Uri; 45fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Handler; 46fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.BaseColumns; 47fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony; 48fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Mms; 49fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.MmsSms; 50fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms; 51fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms.Inbox; 52fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.PhoneStateListener; 53fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.ServiceState; 54fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsManager; 55fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsMessage; 56fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.TelephonyManager; 57fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log; 58fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Xml; 59fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 60fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.map.BluetoothMapUtils.TYPE; 61fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.map.BluetoothMapbMessageMmsEmail.MimePart; 62fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.google.android.mms.pdu.PduHeaders; 63fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 64fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepublic class BluetoothMapContentObserver { 65fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String TAG = "BluetoothMapContentObserver"; 66fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 6770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz private static final boolean D = false; 6870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz private static final boolean V = false; 69fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 70fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private Context mContext; 71fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private ContentResolver mResolver; 72fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private BluetoothMnsObexClient mMnsClient; 73fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private int mMasId; 74fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 75fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public static final int DELETED_THREAD_ID = -1; 76fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 77fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* X-Mms-Message-Type field types. These are from PduHeaders.java */ 78fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84; 79fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 80fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private TYPE mSmsType; 81fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 82fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie static final String[] SMS_PROJECTION = new String[] { 83fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BaseColumns._ID, 84fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.THREAD_ID, 85fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.ADDRESS, 86fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.BODY, 87fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.DATE, 88fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.READ, 89fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.TYPE, 90fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.STATUS, 91fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.LOCKED, 92fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.ERROR_CODE, 93fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 94fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 95fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie static final String[] MMS_PROJECTION = new String[] { 96fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BaseColumns._ID, 97fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.THREAD_ID, 98fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.MESSAGE_ID, 99fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.MESSAGE_SIZE, 100fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.SUBJECT, 101fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.CONTENT_TYPE, 102fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.TEXT_ONLY, 103fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.DATE, 104fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.DATE_SENT, 105fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.READ, 106fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.MESSAGE_BOX, 107fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.MESSAGE_TYPE, 108fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Mms.STATUS, 109fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 110fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 111fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public BluetoothMapContentObserver(final Context context) { 112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mContext = context; 113fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver = mContext.getContentResolver(); 114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 115fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mSmsType = getSmsType(); 116fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 117fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 118fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private TYPE getSmsType() { 119fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie TYPE smsType = null; 120fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie TelephonyManager tm = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE); 121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) { 123fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie smsType = TYPE.SMS_GSM; 124fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { 125fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie smsType = TYPE.SMS_CDMA; 126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 128fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return smsType; 129fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 130fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 131fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private final ContentObserver mObserver = new ContentObserver(new Handler()) { 132fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie @Override 133fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void onChange(boolean selfChange) { 134fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie onChange(selfChange, null); 135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 136fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 137fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie @Override 138fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void onChange(boolean selfChange, Uri uri) { 139fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "onChange on thread: " + Thread.currentThread().getId() 140fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + " Uri: " + uri.toString() + " selfchange: " + selfChange); 141fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 142fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handleMsgListChanges(); 143fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 144fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 145fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 146fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String folderSms[] = { 147fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "", 148fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "inbox", 149fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "sent", 150fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "draft", 151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "outbox", 152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "outbox", 153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "outbox", 154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "inbox", 155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "inbox", 156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 157fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 158fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String folderMms[] = { 159fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "", 160fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "inbox", 161fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "sent", 162fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "draft", 163fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "outbox", 164fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 165fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 166fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private class Event { 167fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String eventType; 168fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long handle; 169fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String folder; 170fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String oldFolder; 171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie TYPE msgType; 172fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public Event(String eventType, long handle, String folder, 174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String oldFolder, TYPE msgType) { 175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String PATH = "telecom/msg/"; 176fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.eventType = eventType; 177fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.handle = handle; 178fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folder != null) { 179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.folder = PATH + folder; 180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.folder = null; 182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (oldFolder != null) { 184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.oldFolder = PATH + oldFolder; 185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.oldFolder = null; 187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.msgType = msgType; 189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public byte[] encode() throws UnsupportedEncodingException { 192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie StringWriter sw = new StringWriter(); 193fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie XmlSerializer xmlEvtReport = Xml.newSerializer(); 194fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 195fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.setOutput(sw); 196fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.startDocument(null, null); 197fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.text("\n"); 19870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz xmlEvtReport.startTag("", "MAP-event-report"); 199fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "version", "1.0"); 200fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 201fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.startTag("", "event"); 202fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "type", eventType); 203fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "handle", BluetoothMapUtils.getMapHandle(handle, msgType)); 204fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folder != null) { 205fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "folder", folder); 206fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 207fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (oldFolder != null) { 208fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "old_folder", oldFolder); 209fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 210fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.attribute("", "msg_type", msgType.name()); 211fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.endTag("", "event"); 212fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 21370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz xmlEvtReport.endTag("", "MAP-event-report"); 214fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlEvtReport.endDocument(); 215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IllegalArgumentException e) { 216fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie e.printStackTrace(); 217fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IllegalStateException e) { 218fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie e.printStackTrace(); 219fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 220fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie e.printStackTrace(); 221fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 222fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 223fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) System.out.println(sw.toString()); 224fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 225fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return sw.toString().getBytes("UTF-8"); 226fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 227fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 228fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 229fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private class Msg { 230fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id; 231fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int type; 232fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 233fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public Msg(long id, int type) { 234fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.id = id; 235fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.type = type; 236fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 237fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 238fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private Map<Long, Msg> mMsgListSms = 240fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Collections.synchronizedMap(new HashMap<Long, Msg>()); 241fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 242fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private Map<Long, Msg> mMsgListMms = 243fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Collections.synchronizedMap(new HashMap<Long, Msg>()); 244fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 245fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void registerObserver(BluetoothMnsObexClient mns, int masId) { 246fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "registerObserver"); 247fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Use MmsSms Uri since the Sms Uri is not notified on deletes */ 248fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMasId = masId; 249fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMnsClient = mns; 250fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.registerContentObserver(MmsSms.CONTENT_URI, false, mObserver); 251fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie initMsgList(); 252fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 253fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 254fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void unregisterObserver() { 255fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "unregisterObserver"); 256fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.unregisterContentObserver(mObserver); 25770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz mMnsClient = null; 258fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 259fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 260fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void sendEvent(Event evt) { 261fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "sendEvent: " + evt.eventType + " " + evt.handle + " " 262fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + evt.folder + " " + evt.oldFolder + " " + evt.msgType.name()); 263fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 264fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (mMnsClient == null) { 265fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "sendEvent: No MNS client registered - don't send event"); 266fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return; 267fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 268fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 269fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 270fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMnsClient.sendEvent(evt.encode(), mMasId); 271fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (UnsupportedEncodingException ex) { 272fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* do nothing */ 273fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 274fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 275fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 276fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void initMsgList() { 277fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "initMsgList"); 278fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 279fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListSms.clear(); 280fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListMms.clear(); 281fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 282fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>(); 283fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 284fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(Sms.CONTENT_URI, 285fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie SMS_PROJECTION, null, null, null); 286fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 287fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 288fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 289fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 290fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int type = c.getInt(c.getColumnIndex(Sms.TYPE)); 291fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 292fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Msg msg = new Msg(id, type); 293fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListSms.put(id, msg); 294fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 295fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 296fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 297fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 298fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListSms = msgListSms; 299fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 300fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>(); 301fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 302fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c = mResolver.query(Mms.CONTENT_URI, 303fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie MMS_PROJECTION, null, null, null); 304fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 305fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 306fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 307fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 308fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX)); 309fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 310fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Msg msg = new Msg(id, type); 311fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListMms.put(id, msg); 312fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 313fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 314fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 315fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 316fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListMms = msgListMms; 317fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 318fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 319fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void handleMsgListChangesSms() { 320fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "handleMsgListChangesSms"); 321fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 322fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>(); 323fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 324fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(Sms.CONTENT_URI, 325fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie SMS_PROJECTION, null, null, null); 326fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 327fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie synchronized(mMsgListSms) { 328fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 329fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 330fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 331fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int type = c.getInt(c.getColumnIndex(Sms.TYPE)); 332fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 333fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Msg msg = mMsgListSms.remove(id); 334fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 335fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msg == null) { 336fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* New message */ 337fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msg = new Msg(id, type); 338fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListSms.put(id, msg); 339fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 340fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folderSms[type].equals("inbox")) { 341fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("NewMessage", id, folderSms[type], 342fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie null, mSmsType); 343fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 344fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 345fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 346fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Existing message */ 347fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (type != msg.type) { 348fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "new type: " + type + " old type: " + msg.type); 349fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("MessageShift", id, folderSms[type], 350fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[msg.type], mSmsType); 351fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 352fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msg.type = type; 353fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 354fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListSms.put(id, msg); 355fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 356fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 357fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 358fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 359fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 360fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for (Msg msg : mMsgListSms.values()) { 361fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("MessageDeleted", msg.id, "deleted", 362fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[msg.type], mSmsType); 363fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 364fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 365fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 366fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListSms = msgListSms; 367fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 368fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 369fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 370fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void handleMsgListChangesMms() { 371fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.d(TAG, "handleMsgListChangesMms"); 372fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 373fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>(); 374fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 375fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(Mms.CONTENT_URI, 376fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie MMS_PROJECTION, null, null, null); 377fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 378fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie synchronized(mMsgListMms) { 379fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 380fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 381fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 382fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX)); 383fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int mtype = c.getInt(c.getColumnIndex(Mms.MESSAGE_TYPE)); 384fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 385fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Msg msg = mMsgListMms.remove(id); 386fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 387fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msg == null) { 388fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* New message - only notify on retrieve conf */ 389fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folderMms[type].equals("inbox") && 390fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mtype != MESSAGE_TYPE_RETRIEVE_CONF) { 391fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie continue; 392fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 393fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 394fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msg = new Msg(id, type); 395fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListMms.put(id, msg); 396fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 397fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folderMms[type].equals("inbox")) { 398fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("NewMessage", id, folderMms[type], 399fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie null, TYPE.MMS); 400fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 401fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 402fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 403fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Existing message */ 404fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (type != msg.type) { 405fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "new type: " + type + " old type: " + msg.type); 406fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("MessageShift", id, folderMms[type], 407fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderMms[msg.type], TYPE.MMS); 408fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 409fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msg.type = type; 410fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 411fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folderMms[type].equals("sent")) { 412fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie evt = new Event("SendingSuccess", id, 413fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[type], null, TYPE.MMS); 414fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 415fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 416fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 417fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgListMms.put(id, msg); 418fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 419fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 420fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 421fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 422fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 423fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for (Msg msg : mMsgListMms.values()) { 424fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("MessageDeleted", msg.id, "deleted", 425fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderMms[msg.type], TYPE.MMS); 426fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 427fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 428fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 429fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListMms = msgListMms; 430fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 431fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 432fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 433fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void handleMsgListChanges() { 434fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handleMsgListChangesSms(); 435fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handleMsgListChangesMms(); 436fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 437fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 438fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private boolean deleteMessageMms(long handle) { 439fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = false; 440fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle); 441fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 442fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 443fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Move to deleted folder, or delete if already in deleted folder */ 444fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID)); 445fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (threadId != DELETED_THREAD_ID) { 446fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Set deleted thread id */ 447fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 448fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Mms.THREAD_ID, DELETED_THREAD_ID); 449fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 450fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 451fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete from observer message list to avoid delete notifications */ 452fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListMms.remove(handle); 453fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete message */ 454fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.delete(uri, null, null); 455fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 456fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = true; 457fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 458fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null) { 459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 461fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 462fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 463fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 464fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void updateThreadIdMms(Uri uri, long threadId) { 465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 466fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Mms.THREAD_ID, threadId); 467fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 468fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 469fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 470fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private boolean unDeleteMessageMms(long handle) { 471fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = false; 472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle); 473fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 474fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 475fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 476fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID)); 477fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (threadId == DELETED_THREAD_ID) { 478fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Restore thread id from address, or if no thread for address 479fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * create new thread by insert and remove of fake message */ 480fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String address; 481fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 482fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int msgBox = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX)); 483fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgBox == Mms.MESSAGE_BOX_INBOX) { 484fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie address = BluetoothMapContent.getAddressMms(mResolver, id, 485fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothMapContent.MMS_FROM); 486fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 487fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie address = BluetoothMapContent.getAddressMms(mResolver, id, 488fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothMapContent.MMS_TO); 489fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 490fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Set<String> recipients = new HashSet<String>(); 491fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie recipients.addAll(Arrays.asList(address)); 492fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie updateThreadIdMms(uri, Telephony.Threads.getOrCreateThreadId(mContext, recipients)); 493fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 494fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Message not in deleted folder: handle " + handle 495fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + " threadId " + threadId); 496fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 497fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = true; 498fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 499fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null) { 500fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 501fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 502fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 503fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 504fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 505fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private boolean deleteMessageSms(long handle) { 506fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = false; 507fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle); 508fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 509fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 510fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 511fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Move to deleted folder, or delete if already in deleted folder */ 512fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID)); 513fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (threadId != DELETED_THREAD_ID) { 514fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Set deleted thread id */ 515fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 516fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Sms.THREAD_ID, DELETED_THREAD_ID); 517fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 518fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 519fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete from observer message list to avoid delete notifications */ 520fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListSms.remove(handle); 521fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete message */ 522fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.delete(uri, null, null); 523fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 524fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = true; 525fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 526fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null) { 527fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 528fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 529fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 530fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 531fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 532fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void updateThreadIdSms(Uri uri, long threadId) { 533fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 534fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Sms.THREAD_ID, threadId); 535fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 536fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 537fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 538fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private boolean unDeleteMessageSms(long handle) { 539fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = false; 540fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle); 541fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 542fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 543fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 544fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID)); 545fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (threadId == DELETED_THREAD_ID) { 546fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String address = c.getString(c.getColumnIndex(Sms.ADDRESS)); 547fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Set<String> recipients = new HashSet<String>(); 548fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie recipients.addAll(Arrays.asList(address)); 549fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie updateThreadIdSms(uri, Telephony.Threads.getOrCreateThreadId(mContext, recipients)); 550fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 551fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Message not in deleted folder: handle " + handle 552fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + " threadId " + threadId); 553fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 554fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = true; 555fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 556fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null) { 557fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 558fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 559fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 560fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 561fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 562fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public boolean setMessageStatusDeleted(long handle, TYPE type, int statusValue) { 563fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = false; 564fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "setMessageStatusDeleted: handle " + handle 565fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + " type " + type + " value " + statusValue); 566fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 567fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (statusValue == BluetoothMapAppParams.STATUS_VALUE_YES) { 568fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) { 569fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = deleteMessageSms(handle); 570fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (type == TYPE.MMS) { 571fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = deleteMessageMms(handle); 572fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 573fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (statusValue == BluetoothMapAppParams.STATUS_VALUE_NO) { 574fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) { 575fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = unDeleteMessageSms(handle); 576fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (type == TYPE.MMS) { 577fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie res = unDeleteMessageMms(handle); 578fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 579fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 580fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 581fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 582fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 583fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public boolean setMessageStatusRead(long handle, TYPE type, int statusValue) { 584fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean res = true; 585fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 586fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "setMessageStatusRead: handle " + handle 587fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie + " type " + type + " value " + statusValue); 588fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 589fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Approved MAP spec errata 3445 states that read status initiated */ 590fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* by the MCE shall change the MSE read status. */ 591fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 592fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) { 593fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle); 594fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 595fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 596fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 597fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Sms.READ, statusValue); 598fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 599fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (type == TYPE.MMS) { 600fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle); 601fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(uri, null, null, null, null); 602fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 603fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(); 604fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Mms.READ, statusValue); 605fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(uri, contentValues, null, null); 606fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 607fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 608fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return res; 609fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 610fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 611fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private class PushMsgInfo { 612fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id; 613fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int transparent; 614fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int retry; 615fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String phone; 616fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri; 617fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int parts; 618fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int partsSent; 619fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int partsDelivered; 620fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean resend; 621fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 622fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public PushMsgInfo(long id, int transparent, 623fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int retry, String phone, Uri uri) { 624fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.id = id; 625fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.transparent = transparent; 626fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.retry = retry; 627fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.phone = phone; 628fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.uri = uri; 629fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie this.resend = false; 630fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 631fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 632fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 633fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private Map<Long, PushMsgInfo> mPushMsgList = 634fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Collections.synchronizedMap(new HashMap<Long, PushMsgInfo>()); 635fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 636fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public long pushMessage(BluetoothMapbMessage msg, String folder, 637fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothMapAppParams ap) throws IllegalArgumentException { 638fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "pushMessage"); 639fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ArrayList<BluetoothMapbMessage.vCard> recipientList = msg.getRecipients(); 640fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int transparent = (ap.getTransparent() == BluetoothMapAppParams.INVALID_VALUE_PARAMETER) ? 641fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 0 : ap.getTransparent(); 642fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int retry = ap.getRetry(); 643fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int charset = ap.getCharset(); 644fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long handle = -1; 645fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 646fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (recipientList == null) { 647fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "empty recipient list"); 648fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return -1; 649fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 650fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 651fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for (BluetoothMapbMessage.vCard recipient : recipientList) { 652fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if(recipient.getEnvLevel() == 0) // Only send the message to the top level recipient 653fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie { 654fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Only send to first address */ 655fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String phone = recipient.getFirstPhoneNumber(); 656fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean read = false; 657fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean deliveryReport = true; 658fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 659fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie switch(msg.getType()){ 660fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie case MMS: 661fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie { 662fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Send message if folder is outbox */ 663c3ec58fcc54cb33635f4dee746ee22cb8b0e3210Zhihai Xu /* to do, support MMS in the future */ 664c3ec58fcc54cb33635f4dee746ee22cb8b0e3210Zhihai Xu /* 665fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folder.equals("outbox")) { 666fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handle = sendMmsMessage(folder, phone, (BluetoothMapbMessageMmsEmail)msg); 667fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 668c3ec58fcc54cb33635f4dee746ee22cb8b0e3210Zhihai Xu */ 669fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie break; 670fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 671fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie case SMS_GSM: //fall-through 672fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie case SMS_CDMA: 673fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie { 674fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Add the message to the database */ 675fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String msgBody = ((BluetoothMapbMessageSms) msg).getSmsBody(); 676fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri contentUri = Uri.parse("content://sms/" + folder); 677fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = Sms.addMessageToUri(mResolver, contentUri, phone, msgBody, 678fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "", System.currentTimeMillis(), read, deliveryReport); 679fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 680fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (uri == null) { 681fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "pushMessage - failure on add to uri " + contentUri); 682fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return -1; 683fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 684fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 685fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handle = Long.parseLong(uri.getLastPathSegment()); 686fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 687fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Send message if folder is outbox */ 688fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folder.equals("outbox")) { 689fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo = new PushMsgInfo(handle, transparent, 690fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie retry, phone, uri); 691fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mPushMsgList.put(handle, msgInfo); 692fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendMessage(msgInfo, msgBody); 693fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 694fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie break; 695fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 696fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie case EMAIL: 697fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie { 698fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie break; 699fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 700fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 701fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 702fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 703fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 704fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 705fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* If multiple recipients return handle of last */ 706fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return handle; 707fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 708fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 709fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 710fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 711fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public long sendMmsMessage(String folder,String to_address, BluetoothMapbMessageMmsEmail msg) { 712fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* 713fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *strategy: 714fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *1) parse message into parts 715fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *if folder is outbox/drafts: 716fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *2) push message to draft 717fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *if folder is outbox: 718fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *3) move message to outbox (to trigger the mms app to add msg to pending_messages list) 719fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *4) send intent to mms app in order to wake it up. 720fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *else if folder !outbox: 721fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie *1) push message to folder 722fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * */ 723fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (folder != null && (folder.equalsIgnoreCase("outbox")|| folder.equalsIgnoreCase("drafts"))) { 724fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long handle = pushMmsToFolder(Mms.MESSAGE_BOX_DRAFTS, to_address, msg); 725fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* if invalid handle (-1) then just return the handle - else continue sending (if folder is outbox) */ 726fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (BluetoothMapAppParams.INVALID_VALUE_PARAMETER != handle && folder.equalsIgnoreCase("outbox")) { 727fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie moveDraftToOutbox(handle); 728fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 729fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Intent sendIntent = new Intent("android.intent.action.MMS_SEND_OUTBOX_MSG"); 730fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "broadcasting intent: "+sendIntent.toString()); 731fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mContext.sendBroadcast(sendIntent); 732fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 733fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return handle; 734fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 735fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* not allowed to push mms to anything but outbox/drafts */ 736fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie throw new IllegalArgumentException("Cannot push message to other folders than outbox/drafts"); 737fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 738fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 739fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 740fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 741fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 742fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void moveDraftToOutbox(long handle) { 743fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentResolver contentResolver = mContext.getContentResolver(); 744fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /*Move message by changing the msg_box value in the content provider database */ 745fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (handle != -1) { 746fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String whereClause = " _id= " + handle; 747fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = Uri.parse("content://mms"); 748fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor queryResult = contentResolver.query(uri, null, whereClause, null, null); 749fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (queryResult != null) { 750fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (queryResult.getCount() > 0) { 751fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie queryResult.moveToFirst(); 752fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues data = new ContentValues(); 753fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* set folder to be outbox */ 754fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie data.put("msg_box", Mms.MESSAGE_BOX_OUTBOX); 755fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentResolver.update(uri, data, whereClause, null); 756fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "moved draft MMS to outbox"); 757fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 758fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie queryResult.close(); 759fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }else { 760fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Could not move draft to outbox "); 761fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 762fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 763fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 764fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private long pushMmsToFolder(int folder, String to_address, BluetoothMapbMessageMmsEmail msg) { 765fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 766fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * strategy: 767fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * 1) parse msg into parts + header 768fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * 2) create thread id (abuse the ease of adding an SMS to get id for thread) 769fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * 3) push parts into content://mms/parts/ table 770fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * 3) 771fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 772fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 773fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues values = new ContentValues(); 774fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("msg_box", folder); 775fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 776fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("read", 0); 777fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("seen", 0); 77870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("sub", msg.getSubject()); 779fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("sub_cs", 106); 780fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("ct_t", "application/vnd.wap.multipart.related"); 781fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("exp", 604800); 782fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("m_cls", PduHeaders.MESSAGE_CLASS_PERSONAL_STR); 783fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("m_type", PduHeaders.MESSAGE_TYPE_SEND_REQ); 784fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("v", PduHeaders.CURRENT_MMS_VERSION); 785fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("pri", PduHeaders.PRIORITY_NORMAL); 786fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("rr", PduHeaders.VALUE_NO); 787fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("tr_id", "T"+ Long.toHexString(System.currentTimeMillis())); 788fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("d_rpt", PduHeaders.VALUE_NO); 789fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("locked", 0); 79070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(msg.getTextOnly() == true) 79170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("text_only", true); 79270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz 79370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("m_size", msg.getSize()); 79470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz 795fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // Get thread id 796fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Set<String> recipients = new HashSet<String>(); 797fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie recipients.addAll(Arrays.asList(to_address)); 798fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("thread_id", Telephony.Threads.getOrCreateThreadId(mContext, recipients)); 799fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri uri = Uri.parse("content://mms"); 800fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 801fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentResolver cr = mContext.getContentResolver(); 802fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = cr.insert(uri, values); 803fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 804fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (uri == null) { 805fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // unable to insert MMS 806fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "Unabled to insert MMS " + values + "Uri: " + uri); 807fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return -1; 808fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 809fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 810fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long handle = Long.parseLong(uri.getLastPathSegment()); 811fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V){ 812fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.v(TAG, " NEW URI " + uri.toString()); 813fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 814fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 81570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(V) Log.v(TAG, "Adding " + msg.getMimeParts().size() + " parts to the data base."); 816fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for(MimePart part : msg.getMimeParts()) { 81770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz int count = 0; 81870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz count++; 819fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.clear(); 820fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if(part.contentType != null && part.contentType.toUpperCase().contains("TEXT")) { 821fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("ct", "text/plain"); 822fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("chset", 106); 82370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.partName != null) { 82470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("fn", part.partName); 82570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("name", part.partName); 82670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz } else if(part.contentId == null && part.contentLocation == null) { 82770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz /* We must set at least one part identifier */ 82870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("fn", "text_" + count +".txt"); 82970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("name", "text_" + count +".txt"); 83070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz } 83170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentId != null) { 83270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cid", part.contentId); 83370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz } 83470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentLocation != null) 83570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cl", part.contentLocation); 83670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentDisposition != null) 83770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cd", part.contentDisposition); 838fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("text", new String(part.data, "UTF-8")); 839fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = Uri.parse("content://mms/" + handle + "/part"); 840fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = cr.insert(uri, values); 84170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(V) Log.v(TAG, "Added TEXT part"); 842fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 843fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (part.contentType != null && part.contentType.toUpperCase().contains("SMIL")){ 844fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 845fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("seq", -1); 846fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("ct", "application/smil"); 84770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentId != null) 84870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cid", part.contentId); 84970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentLocation != null) 85070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cl", part.contentLocation); 85170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentDisposition != null) 85270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cd", part.contentDisposition); 853fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("fn", "smil.xml"); 854fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("name", "smil.xml"); 855fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("text", new String(part.data, "UTF-8")); 856fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 857fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = Uri.parse("content://mms/" + handle + "/part"); 858fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = cr.insert(uri, values); 85970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(V) Log.v(TAG, "Added SMIL part"); 860fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 861fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }else /*VIDEO/AUDIO/IMAGE*/ { 86270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz writeMmsDataPart(handle, part, count); 86370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(V) Log.v(TAG, "Added OTHER part"); 864fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 865fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (uri != null && V){ 866fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.v(TAG, "Added part with content-type: "+ part.contentType + " to Uri: " + uri.toString()); 867fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 868fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 869fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (UnsupportedEncodingException e) { 87070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz Log.w(TAG, e); 871fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 87270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz Log.w(TAG, e); 873fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 874fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 875fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.clear(); 876fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("contact_id", "null"); 877fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("address", "insert-address-token"); 878fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("type", BluetoothMapContent.MMS_FROM); 879fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("charset", 106); 880fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 881fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = Uri.parse("content://mms/" + handle + "/addr"); 882fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = cr.insert(uri, values); 883fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (uri != null && V){ 884fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.v(TAG, " NEW URI " + uri.toString()); 885fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 886fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 887fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.clear(); 888fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("contact_id", "null"); 889fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("address", to_address); 890fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("type", BluetoothMapContent.MMS_TO); 891fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("charset", 106); 892fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 893fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = Uri.parse("content://mms/" + handle + "/addr"); 894fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie uri = cr.insert(uri, values); 895fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (uri != null && V){ 896fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.v(TAG, " NEW URI " + uri.toString()); 897fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 898fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return handle; 899fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 900fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 901fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 90270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz private void writeMmsDataPart(long handle, MimePart part, int count) throws IOException{ 903fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues values = new ContentValues(); 904fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie values.put("mid", handle); 90570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentType != null) 90670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("ct", part.contentType); 90770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentId != null) 90870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cid", part.contentId); 90970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentLocation != null) 91070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cl", part.contentLocation); 91170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.contentDisposition != null) 91270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("cd", part.contentDisposition); 91370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz if(part.partName != null) { 91470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("fn", part.partName); 91570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("name", part.partName); 91670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz } else if(part.contentId == null && part.contentLocation == null) { 91770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz /* We must set at least one part identifier */ 91870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("fn", "part_" + count + ".dat"); 91970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz values.put("name", "part_" + count + ".dat"); 92070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz } 921fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri partUri = Uri.parse("content://mms/" + handle + "/part"); 922fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri res = mResolver.insert(partUri, values); 923fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 924fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // Add data to part 925fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie OutputStream os = mResolver.openOutputStream(res); 92670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz os.write(part.data); 927fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie os.close(); 928fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 929fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 930fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 931fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void sendMessage(PushMsgInfo msgInfo, String msgBody) { 932fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 933fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie SmsManager smsMng = SmsManager.getDefault(); 934fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ArrayList<String> parts = smsMng.divideMessage(msgBody); 935fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgInfo.parts = parts.size(); 936fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 937fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(msgInfo.parts); 938fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(msgInfo.parts); 939fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 940fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for (int i = 0; i < msgInfo.parts; i++) { 941fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Intent intent; 942fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intent = new Intent(ACTION_MESSAGE_DELIVERY, null); 943fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intent.putExtra("HANDLE", msgInfo.id); 944fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie deliveryIntents.add(PendingIntent.getBroadcast(mContext, 0, intent, 945fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PendingIntent.FLAG_UPDATE_CURRENT)); 946fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 947fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intent = new Intent(ACTION_MESSAGE_SENT, null); 948fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intent.putExtra("HANDLE", msgInfo.id); 949fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sentIntents.add(PendingIntent.getBroadcast(mContext, 0, intent, 950fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PendingIntent.FLAG_UPDATE_CURRENT)); 951fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 952fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 953fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "sendMessage to " + msgInfo.phone); 954fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 955fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie smsMng.sendMultipartTextMessage(msgInfo.phone, null, parts, sentIntents, 956fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie deliveryIntents); 957fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 958fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 959fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String ACTION_MESSAGE_DELIVERY = 960fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY"; 961fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String ACTION_MESSAGE_SENT = 962fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT"; 963fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 964fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private SmsBroadcastReceiver mSmsBroadcastReceiver = new SmsBroadcastReceiver(); 965fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 966fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private class SmsBroadcastReceiver extends BroadcastReceiver { 967fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private final String[] ID_PROJECTION = new String[] { Sms._ID }; 968fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private final Uri UPDATE_STATUS_URI = Uri.parse("content://sms/status"); 969fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 970fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void register() { 971fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Handler handler = new Handler(); 972fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 973fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie IntentFilter intentFilter = new IntentFilter(); 974fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intentFilter.addAction(ACTION_MESSAGE_DELIVERY); 975fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie intentFilter.addAction(ACTION_MESSAGE_SENT); 976fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mContext.registerReceiver(this, intentFilter, null, handler); 977fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 978fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 979fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void unregister() { 980fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 981fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mContext.unregisterReceiver(this); 982fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IllegalArgumentException e) { 983fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* do nothing */ 984fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 985fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 986fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 987fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie @Override 988fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void onReceive(Context context, Intent intent) { 989fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String action = intent.getAction(); 990fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long handle = intent.getLongExtra("HANDLE", -1); 991fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo = mPushMsgList.get(handle); 992fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 993fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "onReceive: action" + action); 994fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 995fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo == null) { 996fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "onReceive: no msgInfo found for handle " + handle); 997fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return; 998fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 999fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1000fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (action.equals(ACTION_MESSAGE_SENT)) { 1001fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgInfo.partsSent++; 1002fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo.partsSent == msgInfo.parts) { 1003fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie actionMessageSent(context, intent, msgInfo); 1004fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1005fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else if (action.equals(ACTION_MESSAGE_DELIVERY)) { 1006fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgInfo.partsDelivered++; 1007fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo.partsDelivered == msgInfo.parts) { 1008fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie actionMessageDelivery(context, intent, msgInfo); 1009fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1010fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1011fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "onReceive: Unknown action " + action); 1012fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1013fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1014fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1015fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void actionMessageSent(Context context, Intent intent, 1016fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo) { 1017fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int result = getResultCode(); 1018fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean delete = false; 1019fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1020fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (result == Activity.RESULT_OK) { 1021fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "actionMessageSent: result OK"); 1022fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo.transparent == 0) { 1023fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (!Sms.moveMessageToFolder(context, msgInfo.uri, 1024fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.MESSAGE_TYPE_SENT, 0)) { 1025fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Failed to move " + msgInfo.uri + " to SENT"); 1026fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1027fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1028fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie delete = true; 1029fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1030fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1031fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("SendingSuccess", msgInfo.id, 1032fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[Sms.MESSAGE_TYPE_SENT], null, mSmsType); 1033fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 1034fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1035fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1036fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo.retry == 1) { 1037fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Notify failure, but keep message in outbox for resending */ 1038fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie msgInfo.resend = true; 1039fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("SendingFailure", msgInfo.id, 1040fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[Sms.MESSAGE_TYPE_OUTBOX], null, mSmsType); 1041fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 1042fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1043fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo.transparent == 0) { 1044fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (!Sms.moveMessageToFolder(context, msgInfo.uri, 1045fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.MESSAGE_TYPE_FAILED, 0)) { 1046fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Failed to move " + msgInfo.uri + " to FAILED"); 1047fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1048fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1049fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie delete = true; 1050fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1051fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1052fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("SendingFailure", msgInfo.id, 1053fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[Sms.MESSAGE_TYPE_FAILED], null, mSmsType); 1054fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 1055fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1056fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1057fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1058fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (delete == true) { 1059fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete from Observer message list to avoid delete notifications */ 1060fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mMsgListSms.remove(msgInfo.id); 1061fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1062fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Delete from DB */ 1063fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.delete(msgInfo.uri, null, null); 1064fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1065fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1066fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1067fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void actionMessageDelivery(Context context, Intent intent, 1068fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo) { 1069fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri messageUri = intent.getData(); 1070fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie byte[] pdu = intent.getByteArrayExtra("pdu"); 1071fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String format = intent.getStringExtra("format"); 1072fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1073fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie SmsMessage message = SmsMessage.createFromPdu(pdu, format); 1074fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (message == null) { 1075fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "actionMessageDelivery: Can't get message from pdu"); 1076fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return; 1077fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1078fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int status = message.getStatus(); 1079fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1080fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor cursor = mResolver.query(msgInfo.uri, ID_PROJECTION, null, null, null); 1081fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1082fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 1083fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (cursor.moveToFirst()) { 1084fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int messageId = cursor.getInt(0); 1085fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1086fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Uri updateUri = ContentUris.withAppendedId(UPDATE_STATUS_URI, messageId); 1087fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean isStatusReport = message.isStatusReportMessage(); 1088fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1089fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "actionMessageDelivery: uri=" + messageUri + ", status=" + status + 1090fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ", isStatusReport=" + isStatusReport); 1091fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1092fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ContentValues contentValues = new ContentValues(2); 1093fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1094fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Sms.STATUS, status); 1095fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie contentValues.put(Inbox.DATE_SENT, System.currentTimeMillis()); 1096fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.update(updateUri, contentValues, null, null); 1097fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1098fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Can't find message for status update: " + messageUri); 1099fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1100fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } finally { 1101fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie cursor.close(); 1102fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1103fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1104fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (status == 0) { 1105fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("DeliverySuccess", msgInfo.id, 1106fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[Sms.MESSAGE_TYPE_SENT], null, mSmsType); 1107fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 1108fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 1109fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Event evt = new Event("DeliveryFailure", msgInfo.id, 1110fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie folderSms[Sms.MESSAGE_TYPE_SENT], null, mSmsType); 1111fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendEvent(evt); 1112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1113fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mPushMsgList.remove(msgInfo.id); 1115fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1116fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1117fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1118fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void registerPhoneServiceStateListener() { 1119fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie TelephonyManager tm = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE); 1120fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie tm.listen(mPhoneListener, PhoneStateListener.LISTEN_SERVICE_STATE); 1121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1123fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void unRegisterPhoneServiceStateListener() { 1124fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie TelephonyManager tm = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE); 1125fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie tm.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE); 1126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1128fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void resendPendingMessages() { 1129fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Send pending messages in outbox */ 1130fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX; 1131fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null, 1132fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie null); 1133fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1134fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 1135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 1136fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 1137fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String msgBody = c.getString(c.getColumnIndex(Sms.BODY)); 1138fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo = mPushMsgList.get(id); 1139fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo == null || msgInfo.resend == false) { 1140fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie continue; 1141fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1142fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie sendMessage(msgInfo, msgBody); 1143fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 1144fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie c.close(); 1145fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1146fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1147fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1148fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void failPendingMessages() { 1149fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Move pending messages from outbox to failed */ 1150fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX; 1151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null, 1152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie null); 1153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (c != null && c.moveToFirst()) { 1155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie do { 1156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie long id = c.getLong(c.getColumnIndex(BaseColumns._ID)); 1157fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie String msgBody = c.getString(c.getColumnIndex(Sms.BODY)); 1158fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie PushMsgInfo msgInfo = mPushMsgList.get(id); 1159fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (msgInfo == null || msgInfo.resend == false) { 1160fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie continue; 1161fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1162fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.moveMessageToFolder(mContext, msgInfo.uri, 1163fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Sms.MESSAGE_TYPE_FAILED, 0); 1164fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } while (c.moveToNext()); 1165fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1166fac695e2dc25510b12684217d066b86dbbbba176Zhihai Xu if (c != null) c.close(); 1167fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1168fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1169fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void removeDeletedMessages() { 1170fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Remove messages from virtual "deleted" folder (thread_id -1) */ 1171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mResolver.delete(Uri.parse("content://sms/"), 1172fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie "thread_id = " + DELETED_THREAD_ID, null); 1173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private PhoneStateListener mPhoneListener = new PhoneStateListener() { 1176fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie @Override 1177fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void onServiceStateChanged(ServiceState serviceState) { 1178fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.d(TAG, "Phone service state change: " + serviceState.getState()); 1179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) { 1180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie resendPendingMessages(); 1181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie }; 1184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void init() { 1186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mSmsBroadcastReceiver.register(); 1187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie registerPhoneServiceStateListener(); 1188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 1190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void deinit() { 1191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mSmsBroadcastReceiver.unregister(); 1192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie unRegisterPhoneServiceStateListener(); 1193fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie failPendingMessages(); 1194fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie removeDeletedMessages(); 1195fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 1196fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie} 1197