1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/*
25a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Copyright (C) 2014 Samsung System LSI
35a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Licensed under the Apache License, Version 2.0 (the "License");
45a60e47497f21f64e6d79420dc4c56c1907df22akschulz * you may not use this file except in compliance with the License.
55a60e47497f21f64e6d79420dc4c56c1907df22akschulz * You may obtain a copy of the License at
65a60e47497f21f64e6d79420dc4c56c1907df22akschulz *
75a60e47497f21f64e6d79420dc4c56c1907df22akschulz *      http://www.apache.org/licenses/LICENSE-2.0
85a60e47497f21f64e6d79420dc4c56c1907df22akschulz *
95a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Unless required by applicable law or agreed to in writing, software
105a60e47497f21f64e6d79420dc4c56c1907df22akschulz * distributed under the License is distributed on an "AS IS" BASIS,
115a60e47497f21f64e6d79420dc4c56c1907df22akschulz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125a60e47497f21f64e6d79420dc4c56c1907df22akschulz * See the License for the specific language governing permissions and
135a60e47497f21f64e6d79420dc4c56c1907df22akschulz * limitations under the License.
145a60e47497f21f64e6d79420dc4c56c1907df22akschulz */
15fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepackage com.android.bluetooth.map;
16fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
175a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport android.annotation.TargetApi;
18fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.app.Activity;
19fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.app.PendingIntent;
20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.BroadcastReceiver;
21326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.content.ContentProviderClient;
22fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentResolver;
23fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentUris;
24fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.ContentValues;
25fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Context;
26fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Intent;
27fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.IntentFilter;
28326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.content.IntentFilter.MalformedMimeTypeException;
29edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chouimport android.content.pm.PackageManager;
30fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.database.ContentObserver;
31fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.database.Cursor;
320905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panickerimport android.database.sqlite.SQLiteException;
33fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.net.Uri;
34edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chouimport android.os.Binder;
35fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Handler;
365a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport android.os.Looper;
37326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.Message;
38326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.ParcelFileDescriptor;
39edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chouimport android.os.Process;
40326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.RemoteException;
41db8d8ae565b3db6a5e3187170dcb7b281a79f9daAjay Panickerimport android.os.UserManager;
42fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony;
43fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Mms;
44fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.MmsSms;
45fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms;
46fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms.Inbox;
47fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.PhoneStateListener;
48fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.ServiceState;
49fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsManager;
50fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsMessage;
51fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.TelephonyManager;
52326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.text.format.DateUtils;
53eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssenimport android.text.TextUtils;
54fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log;
55fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Xml;
565a60e47497f21f64e6d79420dc4c56c1907df22akschulz
575a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport org.xmlpull.v1.XmlSerializer;
58fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
59fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.map.BluetoothMapUtils.TYPE;
605a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.map.BluetoothMapbMessageMime.MimePart;
615a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.mapapi.BluetoothMapContract;
625a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.mapapi.BluetoothMapContract.MessageColumns;
63fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.google.android.mms.pdu.PduHeaders;
64fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
655a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.FileNotFoundException;
665a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.FileOutputStream;
675a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.IOException;
685a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.OutputStream;
695a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.StringWriter;
705a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.UnsupportedEncodingException;
715a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.ArrayList;
725a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Arrays;
735a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Calendar;
745a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Collections;
755a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.HashMap;
765a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.HashSet;
775a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Map;
785a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Set;
795a60e47497f21f64e6d79420dc4c56c1907df22akschulz
805a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport javax.obex.ResponseCodes;
815a60e47497f21f64e6d79420dc4c56c1907df22akschulz
825a60e47497f21f64e6d79420dc4c56c1907df22akschulz@TargetApi(19)
83fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepublic class BluetoothMapContentObserver {
84fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String TAG = "BluetoothMapContentObserver";
85fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
86326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final boolean D = BluetoothMapService.DEBUG;
87326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final boolean V = BluetoothMapService.VERBOSE;
88326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
895a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_NEW              = "NewMessage";
905a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_DELETE           = "MessageDeleted";
915a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_REMOVED          = "MessageRemoved";
925a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_SHIFT            = "MessageShift";
93326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_DELEVERY_SUCCESS = "DeliverySuccess";
94326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_SENDING_SUCCESS  = "SendingSuccess";
95326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_SENDING_FAILURE  = "SendingFailure";
96326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_DELIVERY_FAILURE = "DeliveryFailure";
975a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_READ_STATUS      = "ReadStatusChanged";
985a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_CONVERSATION     = "ConversationChanged";
995a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_PRESENCE         = "ParticipantPresenceChanged";
1005a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_CHAT_STATE       = "ParticipantChatStateChanged";
1015a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1025a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_NEW_MESSAGE                  = 1L;
1035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_DELETED              = 1L<<1;
1045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_SHIFT                = 1L<<2;
1055a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_SENDING_SUCCESS              = 1L<<3;
1065a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_SENDING_FAILED               = 1L<<4;
1075a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_DELIVERY_SUCCESS             = 1L<<5;
1085a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_DELIVERY_FAILED              = 1L<<6;
1095a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MEMORY_FULL                  = 1L<<7; // Unused
1105a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MEMORY_AVAILABLE             = 1L<<8; // Unused
1115a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_READ_STATUS_CHANGED          = 1L<<9;
1125a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_CONVERSATION_CHANGED         = 1L<<10;
1135a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_PARTICIPANT_PRESENCE_CHANGED = 1L<<11;
1145a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_PARTICIPANT_CHATSTATE_CHANGED= 1L<<12;
1155a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_REMOVED              = 1L<<13;
1165a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1175a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // TODO: If we are requesting a large message from the network, on a slow connection
1185a60e47497f21f64e6d79420dc4c56c1907df22akschulz    //       20 seconds might not be enough... But then again 20 seconds is long for other
1195a60e47497f21f64e6d79420dc4c56c1907df22akschulz    //       cases.
120326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private Context mContext;
123fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private ContentResolver mResolver;
124326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private ContentProviderClient mProviderClient = null;
125fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private BluetoothMnsObexClient mMnsClient;
126326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private BluetoothMapMasInstance mMasInstance = null;
127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private int mMasId;
128326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mEnableSmsMms = false;
129326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mObserverRegistered = false;
1305a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private BluetoothMapAccountItem mAccount;
131326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private String mAuthority = null;
132326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // Default supported feature bit mask is 0x1f
1345a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private int mMapSupportedFeatures = BluetoothMapUtils.MAP_FEATURE_DEFAULT_BITMASK;
1355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // Default event report version is 1.0
1365a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private int mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V10;
1375a60e47497f21f64e6d79420dc4c56c1907df22akschulz
138326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private BluetoothMapFolderElement mFolders =
139326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            new BluetoothMapFolderElement("DUMMY", null); // Will be set by the MAS when generated.
140326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private Uri mMessageUri = null;
1415a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Uri mContactUri = null;
1425a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1435a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private boolean mTransmitEvents = true;
1445a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1455a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* To make the filter update atomic, we declare it volatile.
1465a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * To avoid a penalty when using it, copy the value to a local
1475a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * non-volatile variable when used more than once.
1485a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Actually we only ever use the lower 4 bytes of this variable,
1495a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * hence we could manage without the volatile keyword, but as
1505a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * we tend to copy ways of doing things, we better do it right:-) */
1515a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private volatile long mEventFilter = 0xFFFFFFFFL;
152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int DELETED_THREAD_ID = -1;
154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
155326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    // X-Mms-Message-Type field types. These are from PduHeaders.java
156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84;
157fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
158326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    // Text only MMS converted to SMS if sms parts less than or equal to defined count
159326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int CONVERT_MMS_TO_SMS_PART_COUNT = 10;
160326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
161fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private TYPE mSmsType;
162fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
163ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private static final String ACTION_MESSAGE_DELIVERY =
164ed70219e41ba68196798dcbf75b782d13fb88603kschulz            "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY";
165ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /*package*/ static final String ACTION_MESSAGE_SENT =
166ed70219e41ba68196798dcbf75b782d13fb88603kschulz        "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT";
167ed70219e41ba68196798dcbf75b782d13fb88603kschulz
168ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_HANDLE = "HANDLE";
169ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_RESULT = "result";
170ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_MSG_TYPE = "type";
171ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_URI = "uri";
172ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_RETRY = "retry";
173ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_TRANSPARENT = "transparent";
174ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_TIMESTAMP = "timestamp";
175ed70219e41ba68196798dcbf75b782d13fb88603kschulz
176ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private SmsBroadcastReceiver mSmsBroadcastReceiver = new SmsBroadcastReceiver();
177725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker    private CeBroadcastReceiver mCeBroadcastReceiver = new CeBroadcastReceiver();
178ed70219e41ba68196798dcbf75b782d13fb88603kschulz
179725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker    private boolean mStorageUnlocked = false;
180ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private boolean mInitialized = false;
181ed70219e41ba68196798dcbf75b782d13fb88603kschulz
182ed70219e41ba68196798dcbf75b782d13fb88603kschulz
183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    static final String[] SMS_PROJECTION = new String[] {
184326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms._ID,
185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.THREAD_ID,
186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.ADDRESS,
187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.BODY,
188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.DATE,
189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.READ,
190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.TYPE,
191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.STATUS,
192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.LOCKED,
193326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms.ERROR_CODE
194fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
195fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
196326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static final String[] SMS_PROJECTION_SHORT = new String[] {
197326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms._ID,
198326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms.THREAD_ID,
1995a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.TYPE,
2005a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.READ
2015a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
2025a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] SMS_PROJECTION_SHORT_EXT = new String[] {
2045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms._ID,
2055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.THREAD_ID,
2065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.ADDRESS,
2075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.BODY,
2085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.DATE,
2095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.READ,
2105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.TYPE,
211326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    };
212326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
213326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static final String[] MMS_PROJECTION_SHORT = new String[] {
214326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Mms._ID,
215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Mms.THREAD_ID,
216fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Mms.MESSAGE_TYPE,
2175a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_BOX,
2185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.READ
2195a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
2205a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2215a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MMS_PROJECTION_SHORT_EXT = new String[] {
2225a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms._ID,
2235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.THREAD_ID,
2245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_TYPE,
2255a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_BOX,
2265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.READ,
2275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.DATE,
2285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.SUBJECT,
2295a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.PRIORITY
230fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
231fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2325a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT = new String[] {
233326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns._ID,
234326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns.FOLDER_ID,
235326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns.FLAG_READ
236326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    };
237326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2385a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT_EXT = new String[] {
2395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns._ID,
2405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FOLDER_ID,
2415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_READ,
2425a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.DATE,
2435a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.SUBJECT,
2445a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FROM_LIST,
2455a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY
2465a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
2475a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2485a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT_EXT2 = new String[] {
2495a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns._ID,
2505a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FOLDER_ID,
2515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_READ,
2525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.DATE,
2535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.SUBJECT,
2545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FROM_LIST,
2555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY,
2565a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.THREAD_ID,
2575a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.THREAD_NAME
2585a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
259326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
260326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public BluetoothMapContentObserver(final Context context,
2615a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMnsObexClient mnsClient,
2625a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMapMasInstance masInstance,
2635a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMapAccountItem account,
2645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            boolean enableSmsMms) throws RemoteException {
265fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mContext = context;
266fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mResolver = mContext.getContentResolver();
267326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mAccount = account;
268326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMasInstance = masInstance;
269326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMasId = mMasInstance.getMasId();
2705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2715a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMapSupportedFeatures = mMasInstance.getRemoteFeatureMask();
2725a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (D) Log.d(TAG, "BluetoothMapContentObserver: Supported features " +
2735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Integer.toHexString(mMapSupportedFeatures) ) ;
2745a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2755a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if((BluetoothMapUtils.MAP_FEATURE_EXTENDED_EVENT_REPORT_11_BIT
2765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                & mMapSupportedFeatures) != 0){
2775a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
2785a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
2795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // Make sure support for all formats result in latest version returned
2805a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if((BluetoothMapUtils.MAP_FEATURE_EVENT_REPORT_V12_BIT
2815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                & mMapSupportedFeatures) != 0){
2825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
2845a60e47497f21f64e6d79420dc4c56c1907df22akschulz
285326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(account != null) {
286326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mAuthority = Uri.parse(account.mBase_uri).getAuthority();
287326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mMessageUri = Uri.parse(account.mBase_uri + "/" + BluetoothMapContract.TABLE_MESSAGE);
2885a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (mAccount.getType() == TYPE.IM) {
2895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mContactUri = Uri.parse(account.mBase_uri + "/"
2905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + BluetoothMapContract.TABLE_CONVOCONTACT);
2915a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO: We need to release this again!
293326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient = mResolver.acquireUnstableContentProviderClient(mAuthority);
294326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (mProviderClient == null) {
295326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                throw new RemoteException("Failed to acquire provider for " + mAuthority);
296326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
297326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
2985a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactList = mMasInstance.getContactList();
2995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mContactList == null) {
3005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setContactList(new HashMap<String, BluetoothMapConvoContactElement>(), false);
3015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                initContactsList();
3025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
303326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
304326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mEnableSmsMms = enableSmsMms;
305fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mSmsType = getSmsType();
306326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMnsClient = mnsClient;
3075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Get the cached list - if any, else create */
3085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListSms = mMasInstance.getMsgListSms();
3095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean doInit = false;
3105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mEnableSmsMms) {
3115a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListSms == null) {
3125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListSms(new HashMap<Long, Msg>(), false);
3135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3145a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3155a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMsgListMms = mMasInstance.getMsgListMms();
3165a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListMms == null) {
3175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMms(new HashMap<Long, Msg>(), false);
3185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3205a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mAccount != null) {
3225a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMsgListMsg = mMasInstance.getMsgListMsg();
3235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListMsg == null) {
3245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMsg(new HashMap<Long, Msg>(), false);
3255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(doInit) {
3295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            initMsgList();
3305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3315a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3325a60e47497f21f64e6d79420dc4c56c1907df22akschulz
333e6564029f132077c8a4877431a95899db201e506Ashwini Munigala    public int getObserverRemoteFeatureMask() {
334e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if (V) Log.v(TAG, "getObserverRemoteFeatureMask : " + mMapEventReportVersion
335e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            + " mMapSupportedFeatures: " + mMapSupportedFeatures);
336e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        return mMapSupportedFeatures;
337e6564029f132077c8a4877431a95899db201e506Ashwini Munigala    }
338e6564029f132077c8a4877431a95899db201e506Ashwini Munigala
339e6564029f132077c8a4877431a95899db201e506Ashwini Munigala    public void setObserverRemoteFeatureMask(int remoteSupportedFeatures) {
340e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        mMapSupportedFeatures = remoteSupportedFeatures;
341e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if ((BluetoothMapUtils.MAP_FEATURE_EXTENDED_EVENT_REPORT_11_BIT
342e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                & mMapSupportedFeatures) != 0) {
343e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
344e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        }
345e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        // Make sure support for all formats result in latest version returned
346e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if ((BluetoothMapUtils.MAP_FEATURE_EVENT_REPORT_V12_BIT
347e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                & mMapSupportedFeatures) != 0) {
348e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
349e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        }
350e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if (V) Log.d(TAG, "setObserverRemoteFeatureMask : " + mMapEventReportVersion
351e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            + " mMapSupportedFeatures : " + mMapSupportedFeatures);
352e6564029f132077c8a4877431a95899db201e506Ashwini Munigala    }
3535a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3545a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListSms() {
3555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListSms;
3565a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3575a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3585a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListSms(Map<Long, Msg> msgListSms, boolean changesDetected) {
3595a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListSms = msgListSms;
3605a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3615a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3625a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListSms(msgListSms);
3645a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3655a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3665a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3675a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListMms() {
3685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListMms;
3695a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3715a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3725a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListMms(Map<Long, Msg> msgListMms, boolean changesDetected) {
3735a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListMms = msgListMms;
3745a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListMms(msgListMms);
378326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
379326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3805a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3815a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListMsg() {
3825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListMsg;
3835a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3845a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3855a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3865a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListMsg(Map<Long, Msg> msgListMsg, boolean changesDetected) {
3875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListMsg = msgListMsg;
3885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3905a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListMsg(msgListMsg);
3925a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3935a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3945a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<String, BluetoothMapConvoContactElement> getContactList() {
3955a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mContactList;
3965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3975a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3985a60e47497f21f64e6d79420dc4c56c1907df22akschulz
399326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
4005a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Currently we only have data for IM / email contacts
4015a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param contactList
4025a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param changesDetected that is not chat state changed nor presence state changed.
403326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
4045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setContactList(Map<String, BluetoothMapConvoContactElement> contactList,
4055a60e47497f21f64e6d79420dc4c56c1907df22akschulz            boolean changesDetected) {
4065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mContactList = contactList;
4075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
4085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateImEmailConvoListVersionCounter();
4095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
4105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setContactList(contactList);
4115a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4125a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4135a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventNewMessage(long eventFilter) {
4145a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_NEW_MESSAGE) > 0);
4155a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4165a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4175a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageDeleted(long eventFilter) {
4185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_DELETED) > 0);
4195a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4205a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4215a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageShift(long eventFilter) {
4225a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_SHIFT) > 0);
4235a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4245a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4255a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventSendingSuccess(long eventFilter) {
4265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_SENDING_SUCCESS) > 0);
4275a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4285a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4295a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventSendingFailed(long eventFilter) {
4305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_SENDING_FAILED) > 0);
4315a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4325a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventDeliverySuccess(long eventFilter) {
4345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_DELIVERY_SUCCESS) > 0);
4355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4365a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4375a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventDeliveryFailed(long eventFilter) {
4385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_DELIVERY_FAILED) > 0);
4395a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4405a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4415a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventReadStatusChanged(long eventFilter) {
4425a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_READ_STATUS_CHANGED) > 0);
4435a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4445a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4455a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventConversationChanged(long eventFilter) {
4465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_CONVERSATION_CHANGED) > 0);
4475a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4485a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4495a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventParticipantPresenceChanged(long eventFilter) {
4505a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_PARTICIPANT_PRESENCE_CHANGED) > 0);
4515a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4525a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4535a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventParticipantChatstateChanged(long eventFilter) {
4545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_PARTICIPANT_CHATSTATE_CHANGED) > 0);
4555a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4565a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4575a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageRemoved(long eventFilter) {
4585a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_REMOVED) > 0);
459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
461fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private TYPE getSmsType() {
462fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        TYPE smsType = null;
4635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
4645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4662e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta        if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
467fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            smsType = TYPE.SMS_CDMA;
4682e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta        } else {
4692e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta            smsType = TYPE.SMS_GSM;
470fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
471fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return smsType;
473fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
474fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
475b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta    private final ContentObserver mObserver = new ContentObserver(new Handler()) {
476fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
477fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onChange(boolean selfChange) {
478fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            onChange(selfChange, null);
479fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
480fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
481fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
482fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onChange(boolean selfChange, Uri uri) {
4835a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(uri == null) {
4845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG, "onChange() with URI == null - not handled.");
4855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
4865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
487725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
488725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            if (!mStorageUnlocked) {
489725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                Log.v(TAG, "Ignore events until storage is completely unlocked");
490725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                return;
491725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            }
492725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
493fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (V) Log.d(TAG, "onChange on thread: " + Thread.currentThread().getId()
4945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    + " Uri: " + uri.toString() + " selfchange: " + selfChange);
495fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4965a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(uri.toString().contains(BluetoothMapContract.TABLE_CONVOCONTACT))
4975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleContactListChanges(uri);
4985a60e47497f21f64e6d79420dc4c56c1907df22akschulz            else
4995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChanges(uri);
500fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
501fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
502fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
5035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final HashMap<Integer, String> FOLDER_SMS_MAP;
5045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static {
5055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP = new HashMap<Integer, String>();
5065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_INBOX,  BluetoothMapContract.FOLDER_NAME_INBOX);
5075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_SENT,  BluetoothMapContract.FOLDER_NAME_SENT);
5085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_DRAFT,  BluetoothMapContract.FOLDER_NAME_DRAFT);
5095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_OUTBOX,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
5105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_FAILED,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
5115a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_QUEUED,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
5125a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
513fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
5145a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static String getSmsFolderName(int type) {
5155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String name = FOLDER_SMS_MAP.get(type);
5165a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(name != null) {
5175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return name;
5185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
5195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Log.e(TAG, "New SMS mailbox types have been introduced, without an update in BT...");
5205a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return "Unknown";
5215a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5225a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5235a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5245a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final HashMap<Integer, String> FOLDER_MMS_MAP;
5255a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static {
5265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP = new HashMap<Integer, String>();
5275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_INBOX,  BluetoothMapContract.FOLDER_NAME_INBOX);
5285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_SENT,   BluetoothMapContract.FOLDER_NAME_SENT);
5295a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_DRAFTS, BluetoothMapContract.FOLDER_NAME_DRAFT);
5305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_OUTBOX, BluetoothMapContract.FOLDER_NAME_OUTBOX);
5315a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5325a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static String getMmsFolderName(int mailbox) {
5345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String name = FOLDER_MMS_MAP.get(mailbox);
5355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(name != null) {
5365a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return name;
5375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
5385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Log.e(TAG, "New MMS mailboxes have been introduced, without an update in BT...");
5395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return "Unknown";
5405a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5415a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5425a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
5435a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Set the folder structure to be used for this instance.
5445a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param folderStructure
5455a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
5465a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public void setFolderStructure(BluetoothMapFolderElement folderStructure) {
5475a60e47497f21f64e6d79420dc4c56c1907df22akschulz        this.mFolders = folderStructure;
5485a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5495a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5505a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private class ConvoContactInfo {
5515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColConvoId         = -1;
5525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColLastActivity    = -1;
5535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColName            = -1;
5545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        //        public int mConvoColRead            = -1;
5555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        //        public int mConvoColVersionCounter  = -1;
5565a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColUci           = -1;
5575a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColConvoId       = -1;
5585a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColName          = -1;
5595a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColNickname      = -1;
5605a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColBtUid         = -1;
5615a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColChatState     = -1;
5625a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColContactId     = -1;
5635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColLastActive    = -1;
5645a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPresenceState = -1;
5655a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPresenceText  = -1;
5665a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPriority      = -1;
5675a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColLastOnline    = -1;
5685a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5695a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public void setConvoColunms(Cursor c) {
5705a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColConvoId         = c.getColumnIndex(
5715a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.THREAD_ID);
5725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColLastActivity    = c.getColumnIndex(
5735a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.LAST_THREAD_ACTIVITY);
5745a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColName            = c.getColumnIndex(
5755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.THREAD_NAME);
5765a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColConvoId       = c.getColumnIndex(
5775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.CONVO_ID);
5785a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColName          = c.getColumnIndex(
5795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NAME);
5805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColNickname      = c.getColumnIndex(
5815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NICKNAME);
5825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColBtUid         = c.getColumnIndex(
5835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.X_BT_UID);
5845a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColChatState     = c.getColumnIndex(
5855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.CHAT_STATE);
5865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColUci           = c.getColumnIndex(
5875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.UCI);
5885a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColNickname      = c.getColumnIndex(
5895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NICKNAME);
5905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColLastActive    = c.getColumnIndex(
5915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.LAST_ACTIVE);
5925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColName          = c.getColumnIndex(
5935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NAME);
5945a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPresenceState = c.getColumnIndex(
5955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.PRESENCE_STATE);
5965a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPresenceText  = c.getColumnIndex(
5975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.STATUS_TEXT);
5985a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPriority      = c.getColumnIndex(
5995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.PRIORITY);
6005a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColLastOnline    = c.getColumnIndex(
6015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.LAST_ONLINE);
6025a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
604fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
605fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class Event {
606fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String eventType;
607fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle;
6085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String folder = null;
6095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String oldFolder = null;
610fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        TYPE msgType;
6115a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Extended event parameters in MAP Event version 1.1 */
6125a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String datetime = null; // OBEX time "YYYYMMDDTHHMMSS"
6135a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String uci = null;
6145a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String subject = null;
6155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String senderName = null;
6165a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String priority = null;
6175a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Event parameters in MAP Event version 1.2 */
6185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String conversationName = null;
6195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long conversationID = -1;
6205a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int presenceState = BluetoothMapContract.PresenceState.UNKNOWN;
6215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String presenceStatus = null;
6225a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int chatState = BluetoothMapContract.ChatState.UNKNOWN;
623fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
624326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        final static String PATH = "telecom/msg/";
625326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
6265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        private void setFolderPath(String name, TYPE type) {
6275a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (name != null) {
6285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(type == TYPE.EMAIL || type == TYPE.IM) {
6295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    this.folder = name;
630326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
6315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    this.folder = PATH + name;
632326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
633fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
634fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                this.folder = null;
635fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
6365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6375a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder,
6395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String oldFolder, TYPE msgType) {
6405a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6415a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
643fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (oldFolder != null) {
6445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msgType == TYPE.EMAIL || msgType == TYPE.IM) {
645326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    this.oldFolder = oldFolder;
646326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
647326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    this.oldFolder = PATH + oldFolder;
648326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
649fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
650fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                this.oldFolder = null;
651fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
652fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.msgType = msgType;
653fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
654fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
6555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType) {
6565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6585a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6595a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6605a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6615a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6625a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.1 */
6635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType,
6645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String datetime, String subject, String senderName, String priority) {
6655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6675a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6695a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = datetime;
6705a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (subject != null) {
6715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.subject = BluetoothMapUtils.stripInvalidChars(subject);
6725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6735a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (senderName != null) {
6745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(senderName);
6755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6765a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
6775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6785a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.2 message events */
6805a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType,
6815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String datetime, String subject, String senderName, String priority,
6825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                long conversationID, String conversationName) {
6835a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6845a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = datetime;
6885a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (subject != null) {
6895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.subject = BluetoothMapUtils.stripInvalidChars(subject);
6905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6915a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (senderName != null) {
6925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(senderName);
6935a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6945a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationID != 0) {
6955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationID = conversationID;
6965a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6975a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationName != null) {
6985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationName = BluetoothMapUtils.stripInvalidChars(conversationName);
6995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7005a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
7015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
7025a60e47497f21f64e6d79420dc4c56c1907df22akschulz
7035a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.2 for conversation, presence or chat state changed events */
7045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, String uci, TYPE msgType, String name, String priority,
7055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String lastActivity, long conversationID, String conversationName,
7065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                int presenceState, String presenceStatus, int chatState) {
7075a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
7085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.uci = uci;
7095a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
7105a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (name != null) {
7115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(name);
7125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7135a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
7145a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = lastActivity;
7155a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationID != 0) {
7165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationID = conversationID;
7175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7185a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationName != null) {
7195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationName = BluetoothMapUtils.stripInvalidChars(conversationName);
7205a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7215a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (presenceState != BluetoothMapContract.PresenceState.UNKNOWN) {
7225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.presenceState = presenceState;
7235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7245a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (presenceStatus != null) {
7255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.presenceStatus = BluetoothMapUtils.stripInvalidChars(presenceStatus);
7265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7275a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (chatState != BluetoothMapContract.ChatState.UNKNOWN) {
7285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.chatState = chatState;
7295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
7315a60e47497f21f64e6d79420dc4c56c1907df22akschulz
732fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public byte[] encode() throws UnsupportedEncodingException {
733fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            StringWriter sw = new StringWriter();
734fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            XmlSerializer xmlEvtReport = Xml.newSerializer();
7355a60e47497f21f64e6d79420dc4c56c1907df22akschulz
736fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
737fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.setOutput(sw);
7385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                xmlEvtReport.startDocument("UTF-8", true);
739326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                xmlEvtReport.text("\r\n");
74070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                xmlEvtReport.startTag("", "MAP-event-report");
7415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
7425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V10_STR);
7435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
7445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V11_STR);
7455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
7465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V12_STR);
7475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
748fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.startTag("", "event");
749fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.attribute("", "type", eventType);
7505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (eventType.equals(EVENT_TYPE_CONVERSATION) ||
7515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        eventType.equals(EVENT_TYPE_PRESENCE) ||
7525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        eventType.equals(EVENT_TYPE_CHAT_STATE)) {
7535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "participant_uci", uci);
7545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
7555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "handle",
7565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapUtils.getMapHandle(handle, msgType));
7575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7585a60e47497f21f64e6d79420dc4c56c1907df22akschulz
759fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (folder != null) {
760fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    xmlEvtReport.attribute("", "folder", folder);
761fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
762fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (oldFolder != null) {
763fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    xmlEvtReport.attribute("", "old_folder", oldFolder);
764fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
7652e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                /* Avoid possible NPE for "msgType" "null" value. "msgType"
7662e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                 * is a implied attribute and will be set "null" for events
7672e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                 * like "memory full" or "memory available" */
7682e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                if (msgType != null) {
7692e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                    xmlEvtReport.attribute("", "msg_type", msgType.name());
7702e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                }
7715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* If MAP event report version is above 1.0 send
7725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * extended event report parameters */
7735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (datetime != null) {
7745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "datetime", datetime);
7755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (subject != null) {
7775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "subject",
7785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            subject.substring(0,subject.length() < 256 ? subject.length() : 256));
7795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (senderName != null) {
7819a18a9fc4349f90e49d036ccafc91d8b5befe973Ajay Panicker                    xmlEvtReport.attribute("", "sender_name", senderName);
7825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (priority != null) {
7845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "priority", priority);
7855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7865a60e47497f21f64e6d79420dc4c56c1907df22akschulz
7875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                //}
7885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Include conversation information from event version 1.2 */
7895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (mMapEventReportVersion > BluetoothMapUtils.MAP_EVENT_REPORT_V11 ) {
7905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (conversationName != null) {
7915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        xmlEvtReport.attribute("", "conversation_name", conversationName);
7925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (conversationID != -1) {
7945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        // Convert provider conversation handle to string incl type
7955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        xmlEvtReport.attribute("", "conversation_id",
7965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapUtils.getMapConvoHandle(conversationID, msgType));
7975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (eventType.equals(EVENT_TYPE_PRESENCE)) {
7995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (presenceState != 0) {
8005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
8015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "presence_availability",
8025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String.valueOf(presenceState));
8035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
8045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (presenceStatus != null) {
8055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
8065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "presence_status",
8075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    presenceStatus.substring(
8085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            0,presenceStatus.length() < 256 ? subject.length() : 256));
8095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
8105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
8115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (eventType.equals(EVENT_TYPE_PRESENCE)) {
8125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (chatState != 0) {
8135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
8145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "chat_state", String.valueOf(chatState));
8155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
8165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
8175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
8185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
8195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                xmlEvtReport.endTag("", "event");
82070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                xmlEvtReport.endTag("", "MAP-event-report");
821fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.endDocument();
822fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalArgumentException e) {
823326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
824fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalStateException e) {
825326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
826fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IOException e) {
827326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
828fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
829fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
830326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (V) Log.d(TAG, sw.toString());
831fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
832fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return sw.toString().getBytes("UTF-8");
833fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
834fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
835fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
8365a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /*package*/ class Msg {
837fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long id;
838326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int type;               // Used as folder for SMS/MMS
839326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int threadId;           // Used for SMS/MMS at delete
840326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long folderId = -1;     // Email folder ID
841326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long oldFolderId = -1;  // Used for email undelete
842326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean localInitiatedSend = false; // Used for MMS to filter out events
843326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean transparent = false; // Used for EMAIL to delete message sent with transparency
8445a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int flagRead = -1;      // Message status read/unread
845326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Msg(long id, int type, int threadId, int readFlag) {
847fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.id = id;
848fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.type = type;
849326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.threadId = threadId;
8505a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.flagRead = readFlag;
851326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
8525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Msg(long id, long folderId, int readFlag) {
853326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.id = id;
854326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.folderId = folderId;
8555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.flagRead = readFlag;
856326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
857326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
858326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* Eclipse generated hashCode() and equals() to make
859326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * hashMap lookup work independent of whether the obj
860326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * is used for email or SMS/MMS and whether or not the
861326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * oldFolder is set. */
862326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        @Override
863326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        public int hashCode() {
864326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            final int prime = 31;
865326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            int result = 1;
866326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            result = prime * result + (int) (id ^ (id >>> 32));
867326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return result;
868fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
869fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
870326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        @Override
871326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        public boolean equals(Object obj) {
872326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (this == obj)
873326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return true;
874326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (obj == null)
875326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
876326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (getClass() != obj.getClass())
877326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
878326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Msg other = (Msg) obj;
879326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (id != other.id)
880326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
881326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return true;
882326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
883326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
884fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
8855a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListSms = null;
8865a60e47497f21f64e6d79420dc4c56c1907df22akschulz
8875a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListMms = null;
888326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8895a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListMsg = null;
890326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8915a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<String, BluetoothMapConvoContactElement> mContactList = null;
892326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
893326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public int setNotificationRegistration(int notificationStatus) throws RemoteException {
894326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Forward the request to the MNS thread as a message - including the MAS instance ID.
895326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(D) Log.d(TAG,"setNotificationRegistration() enter");
896e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if (mMnsClient == null) {
897e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
898e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        }
899326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Handler mns = mMnsClient.getMessageHandler();
900e6564029f132077c8a4877431a95899db201e506Ashwini Munigala        if (mns != null) {
901326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Message msg = mns.obtainMessage();
902e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            if (mMnsClient.isValidMnsRecord()) {
903e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                msg.what = BluetoothMnsObexClient.MSG_MNS_NOTIFICATION_REGISTRATION;
904e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            } else {
905e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                //Trigger SDP Search and notificaiton registration , if SDP record not found.
906e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                msg.what = BluetoothMnsObexClient.MSG_MNS_SDP_SEARCH_REGISTRATION;
907e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                if (mMnsClient.mMnsLstRegRqst != null &&
908e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                        (mMnsClient.mMnsLstRegRqst.isSearchInProgress())) {
909e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                    /*  1. Disallow next Notification ON Request :
910e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                     *     - Respond "Service Unavailable" as SDP Search and last notification
911e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                     *       registration ON request is already InProgress.
912e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                     *     - Next notification ON Request will be allowed ONLY after search
913e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                     *       and connect for last saved request [Replied with OK ] is processed.
914e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                     */
915e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                    if (notificationStatus == BluetoothMapAppParams.NOTIFICATION_STATUS_YES) {
916e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                        return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
917e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                    } else {
918e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                        /*  2. Allow next Notification OFF Request:
919e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                         *    - Keep the SDP search still in progress.
920e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                         *    - Disconnect and Deregister the contentObserver.
921e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                         */
922e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                        msg.what = BluetoothMnsObexClient.MSG_MNS_NOTIFICATION_REGISTRATION;
923e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                    }
924e6564029f132077c8a4877431a95899db201e506Ashwini Munigala                }
925e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            }
926326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.arg1 = mMasId;
927326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.arg2 = notificationStatus;
928326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mns.sendMessageDelayed(msg, 10); // Send message without forcing a context switch
929326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Some devices - e.g. PTS needs to get the unregister confirm before we actually
930326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde             * disconnect the MNS. */
931e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            if(D) Log.d(TAG,"setNotificationRegistration() send : " + msg.what + " to MNS ");
932e6564029f132077c8a4877431a95899db201e506Ashwini Munigala            return ResponseCodes.OBEX_HTTP_OK;
933326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
934326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // This should not happen except at shutdown.
935326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG,"setNotificationRegistration() Unable to send registration request");
936326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
937326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
938326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
939fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
9405a60e47497f21f64e6d79420dc4c56c1907df22akschulz    boolean eventMaskContainsContacts(long mask) {
9415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return sendEventParticipantPresenceChanged(mask);
9425a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9435a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9445a60e47497f21f64e6d79420dc4c56c1907df22akschulz    boolean eventMaskContainsCovo(long mask) {
9455a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return (sendEventConversationChanged(mask)
9465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                || sendEventParticipantChatstateChanged(mask));
9475a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9485a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9495a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* Overwrite the existing notification filter. Will register/deregister observers for
9505a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * the Contacts and Conversation table as needed. We keep the message observer
9515a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * at all times. */
9525a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /*package*/ synchronized void setNotificationFilter(long newFilter) {
9535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long oldFilter = mEventFilter;
9545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mEventFilter = newFilter;
9555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Contacts */
9565a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(!eventMaskContainsContacts(oldFilter) &&
9575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                eventMaskContainsContacts(newFilter)) {
9585a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO:
9595a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Enable the observer
9605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Reset the contacts list
9615a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9625a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Conversations */
9635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(!eventMaskContainsCovo(oldFilter) &&
9645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                eventMaskContainsCovo(newFilter)) {
9655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO:
9665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Enable the observer
9675a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Reset the conversations list
9685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9695a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
971326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public void registerObserver() throws RemoteException{
972fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "registerObserver");
973326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
974326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (mObserverRegistered)
975326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return;
976326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
977326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mAccount != null) {
978326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
979326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient = mResolver.acquireUnstableContentProviderClient(mAuthority);
980326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (mProviderClient == null) {
981326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                throw new RemoteException("Failed to acquire provider for " + mAuthority);
982326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
983326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
984326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
9855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // If there is a change in the database before we init the lists we will be sending
9865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // loads of events - hence init before register.
9875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount.getType() == TYPE.IM) {
9885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                // Further add contact list tracking
9895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                initContactsList();
9905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
9915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9925a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // If there is a change in the database before we init the lists we will be sending
9935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // loads of events - hence init before register.
9945a60e47497f21f64e6d79420dc4c56c1907df22akschulz        initMsgList();
9955a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9965a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Use MmsSms Uri since the Sms Uri is not notified on deletes */
9975a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mEnableSmsMms){
9985a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //this is sms/mms
9995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mResolver.registerContentObserver(MmsSms.CONTENT_URI, false, mObserver);
10005a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mObserverRegistered = true;
10015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10025a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10035a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mAccount != null) {
1004326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* For URI's without account ID */
10055a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Uri uri = Uri.parse(mAccount.mBase_uri_no_account + "/"
10065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    + BluetoothMapContract.TABLE_MESSAGE);
1007326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG, "Registering observer for: " + uri);
1008326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mResolver.registerContentObserver(uri, true, mObserver);
1009326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1010326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* For URI's with account ID - is handled the same way as without ID, but is
1011326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde             * only triggered for MAS instances with matching account ID. */
1012326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            uri = Uri.parse(mAccount.mBase_uri + "/" + BluetoothMapContract.TABLE_MESSAGE);
1013326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG, "Registering observer for: " + uri);
1014326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mResolver.registerContentObserver(uri, true, mObserver);
10155a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10165a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount.getType() == TYPE.IM) {
10175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                uri = Uri.parse(mAccount.mBase_uri_no_account + "/"
10195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + BluetoothMapContract.TABLE_CONVOCONTACT);
10205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "Registering observer for: " + uri);
10215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mResolver.registerContentObserver(uri, true, mObserver);
10225a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* For URI's with account ID - is handled the same way as without ID, but is
10245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * only triggered for MAS instances with matching account ID. */
10255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                uri = Uri.parse(mAccount.mBase_uri + "/" + BluetoothMapContract.TABLE_CONVOCONTACT);
10265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "Registering observer for: " + uri);
10275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mResolver.registerContentObserver(uri, true, mObserver);
10285a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10295a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1030326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mObserverRegistered = true;
1031326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1032fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1033fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
10345a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public void unregisterObserver() {
10355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.d(TAG, "unregisterObserver");
10365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mResolver.unregisterContentObserver(mObserver);
10375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mObserverRegistered = false;
10385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mProviderClient != null){
10395a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mProviderClient.release();
10405a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mProviderClient = null;
10415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10425a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
10435a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10445a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
10455a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Per design it is only possible to call the refreshXxxx functions sequentially, hence it
10465a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * is safe to modify mTransmitEvents without synchronization.
10475a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
10485a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* package */ void refreshFolderVersionCounter() {
10495a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mObserverRegistered) {
10505a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // As we have observers, we already keep the counter up-to-date.
10515a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
10525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* We need to perform the same functionality, as when we receive a notification change,
10545a60e47497f21f64e6d79420dc4c56c1907df22akschulz           hence we:
10555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - disable the event transmission
10565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - triggers the code for updates
10575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - enable the event transmission */
10585a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mTransmitEvents = false;
10595a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
10605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mEnableSmsMms) {
10615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesSms();
10625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesMms();
10635a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount != null) {
10655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                try {
10665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    handleMsgListChangesMsg(mMessageUri);
10675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } catch (RemoteException e) {
10685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Log.e(TAG, "Unable to update FolderVersionCounter. - Not fatal, but can cause" +
10695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            " undesirable user experience!", e);
10705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
10715a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10725a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
10735a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Ensure we always enable events again
10745a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mTransmitEvents = true;
10755a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10765a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
10775a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10785a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* package */ void refreshConvoListVersionCounter() {
10795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mObserverRegistered) {
10805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // As we have observers, we already keep the counter up-to-date.
10815a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
10825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* We need to perform the same functionality, as when we receive a notification change,
10845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        hence we:
10855a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - disable event transmission
10865a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - triggers the code for updates
10875a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - enable event transmission */
10885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mTransmitEvents = false;
10895a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
10905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if((mAccount != null) && (mContactUri != null)) {
10915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleContactListChanges(mContactUri);
10925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
10945a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Ensure we always enable events again
10955a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mTransmitEvents = true;
1096326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1097fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1098fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1099fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void sendEvent(Event evt) {
11005a60e47497f21f64e6d79420dc4c56c1907df22akschulz
11015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mTransmitEvents == false) {
11025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(V) Log.v(TAG, "mTransmitEvents == false - don't send event.");
11035a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
11045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
11055a60e47497f21f64e6d79420dc4c56c1907df22akschulz
11065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(D)Log.d(TAG, "sendEvent: " + evt.eventType + " " + evt.handle + " " + evt.folder + " "
11075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + evt.oldFolder + " " + evt.msgType.name() + " " + evt.datetime + " "
11085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + evt.subject + " " + evt.senderName + " " + evt.priority );
1109fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
11100e7e149687b0b5e340991b20c9d8e5232e8d3e39Hemant Gupta        if (mMnsClient == null || mMnsClient.isConnected() == false) {
11110e7e149687b0b5e340991b20c9d8e5232e8d3e39Hemant Gupta            Log.d(TAG, "sendEvent: No MNS client registered or connected- don't send event");
1112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return;
1113fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
11155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Enable use of the cache for checking the filter */
11165a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long eventFilter = mEventFilter;
11175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
11185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* This should have been a switch on the string, but it is not allowed in Java 1.6 */
11195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* WARNING: Here we do pointer compare for the string to speed up things, that is.
11205a60e47497f21f64e6d79420dc4c56c1907df22akschulz         * HENCE: always use the EVENT_TYPE_"defines" */
11215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(evt.eventType == EVENT_TYPE_NEW) {
11225a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventNewMessage(eventFilter)) {
11235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11255a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELETE) {
11275a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageDeleted(eventFilter)) {
11285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11305a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_REMOVED) {
11325a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageRemoved(eventFilter)) {
11335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11355a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SHIFT) {
11375a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageShift(eventFilter)) {
11385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11405a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELEVERY_SUCCESS) {
11425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventDeliverySuccess(eventFilter)) {
11435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11455a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SENDING_SUCCESS) {
11475a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventSendingSuccess(eventFilter)) {
11485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11505a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SENDING_FAILURE) {
11525a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventSendingFailed(eventFilter)) {
11535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11565a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELIVERY_FAILURE) {
11575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventDeliveryFailed(eventFilter)) {
11585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11615a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_READ_STATUS) {
11625a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventReadStatusChanged(eventFilter)) {
11635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11665a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_CONVERSATION) {
11675a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventConversationChanged(eventFilter)) {
11685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11705a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11715a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_PRESENCE) {
11725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventParticipantPresenceChanged(eventFilter)) {
11735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_CHAT_STATE) {
11775a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventParticipantChatstateChanged(eventFilter)) {
11785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
11825a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        try {
1184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mMnsClient.sendEvent(evt.encode(), mMasId);
1185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (UnsupportedEncodingException ex) {
1186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            /* do nothing */
11875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.e(TAG, "Exception - should not happen: ",ex);
1188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1191326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void initMsgList() throws RemoteException {
1192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "initMsgList");
1193db8d8ae565b3db6a5e3187170dcb7b281a79f9daAjay Panicker        UserManager manager = UserManager.get(mContext);
119429cab6e8ea1014179fd15fb067e621ae4b066085Ajay Panicker        if (manager == null || !manager.isUserUnlocked()) return;
1195fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1196db8d8ae565b3db6a5e3187170dcb7b281a79f9daAjay Panicker        if (mEnableSmsMms) {
1197326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
1198fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
11990905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker            Cursor c;
12000905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker            try {
12010905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker                c = mResolver.query(Sms.CONTENT_URI,
12025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    SMS_PROJECTION_SHORT, null, null, null);
12030905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker            } catch (SQLiteException e) {
12040905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker                Log.e(TAG, "Failed to initialize the list of messages: " + e.toString());
12050905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker                return;
12060905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker            }
12070905a86a66d6754469c00b5d154ffafe35f630b7Ajay Panicker
120828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
12095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
12105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
12115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Sms._ID));
12125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Sms.TYPE));
12135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
12145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Sms.READ));
1215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
12165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, type, threadId, read);
12175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgListSms.put(id, msg);
12185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
121928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
122028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
12215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1222326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
122328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
12245a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListSms()) {
12255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListSms().clear();
12265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListSms(msgListSms, true); // Set initial folder version counter
1227326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1228fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1229326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>();
1230fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1231326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            c = mResolver.query(Mms.CONTENT_URI, MMS_PROJECTION_SHORT, null, null, null);
123228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
12335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
12345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
12355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Mms._ID));
12365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
12375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
12385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Mms.READ));
1239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
12405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, type, threadId, read);
12415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgListMms.put(id, msg);
12425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
124328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
124428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
12455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1246326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
124728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
12485a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMms()) {
12495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMms().clear();
12505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMms(msgListMms, true); // Set initial folder version counter
1251326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1252fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1253fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1254326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mAccount != null) {
12555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            HashMap<Long, Msg> msgList = new HashMap<Long, Msg>();
1256326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uri = mMessageUri;
12575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Cursor c = mProviderClient.query(uri, MSG_PROJECTION_SHORT, null, null, null);
1258326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
125928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
12605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
12615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
12625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(MessageColumns._ID));
12635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long folderId = c.getInt(c.getColumnIndex(
12645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FOLDER_ID));
12655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int readFlag = c.getInt(c.getColumnIndex(
12665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FLAG_READ));
12675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, folderId, readFlag);
12685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgList.put(id, msg);
12695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
127028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
127128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
12725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
12735a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
12745a60e47497f21f64e6d79420dc4c56c1907df22akschulz
12755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
12765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMsg().clear();
12775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMsg(msgList, true);
1278326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
12795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12805a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
128128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
12825a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void initContactsList() throws RemoteException {
12835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.d(TAG, "initContactsList");
12845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mContactUri == null) {
12855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.d(TAG, "initContactsList() no mContactUri - nothing to init");
12865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
12875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Uri uri = mContactUri;
12895a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mProviderClient.query(uri,
12905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                BluetoothMapContract.BT_CONTACT_CHATSTATE_PRESENCE_PROJECTION,
12915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null, null, null);
12925a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Map<String, BluetoothMapConvoContactElement> contactList =
12935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                new HashMap<String, BluetoothMapConvoContactElement>();
12945a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
12955a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
12965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                ConvoContactInfo cInfo = new ConvoContactInfo();
12975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                cInfo.setConvoColunms(c);
12985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
12995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long convoId = c.getLong(cInfo.mContactColConvoId);
13005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (convoId == 0)
13015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
13025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (V) BluetoothMapUtils.printCursor(c);
13035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String uci = c.getString(cInfo.mContactColUci);
13045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String name = c.getString(cInfo.mContactColName);
13055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String displayName = c.getString(cInfo.mContactColNickname);
13065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String presenceStatus = c.getString(cInfo.mContactColPresenceText);
13075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int presenceState = c.getInt(cInfo.mContactColPresenceState);
13085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long lastActivity = c.getLong(cInfo.mContactColLastActive);
13095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int chatState = c.getInt(cInfo.mContactColChatState);
13105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int priority = c.getInt(cInfo.mContactColPriority);
13115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String btUid = c.getString(cInfo.mContactColBtUid);
13125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapConvoContactElement contact =
13135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            new BluetoothMapConvoContactElement(uci, name, displayName,
13145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    presenceStatus, presenceState, lastActivity, chatState,
13155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority, btUid);
13165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    contactList.put(uci, contact);
13175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
1318326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
13195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
13205a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
13215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
13225a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getContactList()) {
13235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            getContactList().clear();
13245a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setContactList(contactList, true);
1325326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1326fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1327fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1328fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void handleMsgListChangesSms() {
1329fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "handleMsgListChangesSms");
1330fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1331fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
13325a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
1333fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
13345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
13355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListSms()) {
1336ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
1337ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                c = mResolver.query(Sms.CONTENT_URI,
1338ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                        SMS_PROJECTION_SHORT, null, null, null);
1339ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            } else {
1340ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                c = mResolver.query(Sms.CONTENT_URI,
1341ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                        SMS_PROJECTION_SHORT_EXT, null, null, null);
1342ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            }
134328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
13445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
13455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
13465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Sms._ID));
13475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Sms.TYPE));
13485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
13495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Sms.READ));
13505a60e47497f21f64e6d79420dc4c56c1907df22akschulz
13515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().remove(id);
13525a60e47497f21f64e6d79420dc4c56c1907df22akschulz
13535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send e.g.
13545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * a message deleted and/or MessageShift for messages deleted by the MCE. */
13555a60e47497f21f64e6d79420dc4c56c1907df22akschulz
13565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
13575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message */
13585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, type, threadId, read);
13595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListSms.put(id, msg);
13605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
13615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Event evt;
13625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mTransmitEvents == true && // extract contact details only if needed
13635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mMapEventReportVersion >
13645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
13655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
13665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(Sms.DATE)));
13675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(Sms.BODY));
13685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String name = "";
13695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String phone = "";
13705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (type == 1) { //inbox
13715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    phone = c.getString(c.getColumnIndex(Sms.ADDRESS));
13725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (phone != null && !phone.isEmpty()) {
13735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = BluetoothMapContent.getContactNameFromPhone(phone,
13745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mResolver);
13755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if(name == null || name.isEmpty()){
13765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            name = phone;
13775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
13785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }else{
13795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = phone;
13805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
13815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
13825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    TelephonyManager tm =
13835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (TelephonyManager)mContext.getSystemService(
13845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            Context.TELEPHONY_SERVICE);
13855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (tm != null) {
13865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        phone = tm.getLine1Number();
13875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = tm.getLine1AlphaTag();
13885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if(name == null || name.isEmpty()){
13895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            name = phone;
13905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
13915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
13925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
13935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";// no priority for sms
13945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
13955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
13965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
13975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
13985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mSmsType, date, subject, name, priority);
13995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
14005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
14015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mSmsType, date, subject, name, priority,
14025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (long)threadId, null);
14035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
14045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else {
14055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
14065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
14075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, mSmsType);
14085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
14095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
14105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
14115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
14125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (type != msg.type) {
14135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
14145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "new type: " + type + " old type: " + msg.type);
14155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String oldFolder = getSmsFolderName(msg.type);
14165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String newFolder = getSmsFolderName(type);
14175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                // Filter out the intermediate outbox steps
14185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(!oldFolder.equalsIgnoreCase(newFolder)) {
14195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
14205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(type), oldFolder, mSmsType);
14215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
14225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
14235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.type = type;
14245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else if(threadId != msg.threadId) {
14255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
14265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "Message delete change: type: " + type
14275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + " old type: " + msg.type
14285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + "\n    threadId: " + threadId
14295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + " old threadId: " + msg.threadId);
14305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(threadId == DELETED_THREAD_ID) { // Message deleted
14315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // TODO:
14325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // We shall only use the folder attribute, but can't remember
14335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // wether to set it to "deleted" or the name of the folder
14345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // from which the message have been deleted.
1435cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
14365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
1437cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            getSmsFolderName(msg.type), null, mSmsType);
14385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
14395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
14405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else { // Undelete
14415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
14425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(msg.type),
14435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.FOLDER_NAME_DELETED, mSmsType);
14445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
14455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
14465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1447326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
14485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(read != msg.flagRead) {
14495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
14505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.flagRead = read;
14515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
14525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
14535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id,
14545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(msg.type), mSmsType);
14555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
14565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1457326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
14585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListSms.put(id, msg);
1459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
14605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
146128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
146228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
14635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1464fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
14665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListSms().values()) {
1467cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // "old_folder" used only for MessageShift event
1468326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
1469cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        getSmsFolderName(msg.type), null, mSmsType);
1470fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
14715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1473fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
14745a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListSms(msgListSms, listChanged);
1475fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1476fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1477fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1478fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void handleMsgListChangesMms() {
1479fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "handleMsgListChangesMms");
1480fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1481fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>();
14825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
14835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
14845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMms()) {
1485ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
1486ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                c = mResolver.query(Mms.CONTENT_URI,
1487ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                        MMS_PROJECTION_SHORT, null, null, null);
1488ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            } else {
1489ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                c = mResolver.query(Mms.CONTENT_URI,
1490ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta                        MMS_PROJECTION_SHORT_EXT, null, null, null);
1491ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta            }
1492ea6b2c977e8a621f160f37ef0d36db91d5c29834Hemant Gupta
14935a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try{
14945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
14955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
14965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Mms._ID));
14975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
14985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int mtype = c.getInt(c.getColumnIndex(Mms.MESSAGE_TYPE));
14995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
15005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        // TODO: Go through code to see if we have an issue with mismatch in types
15015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        //       for threadId. Seems to be a long in DB??
15025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Mms.READ));
15035a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().remove(id);
15055a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send
15075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * e.g. a message deleted and/or MessageShift for messages deleted by the
15085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * MCE.*/
15095a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
15115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message - only notify on retrieve conf */
15125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
15135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (getMmsFolderName(type).equalsIgnoreCase(
15145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    BluetoothMapContract.FOLDER_NAME_INBOX) &&
15155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mtype != MESSAGE_TYPE_RETRIEVE_CONF) {
1516fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                                continue;
15175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
15185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, type, threadId, read);
15195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListMms.put(id, msg);
1520326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Event evt;
15215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mTransmitEvents == true && // extract contact details only if needed
15225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mMapEventReportVersion !=
15235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
15245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
15255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(Mms.DATE)));
15265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(Mms.SUBJECT));
15275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (subject == null || subject.length() == 0) {
15285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /* Get subject from mms text body parts - if any exists */
15295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    subject = BluetoothMapContent.getTextPartsMms(mResolver, id);
15305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                int tmpPri = c.getInt(c.getColumnIndex(Mms.PRIORITY));
15325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "TEMP handleMsgListChangesMms, " +
15335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        "newMessage 'read' state: " + read +
15345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        "priority: " + tmpPri);
15355a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String address = BluetoothMapContent.getAddressMms(
15375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mResolver,id,BluetoothMapContent.MMS_FROM);
15385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";
15395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(tmpPri == PduHeaders.PRIORITY_HIGH)
15405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority = "yes";
15415a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
15435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
15445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
15455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
15465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            TYPE.MMS, date, subject, address, priority);
15475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
15485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
15495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            TYPE.MMS, date, subject, address, priority,
15505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (long)threadId, null);
15515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15525a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else {
15545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
15555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
15565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, TYPE.MMS);
1557326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
15585a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
15605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
15615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
15625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (type != msg.type) {
15635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "new type: " + type + " old type: " + msg.type);
15645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Event evt;
15655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
15665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(msg.localInitiatedSend == false) {
15675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Only send events about local initiated changes
15685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_SHIFT, id, getMmsFolderName(type),
15695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type), TYPE.MMS);
15705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.type = type;
15735a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (getMmsFolderName(type).equalsIgnoreCase(
15755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.FOLDER_NAME_SENT)
15765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && msg.localInitiatedSend == true) {
15775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Stop tracking changes for this message
15785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.localInitiatedSend = false;
15795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_SENDING_SUCCESS, id,
15805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(type), null, TYPE.MMS);
15815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else if(threadId != msg.threadId) {
15845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "Message delete change: type: " + type + " old type: "
15855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.type
15865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + "\n    threadId: " + threadId + " old threadId: "
15875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.threadId);
15885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
15895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(threadId == DELETED_THREAD_ID) { // Message deleted
1590cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
15915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
1592cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            getMmsFolderName(msg.type), null, TYPE.MMS);
15935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
15955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else { // Undelete
15965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
15975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type),
15985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.FOLDER_NAME_DELETED, TYPE.MMS);
15995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
16005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
16015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1602fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                            }
16035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(read != msg.flagRead) {
16045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
16055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.flagRead = read;
16065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
16075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
16085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id,
16095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type), TYPE.MMS);
16105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
16115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1612326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
16135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListMms.put(id, msg);
1614fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
16155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
16165a60e47497f21f64e6d79420dc4c56c1907df22akschulz
161728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
161828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
16195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1620fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
16215a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListMms().values()) {
1622cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // "old_folder" used only for MessageShift event
1623326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
1624cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        getMmsFolderName(msg.type), null, TYPE.MMS);
1625fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
16265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1627fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
16285a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListMms(msgListMms, listChanged);
1629fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1630fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1631fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
16325a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void handleMsgListChangesMsg(Uri uri)  throws RemoteException{
16335a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.v(TAG, "handleMsgListChangesMsg uri: " + uri.toString());
1634326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1635326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // TODO: Change observer to handle accountId and message ID if present
1636326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
16375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        HashMap<Long, Msg> msgList = new HashMap<Long, Msg>();
16385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
16395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
16405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
16415a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT, null, null, null);
16425a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
16435a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT_EXT, null, null, null);
16445a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else {
16455a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT_EXT2, null, null, null);
16465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
16475a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMsg()) {
164828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
16495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
16505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
16515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(
16525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns._ID));
16535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int folderId = c.getInt(c.getColumnIndex(
16545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FOLDER_ID));
16555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int readFlag = c.getInt(c.getColumnIndex(
16565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FLAG_READ));
16575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMsg().remove(id);
16585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        BluetoothMapFolderElement folderElement = mFolders.getFolderById(folderId);
16595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        String newFolder;
16605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(folderElement != null) {
16615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            newFolder = folderElement.getFullPath();
16625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
16635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // This can happen if a new folder is created while connected
16645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            newFolder = "unknown";
16655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
16665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send e.g.
16675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * a message deleted and/or MessageShift for messages deleted by the MCE. */
16685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
16695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
16705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message - created with message unread */
16715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, folderId, 0, readFlag);
16725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgList.put(id, msg);
16735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Event evt;
16745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Incoming message from the network */
16755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
16765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
16775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(
16785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.MessageColumns.DATE)));
16795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(
16805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.SUBJECT));
16815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String address = c.getString(c.getColumnIndex(
16825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.FROM_LIST));
16835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";
16845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(c.getInt(c.getColumnIndex(
16855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY))
16865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        == 1)
16875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority = "yes";
16885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
16895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
16905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, newFolder,
16915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType(), date, subject, address, priority);
16925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
16935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    long thread_id = c.getLong(c.getColumnIndex(
16945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.MessageColumns.THREAD_ID));
16955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String thread_name = c.getString(c.getColumnIndex(
16965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.MessageColumns.THREAD_NAME));
16975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, newFolder,
16985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType(), date, subject, address, priority,
16995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            thread_id, thread_name);
17005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1701326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
17025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, newFolder, null, TYPE.EMAIL);
1703326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
17045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
17055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
17065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
17075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (folderId != msg.folderId && msg.folderId != -1) {
17085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (D) Log.d(TAG, "new folderId: " + folderId + " old folderId: "
17095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.folderId);
17105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement oldFolderElement =
17115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderById(msg.folderId);
17125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String oldFolder;
17135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
17145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(oldFolderElement != null) {
17155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    oldFolder = oldFolderElement.getFullPath();
1716326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                } else {
17175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // This can happen if a new folder is created while connected
17185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    oldFolder = "unknown";
17195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
17205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement deletedFolder =
17215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderByName(
17225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.FOLDER_NAME_DELETED);
17235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement sentFolder =
17245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderByName(
17255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.FOLDER_NAME_SENT);
17265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /*
17275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  If the folder is now 'deleted', send a deleted-event in stead of
17285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  a shift or if message is sent initiated by MAP Client, then send
17295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  sending-success otherwise send folderShift
17305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 */
17315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(deletedFolder != null && deletedFolder.getFolderId()
17325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        == folderId) {
1733cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
1734cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
1735cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            null, mAccount.getType());
17365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
17375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else if(sentFolder != null
17385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && sentFolder.getFolderId() == folderId
17395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && msg.localInitiatedSend == true) {
17405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if(msg.transparent) {
17415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mResolver.delete(
17425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                ContentUris.withAppendedId(mMessageUri, id),
17435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                null, null);
17445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    } else {
17455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        msg.localInitiatedSend = false;
17465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msg.id,
17475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                oldFolder, null, mAccount.getType());
17485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
17495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
17505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
17515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (!oldFolder.equalsIgnoreCase("root")) {
17525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(EVENT_TYPE_SHIFT, id, newFolder,
17535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                oldFolder, mAccount.getType());
17545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
17555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
17565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
17575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.folderId = folderId;
17585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
17595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(readFlag != msg.flagRead) {
17605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
17615a60e47497f21f64e6d79420dc4c56c1907df22akschulz
17625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
17635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
17645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id, newFolder,
17655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType());
1766326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    sendEvent(evt);
17675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.flagRead = readFlag;
1768326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                }
1769326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
17705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
17715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgList.put(id, msg);
1772326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
17735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
177428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
177528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
17765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1777326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1778326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // For all messages no longer in the database send a delete notification
17795a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListMsg().values()) {
17805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                BluetoothMapFolderElement oldFolderElement = mFolders.getFolderById(msg.folderId);
1781326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String oldFolder;
17825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1783326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(oldFolderElement != null) {
1784326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    oldFolder = oldFolderElement.getFullPath();
1785326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
1786326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    oldFolder = "unknown";
1787326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
17885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Some e-mail clients delete the message after sending, and creates a
17895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * new message in sent. We cannot track the message anymore, hence send both a
17905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * send success and delete message.
1791326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 */
1792326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msg.localInitiatedSend == true) {
1793326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    msg.localInitiatedSend = false;
1794326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // If message is send with transparency don't set folder as message is deleted
1795326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.transparent)
1796326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        oldFolder = null;
17975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msg.id, oldFolder, null,
17985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            mAccount.getType());
1799326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendEvent(evt);
1800326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1801326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* As this message deleted is only send on a real delete - don't set folder.
1802326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 *  - only send delete event if message is not sent with transparency
1803326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 */
1804326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (!msg.transparent) {
1805326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1806cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    // "old_folder" used only for MessageShift event
1807cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
1808cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            null, mAccount.getType());
1809326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendEvent(evt);
1810326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1811326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
18125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListMsg(msgList, listChanged);
1813326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1814326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
1815326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1816326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void handleMsgListChanges(Uri uri) {
1817326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(uri.getAuthority().equals(mAuthority)) {
1818326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try {
18195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "handleMsgListChanges: account type = "
18205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + mAccount.getType().toString());
18215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesMsg(uri);
18225a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } catch(RemoteException e) {
1823326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mMasInstance.restartObexServerSession();
18245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG, "Problems contacting the ContentProvider in mas Instance "
18255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + mMasId + " restaring ObexServerSession");
1826326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1827326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
18285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
18295a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // TODO: check to see if there could be problem with IM and SMS in one instance
18305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mEnableSmsMms) {
1831326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            handleMsgListChangesSms();
1832326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            handleMsgListChangesMms();
1833326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1834326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
1835326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
18365a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void handleContactListChanges(Uri uri) {
18375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (uri.getAuthority().equals(mAuthority)) {
18385a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try {
18395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (V) Log.v(TAG,"handleContactListChanges uri: " + uri.toString());
18405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Cursor c = null;
18415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                boolean listChanged = false;
18425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                try {
18435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    ConvoContactInfo cInfo = new ConvoContactInfo();
18445a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V10
18465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            && mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
18475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        c = mProviderClient
18485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                .query(mContactUri,
18495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.
18505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BT_CONTACT_CHATSTATE_PRESENCE_PROJECTION,
18515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, null, null);
18525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        cInfo.setConvoColunms(c);
18535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } else {
18545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (V) Log.v(TAG,"handleContactListChanges MAP version does not" +
18555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "support convocontact notifications");
18565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        return;
18575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
18585a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    HashMap<String, BluetoothMapConvoContactElement> contactList =
18605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            new HashMap<String,
18615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapConvoContactElement>(getContactList().size());
18625a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized (getContactList()) {
18645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (c != null && c.moveToFirst()) {
18655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            do {
18665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String uci = c.getString(cInfo.mContactColUci);
18675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                long convoId = c.getLong(cInfo.mContactColConvoId);
18685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (convoId == 0)
18695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    continue;
18705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (V) BluetoothMapUtils.printCursor(c);
18725a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapConvoContactElement contact =
18745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        getContactList().remove(uci);
18755a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /*
18775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * We must filter out any actions made by the
18785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * MCE, hence do not send e.g. a message deleted
18795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * and/or MessageShift for messages deleted by
18805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * the MCE.
18815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 */
18825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (contact == null) {
18835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    listChanged = true;
18845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /*
18855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * New contact - added to conversation and
18865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * tracked here
18875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     */
18885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (mMapEventReportVersion
18895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            != BluetoothMapUtils.MAP_EVENT_REPORT_V10
18905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            && mMapEventReportVersion
18915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            != BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
18925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt;
18935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String name = c
18945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColName);
18955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String displayName = c
18965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColNickname);
18975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String presenceStatus = c
18985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColPresenceText);
18995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int presenceState = c
19005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColPresenceState);
19015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastActivity = c
19025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getLong(cInfo.mContactColLastActive);
19035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int chatState = c
19045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColChatState);
19055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int priority = c
19065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColPriority);
19075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String btUid = c
19085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColBtUid);
19095a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // Get Conversation information for
19115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // event
19125a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        Uri convoUri = Uri
19135a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .parse(mAccount.mBase_uri
19145a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        + "/"
19155a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        + BluetoothMapContract.TABLE_CONVERSATION);
19165a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        String whereClause = "contacts._id = "
19175a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                + convoId;
19185a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        Cursor cConvo = mProviderClient
19195a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .query(convoUri,
19205a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                       BluetoothMapContract.BT_CONVERSATION_PROJECTION,
19215a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                       whereClause, null, null);
19225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // TODO: will move out of the loop when merged with CB's
19235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // changes make sure to look up col index out side loop
19245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String convoName = null;
19255a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        if (cConvo != null
19265a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                && cConvo.moveToFirst()) {
19275a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            convoName = cConvo
19285a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    .getString(cConvo
19295a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                            .getColumnIndex(BluetoothMapContract.ConvoContactColumns.NAME));
19305a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        }
19315a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact = new BluetoothMapConvoContactElement(
19335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci, name, displayName,
19345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                presenceStatus, presenceState,
19355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                lastActivity, chatState,
19365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                priority, btUid);
19375a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contactList.put(uci, contact);
19395a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        evt = new Event(
19415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_CONVERSATION,
19425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
19435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
19445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                name,
19455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(priority),
19465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapUtils
19475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getDateTimeString(lastActivity),
19485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                convoId, convoName,
19495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                presenceState, presenceStatus,
19505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                chatState);
19515a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
19535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
19545a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
19565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Not new - compare updated content
19575a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    Uri convoUri = Uri
19585a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            .parse(mAccount.mBase_uri
19595a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    + "/"
19605a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    + BluetoothMapContract.TABLE_CONVERSATION);
19615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // TODO: Should be changed to own provider interface name
19625a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    String whereClause = "contacts._id = "
19635a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            + convoId;
19645a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    Cursor cConvo = mProviderClient
19655a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            .query(convoUri,
19665a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    BluetoothMapContract.BT_CONVERSATION_PROJECTION,
19675a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    whereClause, null, null);
19685a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    // TODO: will move out of the loop when merged with CB's
19695a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    // changes make sure to look up col index out side loop
19705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String convoName = null;
19715a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    if (cConvo != null && cConvo.moveToFirst()) {
19725a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        convoName = cConvo
19735a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .getString(cConvo
19745a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        .getColumnIndex(BluetoothMapContract.ConvoContactColumns.NAME));
19755a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    }
19765a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Check if presence is updated
19785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int presenceState = c.getInt(cInfo.mContactColPresenceState);
19795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String presenceStatus = c.getString(
19805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            cInfo.mContactColPresenceText);
19815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String currentPresenceStatus = contact
19825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            .getPresenceStatus();
19835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (contact.getPresenceAvailability() != presenceState
19845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            || currentPresenceStatus != presenceStatus) {
19855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastOnline = c
19865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getLong(cInfo.mContactColLastOnline);
19875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setPresenceAvailability(presenceState);
19885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setLastActivity(lastOnline);
19895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if (currentPresenceStatus != null
19905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                && !currentPresenceStatus
19915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .equals(presenceStatus)) {
19925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            contact.setPresenceStatus(presenceStatus);
19935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
19945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(
19955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_PRESENCE,
19965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
19975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
19985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                contact.getName(),
19995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(contact
20005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getPriority()),
20015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        BluetoothMapUtils
20025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getDateTimeString(lastOnline),
20035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        convoId, convoName,
20045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        presenceState, presenceStatus,
20055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        0);
20065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
20075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
20085a60e47497f21f64e6d79420dc4c56c1907df22akschulz
20095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Check if chat state is updated
20105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int chatState = c.getInt(cInfo.mContactColChatState);
20115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (contact.getChatState() != chatState) {
20125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // Get DB timestamp
20135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastActivity = c.getLong(cInfo.mContactColLastActive);
20145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setLastActivity(lastActivity);
20155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setChatState(chatState);
20165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(
20175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_CHAT_STATE,
20185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
20195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
20205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                contact.getName(),
20215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(contact
20225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getPriority()),
20235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        BluetoothMapUtils
20245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getDateTimeString(lastActivity),
20255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        convoId, convoName, 0, null,
20265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        chatState);
20275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
20285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
20295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    contactList.put(uci, contact);
20305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
20315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } while (c.moveToNext());
20325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
20335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(getContactList().size() > 0) {
20345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // one or more contacts were deleted, hence the conversation listing
20355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // version counter should change.
20365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
20375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
20385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        setContactList(contactList, listChanged);
20395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } // end synchronized
20405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } finally {
20415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (c != null) c.close();
20425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
20435a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } catch (RemoteException e) {
20445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mMasInstance.restartObexServerSession();
20455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG,
20465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        "Problems contacting the ContentProvider in mas Instance "
20475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                + mMasId + " restaring ObexServerSession");
20485a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
20495a60e47497f21f64e6d79420dc4c56c1907df22akschulz
20505a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
20515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // TODO: conversation contact updates if IM and SMS(MMS in one instance
20525a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
20535a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2054326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean setEmailMessageStatusDelete(BluetoothMapFolderElement mCurrentFolder,
2055326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String uriStr, long handle, int status) {
2056326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean res = false;
2057326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Uri.parse(uriStr + BluetoothMapContract.TABLE_MESSAGE);
2058326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2059326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int updateCount = 0;
2060326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        ContentValues contentValues = new ContentValues();
2061326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapFolderElement deleteFolder = mFolders.
20625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getFolderByName(BluetoothMapContract.FOLDER_NAME_DELETED);
2063326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        contentValues.put(BluetoothMapContract.MessageColumns._ID, handle);
20645a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMsg()) {
20655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Msg msg = getMsgListMsg().get(handle);
2066326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (status == BluetoothMapAppParams.STATUS_VALUE_YES) {
2067326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Set deleted folder id */
2068326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                long folderId = -1;
2069326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(deleteFolder != null) {
20705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folderId = deleteFolder.getFolderId();
2071326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2072326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                contentValues.put(BluetoothMapContract.MessageColumns.FOLDER_ID,folderId);
2073326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                updateCount = mResolver.update(uri, contentValues, null, null);
2074326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* The race between updating the value in our cached values and the database
2075326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * is handled by the synchronized statement. */
2076326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(updateCount > 0) {
2077326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = true;
2078326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg != null) {
2079326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msg.oldFolderId = msg.folderId;
20805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* Update the folder ID to avoid triggering an event for MCE
20815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * initiated actions. */
2082326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msg.folderId = folderId;
2083326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2084326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(D) Log.d(TAG, "Deleted MSG: " + handle + " from folderId: " + folderId);
2085326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
2086326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, "Msg: " + handle + " - Set delete status " + status
2087326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            + " failed for folderId " + folderId);
2088326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2089326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (status == BluetoothMapAppParams.STATUS_VALUE_NO) {
2090326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Undelete message. move to old folder if we know it,
2091326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * else move to inbox - as dictated by the spec. */
2092326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msg != null && deleteFolder != null &&
20935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msg.folderId == deleteFolder.getFolderId()) {
2094326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Only modify messages in the 'Deleted' folder */
2095326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    long folderId = -1;
20965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapFolderElement inboxFolder = mCurrentFolder.
20975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            getFolderByName(BluetoothMapContract.FOLDER_NAME_INBOX);
2098326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg != null && msg.oldFolderId != -1) {
2099326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        folderId = msg.oldFolderId;
2100326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
2101326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(inboxFolder != null) {
21025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            folderId = inboxFolder.getFolderId();
2103326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
21045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D)Log.d(TAG,"We did not delete the message, hence the old folder " +
21055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "is unknown. Moving to inbox.");
2106326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2107326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    contentValues.put(BluetoothMapContract.MessageColumns.FOLDER_ID, folderId);
2108326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    updateCount = mResolver.update(uri, contentValues, null, null);
2109326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(updateCount > 0) {
2110326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        res = true;
21115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* Update the folder ID to avoid triggering an event for MCE
21125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * initiated actions. */
21135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* UPDATE: Actually the BT-Spec. states that an undelete is a move of the
21145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * message to INBOX - clearified in errata 5591.
21155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * Therefore we update the cache to INBOX-folderId - to trigger a message
21165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * shift event to the old-folder. */
21175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(inboxFolder != null) {
21185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.folderId = inboxFolder.getFolderId();
21195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
21205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.folderId = folderId;
21215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
2122326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
21235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D)Log.d(TAG,"We did not delete the message, hence the old folder " +
21245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "is unknown. Moving to inbox.");
2125326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2126326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2127326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2128326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(V) {
2129326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                BluetoothMapFolderElement folderElement;
2130326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String folderName = "unknown";
2131326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (msg != null) {
21325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folderElement = mCurrentFolder.getFolderById(msg.folderId);
2133326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(folderElement != null) {
2134326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        folderName = folderElement.getName();
2135326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2136326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2137326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.d(TAG,"setEmailMessageStatusDelete: " + handle + " from " + folderName
2138326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        + " status: " + status);
2139326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2140326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2141326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(res == false) {
2142326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, "Set delete status " + status + " failed.");
2143326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2144326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return res;
2145326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
2146326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2147326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void updateThreadId(Uri uri, String valueString, long threadId) {
2148326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        ContentValues contentValues = new ContentValues();
2149326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        contentValues.put(valueString, threadId);
2150326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mResolver.update(uri, contentValues, null, null);
2151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean deleteMessageMms(long handle) {
2154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
215728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
215828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
215928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                /* Move to deleted folder, or delete if already in deleted folder */
216028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
216128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId != DELETED_THREAD_ID) {
216228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Set deleted thread id */
21635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
21645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().get(handle);
216528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
216628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = DELETED_THREAD_ID;
216728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2168326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
216928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Mms.THREAD_ID, DELETED_THREAD_ID);
217028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
217128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete from observer message list to avoid delete notifications */
21725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
21735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getMsgListMms().remove(handle);
217428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
217528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete message */
217628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    mResolver.delete(uri, null, null);
2177326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
217828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
218028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
21815a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
218328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
2184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean unDeleteMessageMms(long handle) {
2188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
219128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
219228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
219328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
219428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId == DELETED_THREAD_ID) {
219528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Restore thread id from address, or if no thread for address
21965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                     * create new thread by insert and remove of fake message */
219728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    String address;
219828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    long id = c.getLong(c.getColumnIndex(Mms._ID));
219928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int msgBox = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
220028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    if (msgBox == Mms.MESSAGE_BOX_INBOX) {
220128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        address = BluetoothMapContent.getAddressMms(mResolver, id,
22025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContent.MMS_FROM);
220328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    } else {
220428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        address = BluetoothMapContent.getAddressMms(mResolver, id,
22055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContent.MMS_TO);
220628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
220728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Set<String> recipients = new HashSet<String>();
220828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    recipients.addAll(Arrays.asList(address));
220928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Long oldThreadId = Telephony.Threads.getOrCreateThreadId(mContext, recipients);
22105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
22115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().get(handle);
221228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
221328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = oldThreadId.intValue();
22145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Spec. states that undelete shall shift the message to Inbox.
22155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Hence we need to trigger a message shift from INBOX to old-folder
22165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // after undelete.
22175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // We do this by changing the cached folder value to being inbox - hence
22185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // the event handler will se the update as the message have been shifted
22195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // from INBOX to old-folder. (Errata 5591 clearifies this)
22205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.type = Mms.MESSAGE_BOX_INBOX;
222128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2222326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
222328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Mms.THREAD_ID, oldThreadId);
222428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
222528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Log.d(TAG, "Message not in deleted folder: handle " + handle
22265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + " threadId " + threadId);
2227326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
222828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2229fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
223028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
22315a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2232fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2233fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2234fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2235fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2236fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean deleteMessageSms(long handle) {
2237fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2238fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
2239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
224028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
224128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
224228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                /* Move to deleted folder, or delete if already in deleted folder */
224328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
224428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId != DELETED_THREAD_ID) {
22455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
22465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().get(handle);
224728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
224828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = DELETED_THREAD_ID;
224928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2250326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
225128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Set deleted thread id */
225228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Sms.THREAD_ID, DELETED_THREAD_ID);
225328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
225428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete from observer message list to avoid delete notifications */
22555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
22565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getMsgListSms().remove(handle);
225728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
225828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete message */
225928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    mResolver.delete(uri, null, null);
2260326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
226128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2262fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
226328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
22645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2265fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2266fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2267fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2268fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2269fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean unDeleteMessageSms(long handle) {
2270fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2271fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
2272fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
227328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
227428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
227528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
227628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId == DELETED_THREAD_ID) {
227728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    String address = c.getString(c.getColumnIndex(Sms.ADDRESS));
227828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Set<String> recipients = new HashSet<String>();
227928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    recipients.addAll(Arrays.asList(address));
228028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Long oldThreadId = Telephony.Threads.getOrCreateThreadId(mContext, recipients);
22815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
22825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().get(handle);
22835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(msg != null) {
22845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.threadId = oldThreadId.intValue();
22855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* This will always be the case
22865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * The threadId is specified as an int, so it is safe to truncate
22875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * TODO: Test that this will trigger a message-shift from Inbox
22885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * to old-folder
22895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             **/
22905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Spec. states that undelete shall shift the message to Inbox.
22915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * Hence we need to trigger a message shift from INBOX to old-folder
22925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * after undelete.
22935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * We do this by changing the cached folder value to being inbox - hence
22945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * the event handler will se the update as the message have been shifted
22955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * from INBOX to old-folder. (Errata 5591 clearifies this)
22965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * */
22975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.type = Sms.MESSAGE_TYPE_INBOX;
229828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2299326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
230028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Sms.THREAD_ID, oldThreadId);
230128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
230228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Log.d(TAG, "Message not in deleted folder: handle " + handle
23035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + " threadId " + threadId);
2304326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
230528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2306fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
230728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
23085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2309fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2310fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2311fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2312fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
23135a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
23145a60e47497f21f64e6d79420dc4c56c1907df22akschulz     *
23155a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param handle
23165a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param type
23175a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param mCurrentFolder
23185a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param uriStr
23195a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param statusValue
23205a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @return true is success
23215a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
2322326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public boolean setMessageStatusDeleted(long handle, TYPE type,
2323326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            BluetoothMapFolderElement mCurrentFolder, String uriStr, int statusValue) {
2324fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2325fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "setMessageStatusDeleted: handle " + handle
23265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + " type " + type + " value " + statusValue);
2327fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2328326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (type == TYPE.EMAIL) {
2329326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            res = setEmailMessageStatusDelete(mCurrentFolder, uriStr, handle, statusValue);
23305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (type == TYPE.IM) {
23315a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO: to do when deleting IM message
23325a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.d(TAG, "setMessageStatusDeleted: IM not handled" );
2333326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2334326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (statusValue == BluetoothMapAppParams.STATUS_VALUE_YES) {
2335326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
2336326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = deleteMessageSms(handle);
2337326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else if (type == TYPE.MMS) {
2338326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = deleteMessageMms(handle);
2339326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2340326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (statusValue == BluetoothMapAppParams.STATUS_VALUE_NO) {
2341326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
2342326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = unDeleteMessageSms(handle);
2343326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else if (type == TYPE.MMS) {
2344326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = unDeleteMessageMms(handle);
2345326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2346fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2347fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2348fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2349fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2350fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2351326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
2352326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *
2353326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param handle
2354326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param type
2355326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param uriStr
2356326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param statusValue
2357326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return true at success
2358326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
23595a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public boolean setMessageStatusRead(long handle, TYPE type, String uriStr, int statusValue)
23605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            throws RemoteException{
2361326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int count = 0;
2362fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2363fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "setMessageStatusRead: handle " + handle
23645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + " type " + type + " value " + statusValue);
2365fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
23665a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Approved MAP spec errata 3445 states that read status initiated
23675a60e47497f21f64e6d79420dc4c56c1907df22akschulz         * by the MCE shall change the MSE read status. */
2368fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
2369cdf75c3f2b9e0e367ea2a4ce92018a6de662f4cdAjay Panicker            Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
2370fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            ContentValues contentValues = new ContentValues();
2371fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            contentValues.put(Sms.READ, statusValue);
2372326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(Sms.SEEN, statusValue);
2373326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String values = contentValues.toString();
2374cdf75c3f2b9e0e367ea2a4ce92018a6de662f4cdAjay Panicker            if (D) Log.d(TAG, " -> SMS Uri: " + uri.toString() + " values " + values);
23755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListSms()) {
23765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListSms().get(handle);
23775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
23785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
23795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
23805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2381cdf75c3f2b9e0e367ea2a4ce92018a6de662f4cdAjay Panicker            count = mResolver.update(uri, contentValues, null, null);
2382326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> "+count +" rows updated!");
238328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
2384fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } else if (type == TYPE.MMS) {
2385fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2386326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> MMS Uri: " + uri.toString());
2387fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            ContentValues contentValues = new ContentValues();
2388fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            contentValues.put(Mms.READ, statusValue);
23895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMms()) {
23905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListMms().get(handle);
23915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
23925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
23935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
23945a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2395326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            count = mResolver.update(uri, contentValues, null, null);
2396326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> "+count +" rows updated!");
23975a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (type == TYPE.EMAIL ||
23985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                type == TYPE.IM) {
2399326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uri = mMessageUri;
2400326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ContentValues contentValues = new ContentValues();
2401326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(BluetoothMapContract.MessageColumns.FLAG_READ, statusValue);
2402326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(BluetoothMapContract.MessageColumns._ID, handle);
24035a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
24045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListMsg().get(handle);
24055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
24065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
24075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
24085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2409326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            count = mProviderClient.update(uri, contentValues, null, null);
2410326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
241128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
241228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        return (count > 0);
2413fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2414fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2415fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class PushMsgInfo {
2416fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long id;
2417fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int transparent;
2418fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int retry;
2419fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String phone;
2420fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri;
2421326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long timestamp;
2422fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int parts;
2423fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int partsSent;
2424fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int partsDelivered;
2425fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean resend;
2426326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean sendInProgress;
2427326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean failedSent; // Set to true if a single part sent fail is received.
2428326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int statusDelivered; // Set to != 0 if a single part deliver fail is received.
2429fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2430fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public PushMsgInfo(long id, int transparent,
24315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                int retry, String phone, Uri uri) {
2432fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.id = id;
2433fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.transparent = transparent;
2434fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.retry = retry;
2435fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.phone = phone;
2436fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.uri = uri;
2437fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.resend = false;
2438326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.sendInProgress = false;
2439326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.failedSent = false;
2440326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.statusDelivered = 0; /* Assume success */
2441326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.timestamp = 0;
2442fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        };
2443fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2444fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2445fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private Map<Long, PushMsgInfo> mPushMsgList =
24465a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Collections.synchronizedMap(new HashMap<Long, PushMsgInfo>());
2447fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2448326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public long pushMessage(BluetoothMapbMessage msg, BluetoothMapFolderElement folderElement,
2449326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            BluetoothMapAppParams ap, String emailBaseUri)
2450326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throws IllegalArgumentException, RemoteException, IOException {
2451fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "pushMessage");
2452fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<BluetoothMapbMessage.vCard> recipientList = msg.getRecipients();
2453fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int transparent = (ap.getTransparent() == BluetoothMapAppParams.INVALID_VALUE_PARAMETER) ?
2454fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                0 : ap.getTransparent();
2455fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int retry = ap.getRetry();
2456fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int charset = ap.getCharset();
2457fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle = -1;
2458326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long folderId = -1;
2459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (recipientList == null) {
2461c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker            if (folderElement.getName().equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_DRAFT)) {
2462c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                BluetoothMapbMessage.vCard empty =
2463c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                    new BluetoothMapbMessage.vCard("", "", null, null, 0);
2464c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                recipientList = new ArrayList<BluetoothMapbMessage.vCard>();
2465c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                recipientList.add(empty);
2466c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                Log.w(TAG, "Added empty recipient to draft message");
2467c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker            } else {
2468c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                Log.e(TAG, "Trying to send a message with no recipients");
2469c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker                return -1;
2470c06dad4b6c213f57da06fe74903a25733ef6579fAjay Panicker            }
2471fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2473326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if ( msg.getType().equals(TYPE.EMAIL) ) {
2474326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Write the message to the database */
2475326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String msgBody = ((BluetoothMapbMessageEmail) msg).getEmailBody();
2476326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (V) {
2477326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                int length = msgBody.length();
2478326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.v(TAG, "pushMessage: message string length = " + length);
2479326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String messages[] = msgBody.split("\r\n");
2480326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.v(TAG, "pushMessage: messages count=" + messages.length);
2481326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                for(int i = 0; i < messages.length; i++) {
2482326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.v(TAG, "part " + i + ":" + messages[i]);
2483326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2484326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2485326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            FileOutputStream os = null;
2486326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ParcelFileDescriptor fdOut = null;
2487326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uriInsert = Uri.parse(emailBaseUri + BluetoothMapContract.TABLE_MESSAGE);
2488326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, "pushMessage - uriInsert= " + uriInsert.toString() +
24895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    ", intoFolder id=" + folderElement.getFolderId());
2490326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
24915a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
2492326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // Now insert the empty message into folder
2493326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                ContentValues values = new ContentValues();
24945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                folderId = folderElement.getFolderId();
2495326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(BluetoothMapContract.MessageColumns.FOLDER_ID, folderId);
2496326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Uri uriNew = mProviderClient.insert(uriInsert, values);
2497326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (D) Log.d(TAG, "pushMessage - uriNew= " + uriNew.toString());
2498326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                handle =  Long.parseLong(uriNew.getLastPathSegment());
2499326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2500326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                try {
2501326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    fdOut = mProviderClient.openFile(uriNew, "w");
2502326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    os = new FileOutputStream(fdOut.getFileDescriptor());
2503326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // Write Email to DB
2504326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    os.write(msgBody.getBytes(), 0, msgBody.getBytes().length);
2505326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } catch (FileNotFoundException e) {
2506326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, e);
2507326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throw(new IOException("Unable to open file stream"));
2508326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } catch (NullPointerException e) {
2509326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, e);
2510326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throw(new IllegalArgumentException("Unable to parse message."));
2511326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } finally {
2512326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    try {
2513326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(os != null)
2514326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            os.close();
2515326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } catch (IOException e) {Log.w(TAG, e);}
2516326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    try {
2517326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(fdOut != null)
25185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            fdOut.close();
2519326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } catch (IOException e) {Log.w(TAG, e);}
2520326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2521326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2522326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Extract the data for the inserted message, and store in local mirror, to
2523326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * avoid sending a NewMessage Event. */
25245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /*TODO: We need to add the new 1.1 parameter as well:-) e.g. read*/
25255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg newMsg = new Msg(handle, folderId, 1); // TODO: Create define for read-state
2526326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                newMsg.transparent = (transparent == 1) ? true : false;
25275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if ( folderId == folderElement.getFolderByName(
25285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        BluetoothMapContract.FOLDER_NAME_OUTBOX).getFolderId() ) {
2529326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    newMsg.localInitiatedSend = true;
2530326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
25315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMsg().put(handle, newMsg);
2532326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2533326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else { // type SMS_* of MMS
2534326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            for (BluetoothMapbMessage.vCard recipient : recipientList) {
25355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                // Only send the message to the top level recipient
25365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(recipient.getEnvLevel() == 0)
2537326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                {
2538326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Only send to first address */
2539326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String phone = recipient.getFirstPhoneNumber();
2540326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String email = recipient.getFirstEmail();
2541326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String folder = folderElement.getName();
2542326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    boolean read = false;
2543326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    boolean deliveryReport = true;
2544326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String msgBody = null;
2545326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2546326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* If MMS contains text only and the size is less than ten SMS's
2547326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                     * then convert the MMS to type SMS and then proceed
2548326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                     */
2549326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.getType().equals(TYPE.MMS) &&
25505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            (((BluetoothMapbMessageMime) msg).getTextOnly() == true)) {
25515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgBody = ((BluetoothMapbMessageMime) msg).getMessageAsText();
2552326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        SmsManager smsMng = SmsManager.getDefault();
2553326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        ArrayList<String> parts = smsMng.divideMessage(msgBody);
2554326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        int smsParts = parts.size();
2555326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (smsParts  <= CONVERT_MMS_TO_SMS_PART_COUNT ) {
25565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (D) Log.d(TAG, "pushMessage - converting MMS to SMS, sms parts="
25575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    + smsParts );
2558326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msg.setType(mSmsType);
2559326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
25605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (D) Log.d(TAG, "pushMessage - MMS text only but to big to " +
25615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    "convert to SMS");
2562326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msgBody = null;
2563326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2564326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2565fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    }
2566326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2567326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.getType().equals(TYPE.MMS)) {
2568326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        /* Send message if folder is outbox else just store in draft*/
2569ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        handle = sendMmsMessage(folder, phone, (BluetoothMapbMessageMime)msg,
2570ed70219e41ba68196798dcbf75b782d13fb88603kschulz                                transparent, retry);
2571326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else if (msg.getType().equals(TYPE.SMS_GSM) ||
2572326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msg.getType().equals(TYPE.SMS_CDMA) ) {
2573fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        /* Add the message to the database */
2574326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(msgBody == null)
2575326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msgBody = ((BluetoothMapbMessageSms) msg).getSmsBody();
2576326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2577cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        if (TextUtils.isEmpty(msgBody)) {
2578cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            Log.d(TAG, "PushMsg: Empty msgBody ");
2579cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            /* not allowed to push empty message */
2580cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            throw new IllegalArgumentException("push EMPTY message: Invalid Body");
2581cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        }
25825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We need to lock the SMS list while updating the database,
25835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * to avoid sending events on MCE initiated operation. */
2584326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Uri contentUri = Uri.parse(Sms.CONTENT_URI+ "/" + folder);
2585326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Uri uri;
25865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        synchronized(getMsgListSms()) {
2587326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            uri = Sms.addMessageToUri(mResolver, contentUri, phone, msgBody,
25885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    "", System.currentTimeMillis(), read, deliveryReport);
2589326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2590326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(V) Log.v(TAG, "Sms.addMessageToUri() returned: " + uri);
2591326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if (uri == null) {
25925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (D) Log.d(TAG, "pushMessage - failure on add to uri "
25935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + contentUri);
2594326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                return -1;
2595326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2596326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Cursor c = mResolver.query(uri, SMS_PROJECTION_SHORT, null, null, null);
25975a60e47497f21f64e6d79420dc4c56c1907df22akschulz
25985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Extract the data for the inserted message, and store in local mirror,
25995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * to avoid sending a NewMessage Event. */
260028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            try {
260128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                if (c != null && c.moveToFirst()) {
260228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    long id = c.getLong(c.getColumnIndex(Sms._ID));
260328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    int type = c.getInt(c.getColumnIndex(Sms.TYPE));
260428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
26055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int readFlag = c.getInt(c.getColumnIndex(Sms.READ));
26065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if(V) Log.v(TAG, "add message with id=" + id +
26075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            " type=" + type + " threadId=" + threadId +
26085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            " readFlag=" + readFlag + "to mMsgListSms");
26095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Msg newMsg = new Msg(id, type, threadId, readFlag);
26105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    getMsgListSms().put(id, newMsg);
26115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    c.close();
261228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                } else {
26135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Log.w(TAG,"Message: " + uri + " no longer exist!");
26145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /* This can only happen, if the message is deleted
26155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * just as it is added */
26165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    return -1;
261728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                }
261828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            } finally {
26195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (c != null) c.close();
2620326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2621fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2622326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            handle = Long.parseLong(uri.getLastPathSegment());
2623fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2624326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            /* Send message if folder is outbox */
26255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)) {
2626326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                PushMsgInfo msgInfo = new PushMsgInfo(handle, transparent,
26275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        retry, phone, uri);
2628326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                mPushMsgList.put(handle, msgInfo);
2629326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                sendMessage(msgInfo, msgBody);
2630326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                if(V) Log.v(TAG, "sendMessage returned...");
26315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } /* else just added to draft */
26325a60e47497f21f64e6d79420dc4c56c1907df22akschulz
26335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* sendMessage causes the message to be deleted and reinserted,
26345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * hence we need to lock the list while this is happening. */
2635fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
2636326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
2637326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (D) Log.d(TAG, "pushMessage - failure on type " );
2638326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        return -1;
2639fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    }
2640fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
2641fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2642fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2643fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2644fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* If multiple recipients return handle of last */
2645fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return handle;
2646fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2647fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2648ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public long sendMmsMessage(String folder, String to_address, BluetoothMapbMessageMime msg,
2649ed70219e41ba68196798dcbf75b782d13fb88603kschulz            int transparent, int retry) {
2650fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /*
2651fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *strategy:
2652fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *1) parse message into parts
2653fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *if folder is outbox/drafts:
2654fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *2) push message to draft
2655fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *if folder is outbox:
2656fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *3) move message to outbox (to trigger the mms app to add msg to pending_messages list)
2657fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *4) send intent to mms app in order to wake it up.
2658fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *else if folder !outbox:
2659fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *1) push message to folder
2660fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * */
2661326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (folder != null && (folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)
2662326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                ||  folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_DRAFT))) {
2663326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            long handle = pushMmsToFolder(Mms.MESSAGE_BOX_DRAFTS, to_address, msg);
26645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            /* if invalid handle (-1) then just return the handle
26655a60e47497f21f64e6d79420dc4c56c1907df22akschulz             * - else continue sending (if folder is outbox) */
26665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (BluetoothMapAppParams.INVALID_VALUE_PARAMETER != handle &&
26675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)) {
2668ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Uri btMmsUri = MmsFileProvider.CONTENT_URI.buildUpon()
2669ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        .appendPath(Long.toString(handle)).build();
2670ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Intent sentIntent = new Intent(ACTION_MESSAGE_SENT);
2671ed70219e41ba68196798dcbf75b782d13fb88603kschulz                // TODO: update the mmsMsgList <- done in pushMmsToFolder() but check
2672ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.setType("message/" + Long.toString(handle));
2673ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.MMS.ordinal());
2674ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_HANDLE, handle); // needed for notification
2675ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, transparent);
2676ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_RETRY, retry);
2677ed70219e41ba68196798dcbf75b782d13fb88603kschulz                //sentIntent.setDataAndNormalize(btMmsUri);
2678ed70219e41ba68196798dcbf75b782d13fb88603kschulz                PendingIntent pendingSendIntent = PendingIntent.getBroadcast(mContext, 0,
2679ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        sentIntent, 0);
2680ed70219e41ba68196798dcbf75b782d13fb88603kschulz                SmsManager.getDefault().sendMultimediaMessage(mContext,
2681ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        btMmsUri, null/*locationUrl*/, null/*configOverrides*/,
2682ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        pendingSendIntent);
2683326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2684326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return handle;
2685326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2686326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* not allowed to push mms to anything but outbox/draft */
26875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            throw  new IllegalArgumentException("Cannot push message to other " +
26885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    "folders than outbox/draft");
2689fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2690fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2691fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2692fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void moveDraftToOutbox(long handle) {
2693ed70219e41ba68196798dcbf75b782d13fb88603kschulz        moveMmsToFolder(handle, mResolver, Mms.MESSAGE_BOX_OUTBOX);
2694ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
2695ed70219e41ba68196798dcbf75b782d13fb88603kschulz
2696ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /**
2697ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * Move a MMS to another folder.
2698ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param handle the CP handle of the message to move
2699ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param resolver the ContentResolver to use
2700ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param folder the destination folder - use Mms.MESSAGE_BOX_xxx
2701ed70219e41ba68196798dcbf75b782d13fb88603kschulz     */
2702ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private static void moveMmsToFolder(long handle, ContentResolver resolver, int folder) {
2703fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /*Move message by changing the msg_box value in the content provider database */
27045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (handle != -1) {
27055a60e47497f21f64e6d79420dc4c56c1907df22akschulz            String whereClause = " _id= " + handle;
27065a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Uri uri = Mms.CONTENT_URI;
2707ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Cursor queryResult = resolver.query(uri, null, whereClause, null, null);
27085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try {
27095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (queryResult != null) {
27105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (queryResult.getCount() > 0) {
27115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        queryResult.moveToFirst();
27125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        ContentValues data = new ContentValues();
27135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* set folder to be outbox */
2714ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        data.put(Mms.MESSAGE_BOX, folder);
2715ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        resolver.update(uri, data, whereClause, null);
2716ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        if (D) Log.d(TAG, "moved MMS message to " + getMmsFolderName(folder));
27175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
27185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
2719ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Log.w(TAG, "Could not move MMS message to " + getMmsFolderName(folder));
27205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
27215a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } finally {
27225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (queryResult != null) queryResult.close();
2723fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2724fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2725fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
27265a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private long pushMmsToFolder(int folder, String to_address, BluetoothMapbMessageMime msg) {
2727fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /**
2728fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * strategy:
2729fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 1) parse msg into parts + header
2730fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 2) create thread id (abuse the ease of adding an SMS to get id for thread)
2731fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 3) push parts into content://mms/parts/ table
2732fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 3)
2733fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         */
2734fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2735fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ContentValues values = new ContentValues();
2736326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_BOX, folder);
2737326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.READ, 0);
2738326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.SEEN, 0);
2739326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getSubject() != null) {
2740326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT, msg.getSubject());
2741326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2742326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT, "");
2743326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
274470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
2745326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getSubject() != null && msg.getSubject().length() > 0) {
2746326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT_CHARSET, 106);
2747326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2748326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.CONTENT_TYPE, "application/vnd.wap.multipart.related");
2749326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.EXPIRY, 604800);
2750326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_CLASS, PduHeaders.MESSAGE_CLASS_PERSONAL_STR);
2751326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ);
2752326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MMS_VERSION, PduHeaders.CURRENT_MMS_VERSION);
2753326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.PRIORITY, PduHeaders.PRIORITY_NORMAL);
2754326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.READ_REPORT, PduHeaders.VALUE_NO);
2755326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.TRANSACTION_ID, "T"+ Long.toHexString(System.currentTimeMillis()));
2756326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.DELIVERY_REPORT, PduHeaders.VALUE_NO);
2757326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.LOCKED, 0);
2758326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getTextOnly() == true)
2759326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.TEXT_ONLY, true);
2760326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_SIZE, msg.getSize());
276170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
2762326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Get thread id
2763fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Set<String> recipients = new HashSet<String>();
2764fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        recipients.addAll(Arrays.asList(to_address));
2765326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.THREAD_ID, Telephony.Threads.getOrCreateThreadId(mContext, recipients));
2766326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Mms.CONTENT_URI;
2767fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
27685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized (getMsgListMms()) {
27695a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2770326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            uri = mResolver.insert(uri, values);
2771326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2772326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (uri == null) {
2773326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // unable to insert MMS
2774326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "Unabled to insert MMS " + values + "Uri: " + uri);
2775326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return -1;
2776326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2777326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* As we already have all the values we need, we could skip the query, but
2778326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde               doing the query ensures we get any changes made by the content provider
2779326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde               at insert. */
2780326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Cursor c = mResolver.query(uri, MMS_PROJECTION_SHORT, null, null, null);
278128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
278228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (c != null && c.moveToFirst()) {
278328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    long id = c.getLong(c.getColumnIndex(Mms._ID));
278428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
278528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
2786ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    int readStatus = c.getInt(c.getColumnIndex(Mms.READ));
2787326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
278828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* We must filter out any actions made by the MCE. Add the new message to
278928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                     * the list of known messages. */
2790326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2791ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Msg newMsg = new Msg(id, type, threadId, readStatus);
279228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    newMsg.localInitiatedSend = true;
27935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    getMsgListMms().put(id, newMsg);
27945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    c.close();
279528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
279628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
27975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
2798326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2799326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Done adding changes, unlock access to mMsgListMms to allow sending MMS events again
2800fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2801fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle = Long.parseLong(uri.getLastPathSegment());
2802326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (V) Log.v(TAG, " NEW URI " + uri.toString());
2803326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2804fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        try {
2805326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(msg.getMimeParts() == null) {
28065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Perhaps this message have been deleted, and no longer have any content,
28075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * but only headers */
2808326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.w(TAG, "No MMS parts present...");
2809326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
28105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(V) Log.v(TAG, "Adding " + msg.getMimeParts().size()
28115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + " parts to the data base.");
2812326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                for(MimePart part : msg.getMimeParts()) {
28135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int count = 0;
28145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    count++;
2815326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    values.clear();
28165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if(part.mContentType != null &&
28175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            part.mContentType.toUpperCase().contains("TEXT")) {
2818326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CONTENT_TYPE, "text/plain");
2819326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CHARSET, 106);
2820326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mPartName != null) {
2821326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.FILENAME, part.mPartName);
2822326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.NAME, part.mPartName);
2823326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2824326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.FILENAME, "text_" + count +".txt");
2825326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.NAME, "text_" + count +".txt");
2826326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2827326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        // Ensure we have "ci" set
2828326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentId != null) {
2829326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2830326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2831326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(part.mPartName != null) {
2832326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_ID, "<" + part.mPartName + ">");
2833326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
2834326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_ID, "<text_" + count + ">");
2835326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2836326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2837326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        // Ensure we have "cl" set
2838326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentLocation != null) {
2839326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2840326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2841326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(part.mPartName != null) {
2842326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_LOCATION, part.mPartName + ".txt");
2843326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
2844326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_LOCATION, "text_" + count + ".txt");
2845326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2846326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2847326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2848326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentDisposition != null) {
2849326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2850326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2851326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.TEXT, part.getDataAsString());
2852326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = Uri.parse(Mms.CONTENT_URI + "/" + handle + "/part");
2853326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = mResolver.insert(uri, values);
2854326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(V) Log.v(TAG, "Added TEXT part");
2855326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
28565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } else if (part.mContentType != null &&
28575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            part.mContentType.toUpperCase().contains("SMIL")){
2858326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.SEQ, -1);
2859326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CONTENT_TYPE, "application/smil");
2860326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentId != null) {
2861326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2862326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2863326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, "<smil_" + count + ">");
2864326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2865326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentLocation != null) {
2866326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2867326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2868326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, "smil_" + count + ".xml");
2869326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2870326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2871326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentDisposition != null)
2872326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2873326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.FILENAME, "smil.xml");
2874326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.NAME, "smil.xml");
2875326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.TEXT, new String(part.mData, "UTF-8"));
2876326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2877326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = Uri.parse(Mms.CONTENT_URI+ "/" + handle + "/part");
2878326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = mResolver.insert(uri, values);
2879326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (V) Log.v(TAG, "Added SMIL part");
2880326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2881326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }else /*VIDEO/AUDIO/IMAGE*/ {
2882326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        writeMmsDataPart(handle, part, count);
2883326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (V) Log.v(TAG, "Added OTHER part");
2884326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2885326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (uri != null){
28865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (V) Log.v(TAG, "Added part with content-type: " + part.mContentType
28875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                + " to Uri: " + uri.toString());
2888326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
288970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
2890fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2891fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (UnsupportedEncodingException e) {
289270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Log.w(TAG, e);
2893fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (IOException e) {
289470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Log.w(TAG, e);
2895fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2896fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2897fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        values.clear();
2898326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CONTACT_ID, "null");
2899326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.ADDRESS, "insert-address-token");
2900326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.TYPE, BluetoothMapContent.MMS_FROM);
2901326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CHARSET, 106);
2902fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2903326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = Uri.parse(Mms.CONTENT_URI + "/"  + handle + "/addr");
2904326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = mResolver.insert(uri, values);
2905fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (uri != null && V){
2906fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.v(TAG, " NEW URI " + uri.toString());
2907fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2908fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2909fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        values.clear();
2910326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CONTACT_ID, "null");
2911326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.ADDRESS, to_address);
2912326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.TYPE, BluetoothMapContent.MMS_TO);
2913326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CHARSET, 106);
2914fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2915326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = Uri.parse(Mms.CONTENT_URI + "/"  + handle + "/addr");
2916326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = mResolver.insert(uri, values);
2917fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (uri != null && V){
2918fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.v(TAG, " NEW URI " + uri.toString());
2919fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2920fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return handle;
2921fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2922fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2923fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
292470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private void writeMmsDataPart(long handle, MimePart part, int count) throws IOException{
2925fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ContentValues values = new ContentValues();
2926326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Part.MSG_ID, handle);
2927326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentType != null) {
2928326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_TYPE, part.mContentType);
2929326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2930326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, "MMS has no CONTENT_TYPE for part " + count);
2931326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2932326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentId != null) {
2933326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2934326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2935326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(part.mPartName != null) {
2936326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_ID, "<" + part.mPartName + ">");
2937326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
2938326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_ID, "<part_" + count + ">");
2939ed0c6ae1773ad1f4249fe3cf7447d7033195f222Ashwini Munigala            }
2940ed0c6ae1773ad1f4249fe3cf7447d7033195f222Ashwini Munigala        }
2941326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2942326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentLocation != null) {
2943326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2944326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2945326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(part.mPartName != null) {
2946326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_LOCATION, part.mPartName + ".dat");
2947326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
2948326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_LOCATION, "part_" + count + ".dat");
2949326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2950326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2951326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentDisposition != null)
2952326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2953326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mPartName != null) {
2954326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.FILENAME, part.mPartName);
2955326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.NAME, part.mPartName);
2956326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
295770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            /* We must set at least one part identifier */
2958326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.FILENAME, "part_" + count + ".dat");
2959326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.NAME, "part_" + count + ".dat");
296070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
2961326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri partUri = Uri.parse(Mms.CONTENT_URI + "/" + handle + "/part");
2962fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri res = mResolver.insert(partUri, values);
2963fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2964fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        // Add data to part
2965fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        OutputStream os = mResolver.openOutputStream(res);
2966326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        os.write(part.mData);
2967fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        os.close();
2968fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2969fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2970fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2971fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void sendMessage(PushMsgInfo msgInfo, String msgBody) {
2972fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2973fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        SmsManager smsMng = SmsManager.getDefault();
2974fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<String> parts = smsMng.divideMessage(msgBody);
2975fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        msgInfo.parts = parts.size();
2976326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // We add a time stamp to differentiate delivery reports from each other for resent messages
2977326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.timestamp = Calendar.getInstance().getTime().getTime();
2978326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.partsDelivered = 0;
2979326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.partsSent = 0;
2980fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2981fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(msgInfo.parts);
2982fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(msgInfo.parts);
2983fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2984326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /*       We handle the SENT intent in the MAP service, as this object
2985326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       is destroyed at disconnect, hence if a disconnect occur while sending
2986326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       a message, there is no intent handler to move the message from outbox
2987326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       to the correct folder.
2988326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       The correct solution would be to create a service that will start based on
2989326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       the intent, if BT is turned off. */
2990326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2991cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta        if (parts != null && parts.size() > 0) {
2992cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            for (int i = 0; i < msgInfo.parts; i++) {
2993cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                Intent intentDelivery, intentSent;
2994cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2995cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery = new Intent(ACTION_MESSAGE_DELIVERY, null);
2996cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                /* Add msgId and part number to ensure the intents are different, and we
2997cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * thereby get an intent for each msg part.
2998cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * setType is needed to create different intents for each message id/ time stamp,
2999cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * as the extras are not used when comparing. */
3000cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.setType("message/" + Long.toString(msgInfo.id) +
3001cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        msgInfo.timestamp + i);
3002cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_HANDLE, msgInfo.id);
3003cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_TIMESTAMP, msgInfo.timestamp);
3004cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                PendingIntent pendingIntentDelivery = PendingIntent.getBroadcast(mContext, 0,
3005cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        intentDelivery, PendingIntent.FLAG_UPDATE_CURRENT);
3006cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
3007cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent = new Intent(ACTION_MESSAGE_SENT, null);
3008cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                /* Add msgId and part number to ensure the intents are different, and we
3009cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * thereby get an intent for each msg part.
3010cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * setType is needed to create different intents for each message id/ time stamp,
3011cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * as the extras are not used when comparing. */
3012cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.setType("message/" + Long.toString(msgInfo.id) + msgInfo.timestamp + i);
3013cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_HANDLE, msgInfo.id);
3014cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_URI, msgInfo.uri.toString());
3015cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_RETRY, msgInfo.retry);
3016cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, msgInfo.transparent);
3017cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
3018cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                PendingIntent pendingIntentSent = PendingIntent.getBroadcast(mContext, 0,
3019cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        intentSent, PendingIntent.FLAG_UPDATE_CURRENT);
3020cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
3021cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // We use the same pending intent for all parts, but do not set the one shot flag.
3022cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                deliveryIntents.add(pendingIntentDelivery);
3023cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                sentIntents.add(pendingIntentSent);
3024cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            }
3025cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
3026cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            Log.d(TAG, "sendMessage to " + msgInfo.phone);
3027cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
3028cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            smsMng.sendMultipartTextMessage(msgInfo.phone, null, parts, sentIntents,
3029cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    deliveryIntents);
3030cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta        }
3031fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3032fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3033fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class SmsBroadcastReceiver extends BroadcastReceiver {
3034fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        private final String[] ID_PROJECTION = new String[] { Sms._ID };
3035326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        private final Uri UPDATE_STATUS_URI = Uri.withAppendedPath(Sms.CONTENT_URI, "/status");
3036fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3037fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void register() {
3038400eaf8761223196a18b84247b066f0201226c3bHemant Gupta            Handler handler = new Handler(Looper.getMainLooper());
3039fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3040fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            IntentFilter intentFilter = new IntentFilter();
3041fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            intentFilter.addAction(ACTION_MESSAGE_DELIVERY);
3042326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try{
3043326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                intentFilter.addDataType("message/*");
3044326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (MalformedMimeTypeException e) {
3045326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "Wrong mime type!!!", e);
3046326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3047326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3048fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mContext.registerReceiver(this, intentFilter, null, handler);
3049fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3050fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3051fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void unregister() {
3052fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
3053fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                mContext.unregisterReceiver(this);
3054fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalArgumentException e) {
3055fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                /* do nothing */
3056fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3057fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3058fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3059fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
3060fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onReceive(Context context, Intent intent) {
3061fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            String action = intent.getAction();
3062326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3063fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            PushMsgInfo msgInfo = mPushMsgList.get(handle);
3064fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3065fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.d(TAG, "onReceive: action"  + action);
3066fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3067fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (msgInfo == null) {
3068fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                Log.d(TAG, "onReceive: no msgInfo found for handle " + handle);
3069fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                return;
3070fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3071fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
30724f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            if (action.equals(ACTION_MESSAGE_SENT)) {
30734f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                int result = intent.getIntExtra(EXTRA_MESSAGE_SENT_RESULT,
30744f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        Activity.RESULT_CANCELED);
30754f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                msgInfo.partsSent++;
30764f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if(result != Activity.RESULT_OK) {
30774f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    /* If just one of the parts in the message fails, we need to send the
30784f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                     * entire message again
30794f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                     */
30804f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    msgInfo.failedSent = true;
30814f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                }
30824f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if(D) Log.d(TAG, "onReceive: msgInfo.partsSent = " + msgInfo.partsSent
30834f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        + ", msgInfo.parts = " + msgInfo.parts + " result = " + result);
30844f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
30854f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if (msgInfo.partsSent == msgInfo.parts) {
30864f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    actionMessageSent(context, intent, msgInfo);
30874f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                }
30884f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            } else if (action.equals(ACTION_MESSAGE_DELIVERY)) {
3089326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                long timestamp = intent.getLongExtra(EXTRA_MESSAGE_SENT_TIMESTAMP, 0);
3090326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                int status = -1;
3091326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msgInfo.timestamp == timestamp) {
3092326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    msgInfo.partsDelivered++;
3093326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    byte[] pdu = intent.getByteArrayExtra("pdu");
3094326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String format = intent.getStringExtra("format");
3095326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3096326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    SmsMessage message = SmsMessage.createFromPdu(pdu, format);
3097326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (message == null) {
3098326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Log.d(TAG, "actionMessageDelivery: Can't get message from pdu");
3099326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        return;
3100326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3101326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    status = message.getStatus();
3102326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(status != 0/*0 is success*/) {
3103326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msgInfo.statusDelivered = status;
31045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D) Log.d(TAG, "msgInfo.statusDelivered = " + status);
31050ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                        Sms.moveMessageToFolder(mContext, msgInfo.uri, Sms.MESSAGE_TYPE_FAILED, 0);
31060ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                    } else {
31070ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                        Sms.moveMessageToFolder(mContext, msgInfo.uri, Sms.MESSAGE_TYPE_SENT, 0);
3108326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3109326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3110fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (msgInfo.partsDelivered == msgInfo.parts) {
3111fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    actionMessageDelivery(context, intent, msgInfo);
3112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
3113fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
3114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                Log.d(TAG, "onReceive: Unknown action " + action);
3115fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3116fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3117fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
31184f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala        private void actionMessageSent(Context context, Intent intent, PushMsgInfo msgInfo) {
31194f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            /* As the MESSAGE_SENT intent is forwarded from the MAP service, we use the intent
31204f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala             * to carry the result, as getResult() will not return the correct value.
31214f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala             */
31224f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            boolean delete = false;
31234f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31244f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            if(D) Log.d(TAG,"actionMessageSent(): msgInfo.failedSent = " + msgInfo.failedSent);
31254f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31264f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            msgInfo.sendInProgress = false;
31274f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31284f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            if (msgInfo.failedSent == false) {
31294f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if(D) Log.d(TAG, "actionMessageSent: result OK");
31304f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if (msgInfo.transparent == 0) {
31314f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    if (!Sms.moveMessageToFolder(context, msgInfo.uri,
31324f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                            Sms.MESSAGE_TYPE_SENT, 0)) {
31334f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        Log.w(TAG, "Failed to move " + msgInfo.uri + " to SENT");
31344f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    }
31354f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                } else {
31364f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    delete = true;
31374f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                }
31384f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31394f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msgInfo.id,
31404f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
31414f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                sendEvent(evt);
31424f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31434f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            } else {
31444f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                if (msgInfo.retry == 1) {
31454f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    /* Notify failure, but keep message in outbox for resending */
31464f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    msgInfo.resend = true;
31474f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    msgInfo.partsSent = 0; // Reset counter for the retry
31484f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    msgInfo.failedSent = false;
31494f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, msgInfo.id,
31504f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                            getSmsFolderName(Sms.MESSAGE_TYPE_OUTBOX), null, mSmsType);
31514f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    sendEvent(evt);
31524f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                } else {
31534f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    if (msgInfo.transparent == 0) {
31544f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        if (!Sms.moveMessageToFolder(context, msgInfo.uri,
31554f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                                Sms.MESSAGE_TYPE_FAILED, 0)) {
31564f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                            Log.w(TAG, "Failed to move " + msgInfo.uri + " to FAILED");
31574f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        }
31584f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    } else {
31594f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                        delete = true;
31604f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    }
31614f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31624f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, msgInfo.id,
31634f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                            getSmsFolderName(Sms.MESSAGE_TYPE_FAILED), null, mSmsType);
31644f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    sendEvent(evt);
31654f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                }
31664f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            }
31674f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31684f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            if (delete == true) {
31694f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                /* Delete from Observer message list to avoid delete notifications */
31704f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                synchronized(getMsgListSms()) {
31714f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                    getMsgListSms().remove(msgInfo.id);
31724f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                }
31734f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
31744f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                /* Delete from DB */
31754f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala                mResolver.delete(msgInfo.uri, null, null);
31764f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala            }
31774f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala        }
31784f341a3ac7cdfd7c976a9eb59117542d50458398Ashwini Munigala
3179326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        private void actionMessageDelivery(Context context, Intent intent, PushMsgInfo msgInfo) {
3180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Uri messageUri = intent.getData();
3181326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msgInfo.sendInProgress = false;
3182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Cursor cursor = mResolver.query(msgInfo.uri, ID_PROJECTION, null, null, null);
3184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
3186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (cursor.moveToFirst()) {
3187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    int messageId = cursor.getInt(0);
3188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    Uri updateUri = ContentUris.withAppendedId(UPDATE_STATUS_URI, messageId);
3190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
31915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if(D) Log.d(TAG, "actionMessageDelivery: uri=" + messageUri + ", status="
31925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + msgInfo.statusDelivered);
3193fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3194fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    ContentValues contentValues = new ContentValues(2);
3195fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3196326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    contentValues.put(Sms.STATUS, msgInfo.statusDelivered);
3197fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    contentValues.put(Inbox.DATE_SENT, System.currentTimeMillis());
3198fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    mResolver.update(updateUri, contentValues, null, null);
3199fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                } else {
3200fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    Log.d(TAG, "Can't find message for status update: " + messageUri);
3201fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
3202fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } finally {
32035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (cursor != null) cursor.close();
3204fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3205fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3206326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (msgInfo.statusDelivered == 0) {
3207326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELEVERY_SUCCESS, msgInfo.id,
32085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
3209fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
3210fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
32115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Event evt = new Event(EVENT_TYPE_DELIVERY_FAILURE, msgInfo.id,
32125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
3213fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
3214fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3216fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mPushMsgList.remove(msgInfo.id);
3217fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3218fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3219fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3220725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker    private class CeBroadcastReceiver extends BroadcastReceiver {
3221725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        public void register() {
3222725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            UserManager manager = UserManager.get(mContext);
3223725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            if (manager == null || manager.isUserUnlocked()) {
3224725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                mStorageUnlocked = true;
3225725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                return;
3226725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            }
3227725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3228725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            Handler handler = new Handler(Looper.getMainLooper());
3229725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            IntentFilter intentFilter = new IntentFilter();
3230725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
3231725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            mContext.registerReceiver(this, intentFilter, null, handler);
3232725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        }
3233725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3234725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        public void unregister() {
3235725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            try {
3236725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                mContext.unregisterReceiver(this);
3237725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            } catch (IllegalArgumentException e) {
3238725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                /* do nothing */
3239725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            }
3240725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        }
3241725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3242725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        public void onReceive(Context context, Intent intent) {
3243725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            String action = intent.getAction();
3244725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            Log.d(TAG, "onReceive: action"  + action);
3245725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3246725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
3247725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                try {
3248725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                    initMsgList();
3249725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                } catch (RemoteException e) {
3250725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                    Log.e(TAG, "Error initializing SMS/MMS message lists.");
3251725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                }
3252725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3253725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                for (String folder : FOLDER_SMS_MAP.values()) {
3254725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                    Event evt = new Event(EVENT_TYPE_NEW, -1, folder, mSmsType);
3255725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                    sendEvent(evt);
3256725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                }
3257725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                mStorageUnlocked = true;
3258725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                /* After unlock this BroadcastReceiver is never needed */
3259725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                unregister();
3260725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            } else {
3261725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker                Log.d(TAG, "onReceive: Unknown action " + action);
3262725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            }
3263725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        }
3264725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker    }
3265725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3266ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /**
3267ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * Handle MMS sent intents in disconnected(MNS) state, where we do not need to send any
3268ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * notifications.
3269ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param context The context to use for provider operations
3270ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param intent The intent received
3271ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param result The result
3272ed70219e41ba68196798dcbf75b782d13fb88603kschulz     */
3273ed70219e41ba68196798dcbf75b782d13fb88603kschulz    static public void actionMmsSent(Context context, Intent intent, int result,
3274ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Map<Long, Msg> mmsMsgList) {
3275ed70219e41ba68196798dcbf75b782d13fb88603kschulz        /*
3276ed70219e41ba68196798dcbf75b782d13fb88603kschulz         * if transparent:
3277ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   delete message and send notification(regardless of result)
3278ed70219e41ba68196798dcbf75b782d13fb88603kschulz         * else
3279ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   Result == Success:
3280ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *     move to sent folder (will trigger notification)
3281ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   Result == Fail:
3282ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *     move to outbox (send delivery fail notification)
3283ed70219e41ba68196798dcbf75b782d13fb88603kschulz         */
3284ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(D) Log.d(TAG,"actionMmsSent()");
3285ed70219e41ba68196798dcbf75b782d13fb88603kschulz        int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3286ed70219e41ba68196798dcbf75b782d13fb88603kschulz        long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3287ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(handle < 0) {
3288ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Log.w(TAG, "Intent received for an invalid handle");
3289ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return;
3290ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3291ed70219e41ba68196798dcbf75b782d13fb88603kschulz        ContentResolver resolver = context.getContentResolver();
3292ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(transparent == 1) {
3293ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* The specification is a bit unclear about the transparent flag. If it is set
3294ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * no copy of the message shall be kept in the send folder after the message
3295ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * was send, but in the case of a send error, it is unclear what to do.
3296ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * As it will not be transparent if we keep the message in any folder,
3297ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * we delete the message regardless of the result.
3298ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * If we however do have a MNS connection we need to send a notification. */
3299ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
3300ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Delete from observer message list to avoid delete notifications */
3301ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mmsMsgList != null) {
3302ed70219e41ba68196798dcbf75b782d13fb88603kschulz                synchronized(mmsMsgList) {
3303ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    mmsMsgList.remove(handle);
3304ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3305ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3306ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Delete message */
3307ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(D) Log.d(TAG,"Transparent in use - delete");
3308ed70219e41ba68196798dcbf75b782d13fb88603kschulz            resolver.delete(uri, null, null);
3309ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else if (result == Activity.RESULT_OK) {
3310ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* This will trigger a notification */
3311ed70219e41ba68196798dcbf75b782d13fb88603kschulz            moveMmsToFolder(handle, resolver, Mms.MESSAGE_BOX_SENT);
3312ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3313ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mmsMsgList != null) {
3314ed70219e41ba68196798dcbf75b782d13fb88603kschulz                synchronized(mmsMsgList) {
3315ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Msg msg = mmsMsgList.get(handle);
3316ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    if(msg != null) {
3317ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    msg.type=Mms.MESSAGE_BOX_OUTBOX;
3318ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    }
3319ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3320ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3321ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Hand further retries over to the MMS application */
3322ed70219e41ba68196798dcbf75b782d13fb88603kschulz            moveMmsToFolder(handle, resolver, Mms.MESSAGE_BOX_OUTBOX);
3323ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3324ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3325ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3326326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static public void actionMessageSentDisconnected(Context context, Intent intent, int result) {
3327ed70219e41ba68196798dcbf75b782d13fb88603kschulz        TYPE type = TYPE.fromOrdinal(
3328ed70219e41ba68196798dcbf75b782d13fb88603kschulz        intent.getIntExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.NONE.ordinal()));
3329ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(type == TYPE.MMS) {
3330edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            actionMmsSent(context, intent, result, null);
3331ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3332edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            actionSmsSentDisconnected(context, intent, result);
3333ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3334ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3335ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3336ed70219e41ba68196798dcbf75b782d13fb88603kschulz    static public void actionSmsSentDisconnected(Context context, Intent intent, int result) {
3337edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        /* Check permission for message deletion. */
3338edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        if ((Binder.getCallingPid() != Process.myPid()) ||
3339edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            (context.checkCallingOrSelfPermission("android.Manifest.permission.WRITE_SMS")
3340edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou                    != PackageManager.PERMISSION_GRANTED)) {
3341edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            Log.w(TAG, "actionSmsSentDisconnected: Not allowed to delete SMS/MMS messages");
3342edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            return;
3343edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        }
3344edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou
3345326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean delete = false;
3346326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        //int retry = intent.getIntExtra(EXTRA_MESSAGE_SENT_RETRY, 0);
3347326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3348326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        String uriString = intent.getStringExtra(EXTRA_MESSAGE_SENT_URI);
3349326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(uriString == null) {
3350326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // Nothing we can do about it, just bail out
3351326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return;
3352326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3353326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Uri.parse(uriString);
3354326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3355326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (result == Activity.RESULT_OK) {
3356326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.d(TAG, "actionMessageSentDisconnected: result OK");
3357326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (transparent == 0) {
3358326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (!Sms.moveMessageToFolder(context, uri,
3359326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Sms.MESSAGE_TYPE_SENT, 0)) {
3360326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.d(TAG, "Failed to move " + uri + " to SENT");
3361326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3362326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
3363326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                delete = true;
3364326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3365326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
3366326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /*if (retry == 1) {
3367326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 The retry feature only works while connected, else we fail the send,
33685a60e47497f21f64e6d79420dc4c56c1907df22akschulz             * and move the message to failed, to let the user/app resend manually later.
3369326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else */{
3370326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (transparent == 0) {
3371326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (!Sms.moveMessageToFolder(context, uri,
3372326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Sms.MESSAGE_TYPE_FAILED, 0)) {
3373326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Log.d(TAG, "Failed to move " + uri + " to FAILED");
3374326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3375326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
3376326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    delete = true;
3377326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3378326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3379326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3380326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3381edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        if (delete) {
3382326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Delete from DB */
3383326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ContentResolver resolver = context.getContentResolver();
3384edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            if (resolver != null) {
3385326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                resolver.delete(uri, null, null);
3386326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
3387326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.w(TAG, "Unable to get resolver");
3388326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3389326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3390326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
3391326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3392fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void registerPhoneServiceStateListener() {
33935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
33945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
3395fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        tm.listen(mPhoneListener, PhoneStateListener.LISTEN_SERVICE_STATE);
3396fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3397fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3398fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void unRegisterPhoneServiceStateListener() {
33995a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
34005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
3401fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        tm.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
3402fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3403fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3404fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void resendPendingMessages() {
3405fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Send pending messages in outbox */
3406fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
3407db8d8ae565b3db6a5e3187170dcb7b281a79f9daAjay Panicker        UserManager manager = UserManager.get(mContext);
3408db8d8ae565b3db6a5e3187170dcb7b281a79f9daAjay Panicker        if (manager == null || !manager.isUserUnlocked()) return;
34095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
34105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null);
341128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
34125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
34135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
34145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long id = c.getLong(c.getColumnIndex(Sms._ID));
34155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
34165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    PushMsgInfo msgInfo = mPushMsgList.get(id);
34175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (msgInfo == null || msgInfo.resend == false ||
34185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgInfo.sendInProgress == true) {
34195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
34205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
34215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msgInfo.sendInProgress = true;
34225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    sendMessage(msgInfo, msgBody);
34235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
342428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            }
342528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
34265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
3427fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
34285a60e47497f21f64e6d79420dc4c56c1907df22akschulz
34295a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3430fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3431fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3432fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void failPendingMessages() {
3433fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Move pending messages from outbox to failed */
3434fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
34355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
34365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null);
343728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
34385a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
34395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
34405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long id = c.getLong(c.getColumnIndex(Sms._ID));
34415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
34425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    PushMsgInfo msgInfo = mPushMsgList.get(id);
34435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (msgInfo == null || msgInfo.resend == false) {
34445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
34455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
34465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Sms.moveMessageToFolder(mContext, msgInfo.uri,
34475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Sms.MESSAGE_TYPE_FAILED, 0);
34485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
344928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            }
345028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
34515a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
3452fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
34535a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3454fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3455fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3456fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void removeDeletedMessages() {
3457fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Remove messages from virtual "deleted" folder (thread_id -1) */
3458326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mResolver.delete(Sms.CONTENT_URI,
3459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                "thread_id = " + DELETED_THREAD_ID, null);
3460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3461fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3462fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
3463fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
3464fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onServiceStateChanged(ServiceState serviceState) {
3465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.d(TAG, "Phone service state change: " + serviceState.getState());
3466fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
3467fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                resendPendingMessages();
3468fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3469fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3470fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
3471fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void init() {
3473b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta        if (mSmsBroadcastReceiver != null) {
3474b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta            mSmsBroadcastReceiver.register();
3475b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta        }
3476725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3477725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        if (mCeBroadcastReceiver != null) {
3478725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker            mCeBroadcastReceiver.register();
3479725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker        }
3480725c70cfb004690027ded41f080bfe1bb17d2285Ajay Panicker
3481fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        registerPhoneServiceStateListener();
3482326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mInitialized = true;
3483fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3484fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3485fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void deinit() {
3486326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mInitialized = false;
3487326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        unregisterObserver();
3488b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta        if (mSmsBroadcastReceiver != null) {
3489b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta            mSmsBroadcastReceiver.unregister();
3490b6fdf260e28b4eb6b5cdb19f53710c0470ffcad2Hemant Gupta        }
3491fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        unRegisterPhoneServiceStateListener();
3492fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        failPendingMessages();
3493fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        removeDeletedMessages();
3494fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3495326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3496326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public boolean handleSmsSendIntent(Context context, Intent intent){
3497ed70219e41ba68196798dcbf75b782d13fb88603kschulz        TYPE type = TYPE.fromOrdinal(
3498ed70219e41ba68196798dcbf75b782d13fb88603kschulz            intent.getIntExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.NONE.ordinal()));
3499ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(type == TYPE.MMS) {
3500ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return handleMmsSendIntent(context, intent);
3501ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3502ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mInitialized) {
3503ed70219e41ba68196798dcbf75b782d13fb88603kschulz                mSmsBroadcastReceiver.onReceive(context, intent);
3504ed70219e41ba68196798dcbf75b782d13fb88603kschulz                return true;
3505ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3506326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3507326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return false;
3508326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
3509ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3510ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public boolean handleMmsSendIntent(Context context, Intent intent){
3511ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(D) Log.w(TAG, "handleMmsSendIntent()");
3512ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(mMnsClient.isConnected() == false) {
3513ed70219e41ba68196798dcbf75b782d13fb88603kschulz            // No need to handle notifications, just use default handling
3514ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(D) Log.w(TAG, "MNS not connected - use static handling");
3515ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return false;
3516ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3517ed70219e41ba68196798dcbf75b782d13fb88603kschulz        long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3518ed70219e41ba68196798dcbf75b782d13fb88603kschulz        int result = intent.getIntExtra(EXTRA_MESSAGE_SENT_RESULT, Activity.RESULT_CANCELED);
3519ed70219e41ba68196798dcbf75b782d13fb88603kschulz        actionMmsSent(context, intent, result, getMsgListMms());
3520ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(handle < 0) {
3521ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Log.w(TAG, "Intent received for an invalid handle");
3522ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return true;
3523ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3524ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(result != Activity.RESULT_OK) {
3525ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mObserverRegistered) {
3526ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, handle,
3527ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        getMmsFolderName(Mms.MESSAGE_BOX_OUTBOX), null, TYPE.MMS);
3528ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sendEvent(evt);
3529ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3530ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3531ed70219e41ba68196798dcbf75b782d13fb88603kschulz            int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3532ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(transparent != 0) {
3533ed70219e41ba68196798dcbf75b782d13fb88603kschulz                if(mObserverRegistered) {
3534ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, handle,
3535ed70219e41ba68196798dcbf75b782d13fb88603kschulz                            getMmsFolderName(Mms.MESSAGE_BOX_OUTBOX), null, TYPE.MMS);
3536ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    sendEvent(evt);
3537ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3538ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3539ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3540ed70219e41ba68196798dcbf75b782d13fb88603kschulz        return true;
3541ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3542ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3543fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie}
3544