BluetoothMapContentObserver.java revision 1983bccf614d61dfcf20ba3cbf14f4ebf7f49943
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;
32fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.net.Uri;
33edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chouimport android.os.Binder;
34fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Handler;
355a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport android.os.Looper;
36326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.Message;
37326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.ParcelFileDescriptor;
38edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chouimport android.os.Process;
39326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.RemoteException;
40fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony;
41fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Mms;
42fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.MmsSms;
43fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms;
44fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.provider.Telephony.Sms.Inbox;
45fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.PhoneStateListener;
46fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.ServiceState;
47fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsManager;
48fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.SmsMessage;
49fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.telephony.TelephonyManager;
50326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.text.format.DateUtils;
511983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigalaimport android.util.EventLog;
52fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log;
53fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Xml;
54cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Guptaimport android.text.TextUtils;
555a60e47497f21f64e6d79420dc4c56c1907df22akschulz
565a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport org.xmlpull.v1.XmlSerializer;
57fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
58fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.map.BluetoothMapUtils.TYPE;
595a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.map.BluetoothMapbMessageMime.MimePart;
605a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.mapapi.BluetoothMapContract;
615a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.bluetooth.mapapi.BluetoothMapContract.MessageColumns;
62fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.google.android.mms.pdu.PduHeaders;
63fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
645a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.FileNotFoundException;
655a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.FileOutputStream;
665a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.IOException;
675a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.OutputStream;
685a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.StringWriter;
695a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.UnsupportedEncodingException;
705a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.ArrayList;
715a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Arrays;
725a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Calendar;
735a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Collections;
745a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.HashMap;
755a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.HashSet;
765a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Map;
775a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Set;
785a60e47497f21f64e6d79420dc4c56c1907df22akschulz
795a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport javax.obex.ResponseCodes;
805a60e47497f21f64e6d79420dc4c56c1907df22akschulz
815a60e47497f21f64e6d79420dc4c56c1907df22akschulz@TargetApi(19)
82fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepublic class BluetoothMapContentObserver {
83fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String TAG = "BluetoothMapContentObserver";
84fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
85326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final boolean D = BluetoothMapService.DEBUG;
86326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final boolean V = BluetoothMapService.VERBOSE;
87326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
885a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_NEW              = "NewMessage";
895a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_DELETE           = "MessageDeleted";
905a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_REMOVED          = "MessageRemoved";
915a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_SHIFT            = "MessageShift";
92326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_DELEVERY_SUCCESS = "DeliverySuccess";
93326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_SENDING_SUCCESS  = "SendingSuccess";
94326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_SENDING_FAILURE  = "SendingFailure";
95326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String EVENT_TYPE_DELIVERY_FAILURE = "DeliveryFailure";
965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_READ_STATUS      = "ReadStatusChanged";
975a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_CONVERSATION     = "ConversationChanged";
985a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_PRESENCE         = "ParticipantPresenceChanged";
995a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final String EVENT_TYPE_CHAT_STATE       = "ParticipantChatStateChanged";
1005a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1015a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_NEW_MESSAGE                  = 1L;
1025a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_DELETED              = 1L<<1;
1035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_SHIFT                = 1L<<2;
1045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_SENDING_SUCCESS              = 1L<<3;
1055a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_SENDING_FAILED               = 1L<<4;
1065a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_DELIVERY_SUCCESS             = 1L<<5;
1075a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_DELIVERY_FAILED              = 1L<<6;
1085a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MEMORY_FULL                  = 1L<<7; // Unused
1095a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MEMORY_AVAILABLE             = 1L<<8; // Unused
1105a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_READ_STATUS_CHANGED          = 1L<<9;
1115a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_CONVERSATION_CHANGED         = 1L<<10;
1125a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_PARTICIPANT_PRESENCE_CHANGED = 1L<<11;
1135a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_PARTICIPANT_CHATSTATE_CHANGED= 1L<<12;
1145a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final long EVENT_FILTER_MESSAGE_REMOVED              = 1L<<13;
1155a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1165a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // TODO: If we are requesting a large message from the network, on a slow connection
1175a60e47497f21f64e6d79420dc4c56c1907df22akschulz    //       20 seconds might not be enough... But then again 20 seconds is long for other
1185a60e47497f21f64e6d79420dc4c56c1907df22akschulz    //       cases.
119326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
120fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private Context mContext;
122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private ContentResolver mResolver;
123326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private ContentProviderClient mProviderClient = null;
124fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private BluetoothMnsObexClient mMnsClient;
125326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private BluetoothMapMasInstance mMasInstance = null;
126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private int mMasId;
127326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mEnableSmsMms = false;
128326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mObserverRegistered = false;
1295a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private BluetoothMapAccountItem mAccount;
130326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private String mAuthority = null;
131326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1325a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // Default supported feature bit mask is 0x1f
1335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private int mMapSupportedFeatures = BluetoothMapUtils.MAP_FEATURE_DEFAULT_BITMASK;
1345a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // Default event report version is 1.0
1355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private int mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V10;
1365a60e47497f21f64e6d79420dc4c56c1907df22akschulz
137326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private BluetoothMapFolderElement mFolders =
138326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            new BluetoothMapFolderElement("DUMMY", null); // Will be set by the MAS when generated.
139326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private Uri mMessageUri = null;
1405a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Uri mContactUri = null;
1415a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1425a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private boolean mTransmitEvents = true;
1435a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1445a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* To make the filter update atomic, we declare it volatile.
1455a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * To avoid a penalty when using it, copy the value to a local
1465a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * non-volatile variable when used more than once.
1475a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Actually we only ever use the lower 4 bytes of this variable,
1485a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * hence we could manage without the volatile keyword, but as
1495a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * we tend to copy ways of doing things, we better do it right:-) */
1505a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private volatile long mEventFilter = 0xFFFFFFFFL;
151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int DELETED_THREAD_ID = -1;
153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
154326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    // X-Mms-Message-Type field types. These are from PduHeaders.java
155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84;
156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
157326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    // Text only MMS converted to SMS if sms parts less than or equal to defined count
158326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int CONVERT_MMS_TO_SMS_PART_COUNT = 10;
159326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
160fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private TYPE mSmsType;
161fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
162ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private static final String ACTION_MESSAGE_DELIVERY =
163ed70219e41ba68196798dcbf75b782d13fb88603kschulz            "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY";
164ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /*package*/ static final String ACTION_MESSAGE_SENT =
165ed70219e41ba68196798dcbf75b782d13fb88603kschulz        "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT";
166ed70219e41ba68196798dcbf75b782d13fb88603kschulz
167ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_HANDLE = "HANDLE";
168ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_RESULT = "result";
169ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_MSG_TYPE = "type";
170ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_URI = "uri";
171ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_RETRY = "retry";
172ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_TRANSPARENT = "transparent";
173ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public static final String EXTRA_MESSAGE_SENT_TIMESTAMP = "timestamp";
174ed70219e41ba68196798dcbf75b782d13fb88603kschulz
175ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private SmsBroadcastReceiver mSmsBroadcastReceiver = new SmsBroadcastReceiver();
176ed70219e41ba68196798dcbf75b782d13fb88603kschulz
177ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private boolean mInitialized = false;
178ed70219e41ba68196798dcbf75b782d13fb88603kschulz
179ed70219e41ba68196798dcbf75b782d13fb88603kschulz
180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    static final String[] SMS_PROJECTION = new String[] {
181326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms._ID,
182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.THREAD_ID,
183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.ADDRESS,
184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.BODY,
185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.DATE,
186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.READ,
187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.TYPE,
188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.STATUS,
189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Sms.LOCKED,
190326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms.ERROR_CODE
191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
193326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static final String[] SMS_PROJECTION_SHORT = new String[] {
194326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms._ID,
195326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Sms.THREAD_ID,
1965a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.TYPE,
1975a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.READ
1985a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
1995a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2005a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] SMS_PROJECTION_SHORT_EXT = new String[] {
2015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms._ID,
2025a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.THREAD_ID,
2035a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.ADDRESS,
2045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.BODY,
2055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.DATE,
2065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.READ,
2075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Sms.TYPE,
208326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    };
209326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
210326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static final String[] MMS_PROJECTION_SHORT = new String[] {
211326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Mms._ID,
212fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Mms.THREAD_ID,
213fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Mms.MESSAGE_TYPE,
2145a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_BOX,
2155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.READ
2165a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
2175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2185a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MMS_PROJECTION_SHORT_EXT = new String[] {
2195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms._ID,
2205a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.THREAD_ID,
2215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_TYPE,
2225a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.MESSAGE_BOX,
2235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.READ,
2245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.DATE,
2255a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.SUBJECT,
2265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Mms.PRIORITY
227fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
228fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2295a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT = new String[] {
230326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns._ID,
231326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns.FOLDER_ID,
232326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapContract.MessageColumns.FLAG_READ
233326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    };
234326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT_EXT = new String[] {
2365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns._ID,
2375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FOLDER_ID,
2385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_READ,
2395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.DATE,
2405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.SUBJECT,
2415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FROM_LIST,
2425a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY
2435a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
2445a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2455a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static final String[] MSG_PROJECTION_SHORT_EXT2 = new String[] {
2465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns._ID,
2475a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FOLDER_ID,
2485a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_READ,
2495a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.DATE,
2505a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.SUBJECT,
2515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FROM_LIST,
2525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY,
2535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.THREAD_ID,
2545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        BluetoothMapContract.MessageColumns.THREAD_NAME
2555a60e47497f21f64e6d79420dc4c56c1907df22akschulz    };
256326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
257326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public BluetoothMapContentObserver(final Context context,
2585a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMnsObexClient mnsClient,
2595a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMapMasInstance masInstance,
2605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            BluetoothMapAccountItem account,
2615a60e47497f21f64e6d79420dc4c56c1907df22akschulz            boolean enableSmsMms) throws RemoteException {
262fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mContext = context;
263fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mResolver = mContext.getContentResolver();
264326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mAccount = account;
265326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMasInstance = masInstance;
266326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMasId = mMasInstance.getMasId();
2675a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMapSupportedFeatures = mMasInstance.getRemoteFeatureMask();
2695a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (D) Log.d(TAG, "BluetoothMapContentObserver: Supported features " +
2705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Integer.toHexString(mMapSupportedFeatures) ) ;
2715a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2725a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if((BluetoothMapUtils.MAP_FEATURE_EXTENDED_EVENT_REPORT_11_BIT
2735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                & mMapSupportedFeatures) != 0){
2745a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
2755a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
2765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // Make sure support for all formats result in latest version returned
2775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if((BluetoothMapUtils.MAP_FEATURE_EVENT_REPORT_V12_BIT
2785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                & mMapSupportedFeatures) != 0){
2795a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2805a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
2815a60e47497f21f64e6d79420dc4c56c1907df22akschulz
282326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(account != null) {
283326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mAuthority = Uri.parse(account.mBase_uri).getAuthority();
284326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mMessageUri = Uri.parse(account.mBase_uri + "/" + BluetoothMapContract.TABLE_MESSAGE);
2855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (mAccount.getType() == TYPE.IM) {
2865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mContactUri = Uri.parse(account.mBase_uri + "/"
2875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + BluetoothMapContract.TABLE_CONVOCONTACT);
2885a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO: We need to release this again!
290326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient = mResolver.acquireUnstableContentProviderClient(mAuthority);
291326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (mProviderClient == null) {
292326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                throw new RemoteException("Failed to acquire provider for " + mAuthority);
293326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
294326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
2955a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactList = mMasInstance.getContactList();
2965a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mContactList == null) {
2975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setContactList(new HashMap<String, BluetoothMapConvoContactElement>(), false);
2985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                initContactsList();
2995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
300326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
301326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mEnableSmsMms = enableSmsMms;
302fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mSmsType = getSmsType();
303326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mMnsClient = mnsClient;
3045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Get the cached list - if any, else create */
3055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListSms = mMasInstance.getMsgListSms();
3065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean doInit = false;
3075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mEnableSmsMms) {
3085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListSms == null) {
3095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListSms(new HashMap<Long, Msg>(), false);
3105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3115a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMsgListMms = mMasInstance.getMsgListMms();
3135a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListMms == null) {
3145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMms(new HashMap<Long, Msg>(), false);
3155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3165a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3175a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mAccount != null) {
3195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMsgListMsg = mMasInstance.getMsgListMsg();
3205a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mMsgListMsg == null) {
3215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMsg(new HashMap<Long, Msg>(), false);
3225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                doInit = true;
3235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
3245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3255a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(doInit) {
3265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            initMsgList();
3275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3285a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3295a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3305a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3315a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListSms() {
3325a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListSms;
3335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3345a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListSms(Map<Long, Msg> msgListSms, boolean changesDetected) {
3365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListSms = msgListSms;
3375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3385a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListSms(msgListSms);
3415a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3425a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3435a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3445a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListMms() {
3455a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListMms;
3465a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3475a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3485a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3495a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListMms(Map<Long, Msg> msgListMms, boolean changesDetected) {
3505a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListMms = msgListMms;
3515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3525a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListMms(msgListMms);
355326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
356326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3575a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3585a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> getMsgListMsg() {
3595a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mMsgListMsg;
3605a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3615a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3625a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3635a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setMsgListMsg(Map<Long, Msg> msgListMsg, boolean changesDetected) {
3645a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMsgListMsg = msgListMsg;
3655a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateFolderVersionCounter();
3675a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setMsgListMsg(msgListMsg);
3695a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3715a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<String, BluetoothMapConvoContactElement> getContactList() {
3725a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mContactList;
3735a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3745a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3755a60e47497f21f64e6d79420dc4c56c1907df22akschulz
376326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
3775a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Currently we only have data for IM / email contacts
3785a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param contactList
3795a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param changesDetected that is not chat state changed nor presence state changed.
380326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
3815a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void setContactList(Map<String, BluetoothMapConvoContactElement> contactList,
3825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            boolean changesDetected) {
3835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mContactList = contactList;
3845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(changesDetected) {
3855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mMasInstance.updateImEmailConvoListVersionCounter();
3865a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
3875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mMasInstance.setContactList(contactList);
3885a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3895a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3905a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventNewMessage(long eventFilter) {
3915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_NEW_MESSAGE) > 0);
3925a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3935a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3945a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageDeleted(long eventFilter) {
3955a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_DELETED) > 0);
3965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
3975a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3985a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageShift(long eventFilter) {
3995a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_SHIFT) > 0);
4005a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4015a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4025a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventSendingSuccess(long eventFilter) {
4035a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_SENDING_SUCCESS) > 0);
4045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4055a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4065a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventSendingFailed(long eventFilter) {
4075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_SENDING_FAILED) > 0);
4085a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4095a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4105a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventDeliverySuccess(long eventFilter) {
4115a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_DELIVERY_SUCCESS) > 0);
4125a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4135a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4145a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventDeliveryFailed(long eventFilter) {
4155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_DELIVERY_FAILED) > 0);
4165a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4185a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventReadStatusChanged(long eventFilter) {
4195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_READ_STATUS_CHANGED) > 0);
4205a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4215a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4225a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventConversationChanged(long eventFilter) {
4235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_CONVERSATION_CHANGED) > 0);
4245a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4255a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4265a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventParticipantPresenceChanged(long eventFilter) {
4275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_PARTICIPANT_PRESENCE_CHANGED) > 0);
4285a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4295a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4305a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventParticipantChatstateChanged(long eventFilter) {
4315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_PARTICIPANT_CHATSTATE_CHANGED) > 0);
4325a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4335a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4345a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static boolean sendEventMessageRemoved(long eventFilter) {
4355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return ((eventFilter & EVENT_FILTER_MESSAGE_REMOVED) > 0);
436fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
437fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
438fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private TYPE getSmsType() {
439fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        TYPE smsType = null;
4405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
4415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
442fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4432e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta        if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
444fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            smsType = TYPE.SMS_CDMA;
4452e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta        } else {
4462e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta            smsType = TYPE.SMS_GSM;
447fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
448fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
449fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return smsType;
450fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
451fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4525a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private final ContentObserver mObserver = new ContentObserver(
4535a60e47497f21f64e6d79420dc4c56c1907df22akschulz            new Handler(Looper.getMainLooper())) {
454fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
455fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onChange(boolean selfChange) {
456fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            onChange(selfChange, null);
457fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
458fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onChange(boolean selfChange, Uri uri) {
4615a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(uri == null) {
4625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG, "onChange() with URI == null - not handled.");
4635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
4645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (V) Log.d(TAG, "onChange on thread: " + Thread.currentThread().getId()
4665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    + " Uri: " + uri.toString() + " selfchange: " + selfChange);
467fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(uri.toString().contains(BluetoothMapContract.TABLE_CONVOCONTACT))
4695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleContactListChanges(uri);
4705a60e47497f21f64e6d79420dc4c56c1907df22akschulz            else
4715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChanges(uri);
472fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
473fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
474fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4755a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final HashMap<Integer, String> FOLDER_SMS_MAP;
4765a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static {
4775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP = new HashMap<Integer, String>();
4785a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_INBOX,  BluetoothMapContract.FOLDER_NAME_INBOX);
4795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_SENT,  BluetoothMapContract.FOLDER_NAME_SENT);
4805a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_DRAFT,  BluetoothMapContract.FOLDER_NAME_DRAFT);
4815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_OUTBOX,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
4825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_FAILED,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
4835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_SMS_MAP.put(Sms.MESSAGE_TYPE_QUEUED,  BluetoothMapContract.FOLDER_NAME_OUTBOX);
4845a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
485fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
4865a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static String getSmsFolderName(int type) {
4875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String name = FOLDER_SMS_MAP.get(type);
4885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(name != null) {
4895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return name;
4905a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
4915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Log.e(TAG, "New SMS mailbox types have been introduced, without an update in BT...");
4925a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return "Unknown";
4935a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
4945a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4955a60e47497f21f64e6d79420dc4c56c1907df22akschulz
4965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static final HashMap<Integer, String> FOLDER_MMS_MAP;
4975a60e47497f21f64e6d79420dc4c56c1907df22akschulz    static {
4985a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP = new HashMap<Integer, String>();
4995a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_INBOX,  BluetoothMapContract.FOLDER_NAME_INBOX);
5005a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_SENT,   BluetoothMapContract.FOLDER_NAME_SENT);
5015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_DRAFTS, BluetoothMapContract.FOLDER_NAME_DRAFT);
5025a60e47497f21f64e6d79420dc4c56c1907df22akschulz        FOLDER_MMS_MAP.put(Mms.MESSAGE_BOX_OUTBOX, BluetoothMapContract.FOLDER_NAME_OUTBOX);
5035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5045a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5055a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private static String getMmsFolderName(int mailbox) {
5065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String name = FOLDER_MMS_MAP.get(mailbox);
5075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(name != null) {
5085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return name;
5095a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
5105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Log.e(TAG, "New MMS mailboxes have been introduced, without an update in BT...");
5115a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return "Unknown";
5125a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5135a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5145a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
5155a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Set the folder structure to be used for this instance.
5165a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param folderStructure
5175a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
5185a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public void setFolderStructure(BluetoothMapFolderElement folderStructure) {
5195a60e47497f21f64e6d79420dc4c56c1907df22akschulz        this.mFolders = folderStructure;
5205a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
5215a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5225a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private class ConvoContactInfo {
5235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColConvoId         = -1;
5245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColLastActivity    = -1;
5255a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mConvoColName            = -1;
5265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        //        public int mConvoColRead            = -1;
5275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        //        public int mConvoColVersionCounter  = -1;
5285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColUci           = -1;
5295a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColConvoId       = -1;
5305a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColName          = -1;
5315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColNickname      = -1;
5325a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColBtUid         = -1;
5335a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColChatState     = -1;
5345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColContactId     = -1;
5355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColLastActive    = -1;
5365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPresenceState = -1;
5375a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPresenceText  = -1;
5385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColPriority      = -1;
5395a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public int mContactColLastOnline    = -1;
5405a60e47497f21f64e6d79420dc4c56c1907df22akschulz
5415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public void setConvoColunms(Cursor c) {
5425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColConvoId         = c.getColumnIndex(
5435a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.THREAD_ID);
5445a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColLastActivity    = c.getColumnIndex(
5455a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.LAST_THREAD_ACTIVITY);
5465a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //            mConvoColName            = c.getColumnIndex(
5475a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //                    BluetoothMapContract.ConversationColumns.THREAD_NAME);
5485a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColConvoId       = c.getColumnIndex(
5495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.CONVO_ID);
5505a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColName          = c.getColumnIndex(
5515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NAME);
5525a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColNickname      = c.getColumnIndex(
5535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NICKNAME);
5545a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColBtUid         = c.getColumnIndex(
5555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.X_BT_UID);
5565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColChatState     = c.getColumnIndex(
5575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.CHAT_STATE);
5585a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColUci           = c.getColumnIndex(
5595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.UCI);
5605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColNickname      = c.getColumnIndex(
5615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NICKNAME);
5625a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColLastActive    = c.getColumnIndex(
5635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.LAST_ACTIVE);
5645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColName          = c.getColumnIndex(
5655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.NAME);
5665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPresenceState = c.getColumnIndex(
5675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.PRESENCE_STATE);
5685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPresenceText  = c.getColumnIndex(
5695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.STATUS_TEXT);
5705a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColPriority      = c.getColumnIndex(
5715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.PRIORITY);
5725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mContactColLastOnline    = c.getColumnIndex(
5735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapContract.ConvoContactColumns.LAST_ONLINE);
5745a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
5755a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
576fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
577fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class Event {
578fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String eventType;
579fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle;
5805a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String folder = null;
5815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String oldFolder = null;
582fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        TYPE msgType;
5835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Extended event parameters in MAP Event version 1.1 */
5845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String datetime = null; // OBEX time "YYYYMMDDTHHMMSS"
5855a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String uci = null;
5865a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String subject = null;
5875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String senderName = null;
5885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String priority = null;
5895a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Event parameters in MAP Event version 1.2 */
5905a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String conversationName = null;
5915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long conversationID = -1;
5925a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int presenceState = BluetoothMapContract.PresenceState.UNKNOWN;
5935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        String presenceStatus = null;
5945a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int chatState = BluetoothMapContract.ChatState.UNKNOWN;
595fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
596326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        final static String PATH = "telecom/msg/";
597326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
5985a60e47497f21f64e6d79420dc4c56c1907df22akschulz        private void setFolderPath(String name, TYPE type) {
5995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (name != null) {
6005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(type == TYPE.EMAIL || type == TYPE.IM) {
6015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    this.folder = name;
602326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
6035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    this.folder = PATH + name;
604326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
605fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
606fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                this.folder = null;
607fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
6085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6095a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder,
6115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String oldFolder, TYPE msgType) {
6125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6135a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6145a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
615fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (oldFolder != null) {
6165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msgType == TYPE.EMAIL || msgType == TYPE.IM) {
617326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    this.oldFolder = oldFolder;
618326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
619326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    this.oldFolder = PATH + oldFolder;
620326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
621fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
622fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                this.oldFolder = null;
623fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
624fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.msgType = msgType;
625fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
626fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
6275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType) {
6285a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6305a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6315a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6325a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6335a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.1 */
6355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType,
6365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String datetime, String subject, String senderName, String priority) {
6375a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6385a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6395a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6405a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6415a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = datetime;
6425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (subject != null) {
6435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.subject = BluetoothMapUtils.stripInvalidChars(subject);
6445a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6455a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (senderName != null) {
6465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(senderName);
6475a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6485a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
6495a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6505a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6515a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.2 message events */
6525a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, long handle, String folder, TYPE msgType,
6535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String datetime, String subject, String senderName, String priority,
6545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                long conversationID, String conversationName) {
6555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.handle = handle;
6575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setFolderPath(folder, msgType);
6585a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6595a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = datetime;
6605a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (subject != null) {
6615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.subject = BluetoothMapUtils.stripInvalidChars(subject);
6625a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6635a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (senderName != null) {
6645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(senderName);
6655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationID != 0) {
6675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationID = conversationID;
6685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6695a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationName != null) {
6705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationName = BluetoothMapUtils.stripInvalidChars(conversationName);
6715a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
6735a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
6745a60e47497f21f64e6d79420dc4c56c1907df22akschulz
6755a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* extended event type 1.2 for conversation, presence or chat state changed events */
6765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Event(String eventType, String uci, TYPE msgType, String name, String priority,
6775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                String lastActivity, long conversationID, String conversationName,
6785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                int presenceState, String presenceStatus, int chatState) {
6795a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.eventType = eventType;
6805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.uci = uci;
6815a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.msgType = msgType;
6825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (name != null) {
6835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.senderName = BluetoothMapUtils.stripInvalidChars(name);
6845a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.priority = priority;
6865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.datetime = lastActivity;
6875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationID != 0) {
6885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationID = conversationID;
6895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (conversationName != null) {
6915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.conversationName = BluetoothMapUtils.stripInvalidChars(conversationName);
6925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6935a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (presenceState != BluetoothMapContract.PresenceState.UNKNOWN) {
6945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.presenceState = presenceState;
6955a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6965a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (presenceStatus != null) {
6975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.presenceStatus = BluetoothMapUtils.stripInvalidChars(presenceStatus);
6985a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
6995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (chatState != BluetoothMapContract.ChatState.UNKNOWN) {
7005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                this.chatState = chatState;
7015a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
7025a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
7035a60e47497f21f64e6d79420dc4c56c1907df22akschulz
704fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public byte[] encode() throws UnsupportedEncodingException {
705fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            StringWriter sw = new StringWriter();
706fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            XmlSerializer xmlEvtReport = Xml.newSerializer();
7075a60e47497f21f64e6d79420dc4c56c1907df22akschulz
708fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
709fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.setOutput(sw);
7105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                xmlEvtReport.startDocument("UTF-8", true);
711326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                xmlEvtReport.text("\r\n");
71270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                xmlEvtReport.startTag("", "MAP-event-report");
7135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
7145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V10_STR);
7155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
7165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V11_STR);
7175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
7185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "version", BluetoothMapUtils.MAP_V12_STR);
7195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
720fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.startTag("", "event");
721fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.attribute("", "type", eventType);
7225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (eventType.equals(EVENT_TYPE_CONVERSATION) ||
7235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        eventType.equals(EVENT_TYPE_PRESENCE) ||
7245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        eventType.equals(EVENT_TYPE_CHAT_STATE)) {
7255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "participant_uci", uci);
7265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
7275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "handle",
7285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapUtils.getMapHandle(handle, msgType));
7295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7305a60e47497f21f64e6d79420dc4c56c1907df22akschulz
731fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (folder != null) {
732fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    xmlEvtReport.attribute("", "folder", folder);
733fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
734fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (oldFolder != null) {
735fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    xmlEvtReport.attribute("", "old_folder", oldFolder);
736fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
7372e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                /* Avoid possible NPE for "msgType" "null" value. "msgType"
7382e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                 * is a implied attribute and will be set "null" for events
7392e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                 * like "memory full" or "memory available" */
7402e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                if (msgType != null) {
7412e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                    xmlEvtReport.attribute("", "msg_type", msgType.name());
7422e7dd83a6b3b4bf15e0dec6aad9ab826e6e2531bHemant Gupta                }
7435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* If MAP event report version is above 1.0 send
7445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * extended event report parameters */
7455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (datetime != null) {
7465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "datetime", datetime);
7475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (subject != null) {
7495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "subject",
7505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            subject.substring(0,subject.length() < 256 ? subject.length() : 256));
7515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (senderName != null) {
7535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "senderName", senderName);
7545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (priority != null) {
7565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    xmlEvtReport.attribute("", "priority", priority);
7575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7585a60e47497f21f64e6d79420dc4c56c1907df22akschulz
7595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                //}
7605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Include conversation information from event version 1.2 */
7615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (mMapEventReportVersion > BluetoothMapUtils.MAP_EVENT_REPORT_V11 ) {
7625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (conversationName != null) {
7635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        xmlEvtReport.attribute("", "conversation_name", conversationName);
7645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (conversationID != -1) {
7665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        // Convert provider conversation handle to string incl type
7675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        xmlEvtReport.attribute("", "conversation_id",
7685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapUtils.getMapConvoHandle(conversationID, msgType));
7695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (eventType.equals(EVENT_TYPE_PRESENCE)) {
7715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (presenceState != 0) {
7725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
7735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "presence_availability",
7745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String.valueOf(presenceState));
7755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
7765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (presenceStatus != null) {
7775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
7785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "presence_status",
7795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    presenceStatus.substring(
7805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            0,presenceStatus.length() < 256 ? subject.length() : 256));
7815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
7825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (eventType.equals(EVENT_TYPE_PRESENCE)) {
7845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (chatState != 0) {
7855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Convert provider conversation handle to string incl type
7865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            xmlEvtReport.attribute("", "chat_state", String.valueOf(chatState));
7875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
7885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
7895a60e47497f21f64e6d79420dc4c56c1907df22akschulz
7905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
7915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                xmlEvtReport.endTag("", "event");
79270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                xmlEvtReport.endTag("", "MAP-event-report");
793fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                xmlEvtReport.endDocument();
794fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalArgumentException e) {
795326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
796fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalStateException e) {
797326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
798fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IOException e) {
799326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(D) Log.w(TAG,e);
800fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
801fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
802326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (V) Log.d(TAG, sw.toString());
803fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
804fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return sw.toString().getBytes("UTF-8");
805fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
806fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
807fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
8085a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /*package*/ class Msg {
809fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long id;
810326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int type;               // Used as folder for SMS/MMS
811326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int threadId;           // Used for SMS/MMS at delete
812326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long folderId = -1;     // Email folder ID
813326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long oldFolderId = -1;  // Used for email undelete
814326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean localInitiatedSend = false; // Used for MMS to filter out events
815326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean transparent = false; // Used for EMAIL to delete message sent with transparency
8165a60e47497f21f64e6d79420dc4c56c1907df22akschulz        int flagRead = -1;      // Message status read/unread
817326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Msg(long id, int type, int threadId, int readFlag) {
819fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.id = id;
820fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.type = type;
821326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.threadId = threadId;
8225a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.flagRead = readFlag;
823326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
8245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        public Msg(long id, long folderId, int readFlag) {
825326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.id = id;
826326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.folderId = folderId;
8275a60e47497f21f64e6d79420dc4c56c1907df22akschulz            this.flagRead = readFlag;
828326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
829326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
830326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* Eclipse generated hashCode() and equals() to make
831326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * hashMap lookup work independent of whether the obj
832326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * is used for email or SMS/MMS and whether or not the
833326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * oldFolder is set. */
834326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        @Override
835326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        public int hashCode() {
836326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            final int prime = 31;
837326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            int result = 1;
838326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            result = prime * result + (int) (id ^ (id >>> 32));
839326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return result;
840fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
841fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
842326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        @Override
843326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        public boolean equals(Object obj) {
844326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (this == obj)
845326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return true;
846326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (obj == null)
847326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
848326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (getClass() != obj.getClass())
849326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
850326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Msg other = (Msg) obj;
851326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (id != other.id)
852326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false;
853326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return true;
854326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
855326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
856fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
8575a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListSms = null;
8585a60e47497f21f64e6d79420dc4c56c1907df22akschulz
8595a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListMms = null;
860326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8615a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<Long, Msg> mMsgListMsg = null;
862326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
8635a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private Map<String, BluetoothMapConvoContactElement> mContactList = null;
864326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
865326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public int setNotificationRegistration(int notificationStatus) throws RemoteException {
866326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Forward the request to the MNS thread as a message - including the MAS instance ID.
867326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(D) Log.d(TAG,"setNotificationRegistration() enter");
868326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Handler mns = mMnsClient.getMessageHandler();
869326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mns != null) {
870326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Message msg = mns.obtainMessage();
871326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.what = BluetoothMnsObexClient.MSG_MNS_NOTIFICATION_REGISTRATION;
872326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.arg1 = mMasId;
873326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.arg2 = notificationStatus;
874326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mns.sendMessageDelayed(msg, 10); // Send message without forcing a context switch
875326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Some devices - e.g. PTS needs to get the unregister confirm before we actually
876326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde             * disconnect the MNS. */
8775a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(D) Log.d(TAG,"setNotificationRegistration() MSG_MNS_NOTIFICATION_REGISTRATION " +
8785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    "send to MNS");
879326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
880326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // This should not happen except at shutdown.
881326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG,"setNotificationRegistration() Unable to send registration request");
882326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
883326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
884326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(notificationStatus == BluetoothMapAppParams.NOTIFICATION_STATUS_YES) {
885326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            registerObserver();
886326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
887326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            unregisterObserver();
888326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
889326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return ResponseCodes.OBEX_HTTP_OK;
890326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
891fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
8925a60e47497f21f64e6d79420dc4c56c1907df22akschulz    boolean eventMaskContainsContacts(long mask) {
8935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return sendEventParticipantPresenceChanged(mask);
8945a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
8955a60e47497f21f64e6d79420dc4c56c1907df22akschulz
8965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    boolean eventMaskContainsCovo(long mask) {
8975a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return (sendEventConversationChanged(mask)
8985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                || sendEventParticipantChatstateChanged(mask));
8995a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9005a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9015a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* Overwrite the existing notification filter. Will register/deregister observers for
9025a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * the Contacts and Conversation table as needed. We keep the message observer
9035a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * at all times. */
9045a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /*package*/ synchronized void setNotificationFilter(long newFilter) {
9055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long oldFilter = mEventFilter;
9065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mEventFilter = newFilter;
9075a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Contacts */
9085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(!eventMaskContainsContacts(oldFilter) &&
9095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                eventMaskContainsContacts(newFilter)) {
9105a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO:
9115a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Enable the observer
9125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Reset the contacts list
9135a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9145a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Conversations */
9155a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(!eventMaskContainsCovo(oldFilter) &&
9165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                eventMaskContainsCovo(newFilter)) {
9175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO:
9185a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Enable the observer
9195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Reset the conversations list
9205a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9215a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9225a60e47497f21f64e6d79420dc4c56c1907df22akschulz
923326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public void registerObserver() throws RemoteException{
924fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "registerObserver");
925326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
926326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (mObserverRegistered)
927326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return;
928326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
929326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mAccount != null) {
930326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
931326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient = mResolver.acquireUnstableContentProviderClient(mAuthority);
932326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (mProviderClient == null) {
933326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                throw new RemoteException("Failed to acquire provider for " + mAuthority);
934326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
935326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mProviderClient.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
936326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
9375a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // If there is a change in the database before we init the lists we will be sending
9385a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // loads of events - hence init before register.
9395a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount.getType() == TYPE.IM) {
9405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                // Further add contact list tracking
9415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                initContactsList();
9425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
9435a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9445a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // If there is a change in the database before we init the lists we will be sending
9455a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // loads of events - hence init before register.
9465a60e47497f21f64e6d79420dc4c56c1907df22akschulz        initMsgList();
9475a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9485a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Use MmsSms Uri since the Sms Uri is not notified on deletes */
9495a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mEnableSmsMms){
9505a60e47497f21f64e6d79420dc4c56c1907df22akschulz            //this is sms/mms
9515a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mResolver.registerContentObserver(MmsSms.CONTENT_URI, false, mObserver);
9525a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mObserverRegistered = true;
9535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9545a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9555a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mAccount != null) {
956326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* For URI's without account ID */
9575a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Uri uri = Uri.parse(mAccount.mBase_uri_no_account + "/"
9585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    + BluetoothMapContract.TABLE_MESSAGE);
959326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG, "Registering observer for: " + uri);
960326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mResolver.registerContentObserver(uri, true, mObserver);
961326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
962326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* For URI's with account ID - is handled the same way as without ID, but is
963326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde             * only triggered for MAS instances with matching account ID. */
964326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            uri = Uri.parse(mAccount.mBase_uri + "/" + BluetoothMapContract.TABLE_MESSAGE);
965326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(D) Log.d(TAG, "Registering observer for: " + uri);
966326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mResolver.registerContentObserver(uri, true, mObserver);
9675a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount.getType() == TYPE.IM) {
9695a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                uri = Uri.parse(mAccount.mBase_uri_no_account + "/"
9715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + BluetoothMapContract.TABLE_CONVOCONTACT);
9725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "Registering observer for: " + uri);
9735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mResolver.registerContentObserver(uri, true, mObserver);
9745a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* For URI's with account ID - is handled the same way as without ID, but is
9765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * only triggered for MAS instances with matching account ID. */
9775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                uri = Uri.parse(mAccount.mBase_uri + "/" + BluetoothMapContract.TABLE_CONVOCONTACT);
9785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "Registering observer for: " + uri);
9795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mResolver.registerContentObserver(uri, true, mObserver);
9805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
9815a60e47497f21f64e6d79420dc4c56c1907df22akschulz
982326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mObserverRegistered = true;
983326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
984fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
985fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
9865a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public void unregisterObserver() {
9875a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.d(TAG, "unregisterObserver");
9885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mResolver.unregisterContentObserver(mObserver);
9895a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mObserverRegistered = false;
9905a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mProviderClient != null){
9915a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mProviderClient.release();
9925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mProviderClient = null;
9935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
9945a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
9955a60e47497f21f64e6d79420dc4c56c1907df22akschulz
9965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
9975a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * Per design it is only possible to call the refreshXxxx functions sequentially, hence it
9985a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * is safe to modify mTransmitEvents without synchronization.
9995a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
10005a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* package */ void refreshFolderVersionCounter() {
10015a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mObserverRegistered) {
10025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // As we have observers, we already keep the counter up-to-date.
10035a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
10045a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10055a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* We need to perform the same functionality, as when we receive a notification change,
10065a60e47497f21f64e6d79420dc4c56c1907df22akschulz           hence we:
10075a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - disable the event transmission
10085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - triggers the code for updates
10095a60e47497f21f64e6d79420dc4c56c1907df22akschulz            - enable the event transmission */
10105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mTransmitEvents = false;
10115a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
10125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mEnableSmsMms) {
10135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesSms();
10145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesMms();
10155a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10165a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mAccount != null) {
10175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                try {
10185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    handleMsgListChangesMsg(mMessageUri);
10195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } catch (RemoteException e) {
10205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Log.e(TAG, "Unable to update FolderVersionCounter. - Not fatal, but can cause" +
10215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            " undesirable user experience!", e);
10225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
10235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10245a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
10255a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Ensure we always enable events again
10265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mTransmitEvents = true;
10275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10285a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
10295a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10305a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /* package */ void refreshConvoListVersionCounter() {
10315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mObserverRegistered) {
10325a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // As we have observers, we already keep the counter up-to-date.
10335a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
10345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10355a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* We need to perform the same functionality, as when we receive a notification change,
10365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        hence we:
10375a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - disable event transmission
10385a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - triggers the code for updates
10395a60e47497f21f64e6d79420dc4c56c1907df22akschulz         - enable event transmission */
10405a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mTransmitEvents = false;
10415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
10425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if((mAccount != null) && (mContactUri != null)) {
10435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleContactListChanges(mContactUri);
10445a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10455a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
10465a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // Ensure we always enable events again
10475a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mTransmitEvents = true;
1048326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1049fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1050fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1051fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void sendEvent(Event evt) {
10525a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10535a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mTransmitEvents == false) {
10545a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(V) Log.v(TAG, "mTransmitEvents == false - don't send event.");
10555a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
10565a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
10575a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10585a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(D)Log.d(TAG, "sendEvent: " + evt.eventType + " " + evt.handle + " " + evt.folder + " "
10595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + evt.oldFolder + " " + evt.msgType.name() + " " + evt.datetime + " "
10605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + evt.subject + " " + evt.senderName + " " + evt.priority );
1061fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
10620e7e149687b0b5e340991b20c9d8e5232e8d3e39Hemant Gupta        if (mMnsClient == null || mMnsClient.isConnected() == false) {
10630e7e149687b0b5e340991b20c9d8e5232e8d3e39Hemant Gupta            Log.d(TAG, "sendEvent: No MNS client registered or connected- don't send event");
1064fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return;
1065fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1066fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
10675a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Enable use of the cache for checking the filter */
10685a60e47497f21f64e6d79420dc4c56c1907df22akschulz        long eventFilter = mEventFilter;
10695a60e47497f21f64e6d79420dc4c56c1907df22akschulz
10705a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* This should have been a switch on the string, but it is not allowed in Java 1.6 */
10715a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* WARNING: Here we do pointer compare for the string to speed up things, that is.
10725a60e47497f21f64e6d79420dc4c56c1907df22akschulz         * HENCE: always use the EVENT_TYPE_"defines" */
10735a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(evt.eventType == EVENT_TYPE_NEW) {
10745a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventNewMessage(eventFilter)) {
10755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
10765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
10775a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10785a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELETE) {
10795a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageDeleted(eventFilter)) {
10805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
10815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
10825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_REMOVED) {
10845a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageRemoved(eventFilter)) {
10855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
10865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
10875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SHIFT) {
10895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventMessageShift(eventFilter)) {
10905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
10915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
10925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELEVERY_SUCCESS) {
10945a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventDeliverySuccess(eventFilter)) {
10955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
10965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
10975a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
10985a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SENDING_SUCCESS) {
10995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventSendingSuccess(eventFilter)) {
11005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11035a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_SENDING_FAILURE) {
11045a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventSendingFailed(eventFilter)) {
11055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11075a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_DELIVERY_FAILURE) {
11095a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventDeliveryFailed(eventFilter)) {
11105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11125a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11135a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_READ_STATUS) {
11145a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventReadStatusChanged(eventFilter)) {
11155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11185a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_CONVERSATION) {
11195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventConversationChanged(eventFilter)) {
11205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11225a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_PRESENCE) {
11245a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventParticipantPresenceChanged(eventFilter)) {
11255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11275a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if(evt.eventType == EVENT_TYPE_CHAT_STATE) {
11295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(!sendEventParticipantChatstateChanged(eventFilter)) {
11305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D)Log.d(TAG, "Skip sending event of type: " + evt.eventType);
11315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                return;
11325a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
11335a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
11345a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        try {
1136fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mMnsClient.sendEvent(evt.encode(), mMasId);
1137fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (UnsupportedEncodingException ex) {
1138fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            /* do nothing */
11395a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.e(TAG, "Exception - should not happen: ",ex);
1140fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1141fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1142fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1143326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void initMsgList() throws RemoteException {
1144fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "initMsgList");
1145fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1146326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mEnableSmsMms) {
1147fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1148326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
1149fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1150326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Cursor c = mResolver.query(Sms.CONTENT_URI,
11515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    SMS_PROJECTION_SHORT, null, null, null);
115228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
11535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
11545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
11555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Sms._ID));
11565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Sms.TYPE));
11575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
11585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Sms.READ));
1159fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
11605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, type, threadId, read);
11615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgListSms.put(id, msg);
11625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
116328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
116428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
11655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1166326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
116728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
11685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListSms()) {
11695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListSms().clear();
11705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListSms(msgListSms, true); // Set initial folder version counter
1171326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1172fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1173326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>();
1174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1175326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            c = mResolver.query(Mms.CONTENT_URI, MMS_PROJECTION_SHORT, null, null, null);
117628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
11775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
11785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
11795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Mms._ID));
11805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
11815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
11825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Mms.READ));
1183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
11845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, type, threadId, read);
11855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgListMms.put(id, msg);
11865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
118728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
118828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
11895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1190326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
119128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
11925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMms()) {
11935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMms().clear();
11945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMms(msgListMms, true); // Set initial folder version counter
1195326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1196fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1197fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1198326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mAccount != null) {
11995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            HashMap<Long, Msg> msgList = new HashMap<Long, Msg>();
1200326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uri = mMessageUri;
12015a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Cursor c = mProviderClient.query(uri, MSG_PROJECTION_SHORT, null, null, null);
1202326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
120328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
12045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
12055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
12065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(MessageColumns._ID));
12075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long folderId = c.getInt(c.getColumnIndex(
12085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FOLDER_ID));
12095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int readFlag = c.getInt(c.getColumnIndex(
12105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FLAG_READ));
12115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = new Msg(id, folderId, readFlag);
12125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgList.put(id, msg);
12135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
121428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
121528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
12165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
12175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
12185a60e47497f21f64e6d79420dc4c56c1907df22akschulz
12195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
12205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMsg().clear();
12215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                setMsgListMsg(msgList, true);
1222326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
12235a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12245a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
122528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
12265a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void initContactsList() throws RemoteException {
12275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.d(TAG, "initContactsList");
12285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mContactUri == null) {
12295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.d(TAG, "initContactsList() no mContactUri - nothing to init");
12305a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return;
12315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12325a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Uri uri = mContactUri;
12335a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mProviderClient.query(uri,
12345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                BluetoothMapContract.BT_CONTACT_CHATSTATE_PRESENCE_PROJECTION,
12355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null, null, null);
12365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Map<String, BluetoothMapConvoContactElement> contactList =
12375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                new HashMap<String, BluetoothMapConvoContactElement>();
12385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        try {
12395a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
12405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                ConvoContactInfo cInfo = new ConvoContactInfo();
12415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                cInfo.setConvoColunms(c);
12425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
12435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long convoId = c.getLong(cInfo.mContactColConvoId);
12445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (convoId == 0)
12455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
12465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (V) BluetoothMapUtils.printCursor(c);
12475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String uci = c.getString(cInfo.mContactColUci);
12485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String name = c.getString(cInfo.mContactColName);
12495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String displayName = c.getString(cInfo.mContactColNickname);
12505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String presenceStatus = c.getString(cInfo.mContactColPresenceText);
12515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int presenceState = c.getInt(cInfo.mContactColPresenceState);
12525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long lastActivity = c.getLong(cInfo.mContactColLastActive);
12535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int chatState = c.getInt(cInfo.mContactColChatState);
12545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int priority = c.getInt(cInfo.mContactColPriority);
12555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String btUid = c.getString(cInfo.mContactColBtUid);
12565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapConvoContactElement contact =
12575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            new BluetoothMapConvoContactElement(uci, name, displayName,
12585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    presenceStatus, presenceState, lastActivity, chatState,
12595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority, btUid);
12605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    contactList.put(uci, contact);
12615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
1262326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
12635a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } finally {
12645a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
12655a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12665a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getContactList()) {
12675a60e47497f21f64e6d79420dc4c56c1907df22akschulz            getContactList().clear();
12685a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setContactList(contactList, true);
1269326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1270fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1271fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1272fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void handleMsgListChangesSms() {
1273fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "handleMsgListChangesSms");
1274fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1275fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
12765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
1277fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
12785a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
12795a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
12805a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mResolver.query(Sms.CONTENT_URI,
12815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    SMS_PROJECTION_SHORT, null, null, null);
12825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else {
12835a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mResolver.query(Sms.CONTENT_URI,
12845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    SMS_PROJECTION_SHORT_EXT, null, null, null);
12855a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
12865a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListSms()) {
128728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
12885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
12895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
12905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Sms._ID));
12915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Sms.TYPE));
12925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
12935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Sms.READ));
12945a60e47497f21f64e6d79420dc4c56c1907df22akschulz
12955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().remove(id);
12965a60e47497f21f64e6d79420dc4c56c1907df22akschulz
12975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send e.g.
12985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * a message deleted and/or MessageShift for messages deleted by the MCE. */
12995a60e47497f21f64e6d79420dc4c56c1907df22akschulz
13005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
13015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message */
13025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, type, threadId, read);
13035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListSms.put(id, msg);
13045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
13055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Event evt;
13065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mTransmitEvents == true && // extract contact details only if needed
13075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mMapEventReportVersion >
13085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
13095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
13105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(Sms.DATE)));
13115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(Sms.BODY));
13125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String name = "";
13135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String phone = "";
13145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (type == 1) { //inbox
13155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    phone = c.getString(c.getColumnIndex(Sms.ADDRESS));
13165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (phone != null && !phone.isEmpty()) {
13175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = BluetoothMapContent.getContactNameFromPhone(phone,
13185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mResolver);
13195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if(name == null || name.isEmpty()){
13205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            name = phone;
13215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
13225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }else{
13235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = phone;
13245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
13255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
13265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    TelephonyManager tm =
13275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (TelephonyManager)mContext.getSystemService(
13285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            Context.TELEPHONY_SERVICE);
13295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (tm != null) {
13305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        phone = tm.getLine1Number();
13315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        name = tm.getLine1AlphaTag();
13325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if(name == null || name.isEmpty()){
13335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            name = phone;
13345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
13355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
13365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
13375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";// no priority for sms
13385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
13395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
13405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
13415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
13425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mSmsType, date, subject, name, priority);
13435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
13445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
13455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mSmsType, date, subject, name, priority,
13465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (long)threadId, null);
13475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
13485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else {
13495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
13505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, getSmsFolderName(type),
13515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, mSmsType);
13525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
13535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
13545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
13555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
13565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (type != msg.type) {
13575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
13585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "new type: " + type + " old type: " + msg.type);
13595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String oldFolder = getSmsFolderName(msg.type);
13605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String newFolder = getSmsFolderName(type);
13615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                // Filter out the intermediate outbox steps
13625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(!oldFolder.equalsIgnoreCase(newFolder)) {
13635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
13645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(type), oldFolder, mSmsType);
13655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
13665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
13675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.type = type;
13685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else if(threadId != msg.threadId) {
13695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
13705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "Message delete change: type: " + type
13715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + " old type: " + msg.type
13725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + "\n    threadId: " + threadId
13735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + " old threadId: " + msg.threadId);
13745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(threadId == DELETED_THREAD_ID) { // Message deleted
13755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // TODO:
13765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // We shall only use the folder attribute, but can't remember
13775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // wether to set it to "deleted" or the name of the folder
13785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // from which the message have been deleted.
1379cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
13805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
1381cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            getSmsFolderName(msg.type), null, mSmsType);
13825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
13835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
13845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else { // Undelete
13855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
13865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(msg.type),
13875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.FOLDER_NAME_DELETED, mSmsType);
13885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
13895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
13905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1391326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
13925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(read != msg.flagRead) {
13935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
13945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.flagRead = read;
13955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
13965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
13975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id,
13985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getSmsFolderName(msg.type), mSmsType);
13995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
14005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1401326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
14025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListSms.put(id, msg);
1403fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
14045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
140528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
140628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
14075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1408fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1409fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
14105a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListSms().values()) {
1411cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // "old_folder" used only for MessageShift event
1412326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
1413cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        getSmsFolderName(msg.type), null, mSmsType);
1414fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
14155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1416fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1417fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
14185a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListSms(msgListSms, listChanged);
1419fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1420fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1421fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1422fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void handleMsgListChangesMms() {
1423fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (V) Log.d(TAG, "handleMsgListChangesMms");
1424fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1425fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>();
14265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
14275a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
14285a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
14295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mResolver.query(Mms.CONTENT_URI,
14305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    MMS_PROJECTION_SHORT, null, null, null);
14315a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else {
14325a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mResolver.query(Mms.CONTENT_URI,
14335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    MMS_PROJECTION_SHORT_EXT, null, null, null);
14345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
1435fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
14365a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMms()) {
14375a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try{
14385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
14395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
14405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(Mms._ID));
14415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
14425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int mtype = c.getInt(c.getColumnIndex(Mms.MESSAGE_TYPE));
14435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
14445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        // TODO: Go through code to see if we have an issue with mismatch in types
14455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        //       for threadId. Seems to be a long in DB??
14465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int read = c.getInt(c.getColumnIndex(Mms.READ));
14475a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().remove(id);
14495a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send
14515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * e.g. a message deleted and/or MessageShift for messages deleted by the
14525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * MCE.*/
14535a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
14555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message - only notify on retrieve conf */
14565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
14575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (getMmsFolderName(type).equalsIgnoreCase(
14585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    BluetoothMapContract.FOLDER_NAME_INBOX) &&
14595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mtype != MESSAGE_TYPE_RETRIEVE_CONF) {
1460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                                continue;
14615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
14625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, type, threadId, read);
14635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListMms.put(id, msg);
1464326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Event evt;
14655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mTransmitEvents == true && // extract contact details only if needed
14665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    mMapEventReportVersion !=
14675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
14685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
14695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(Mms.DATE)));
14705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(Mms.SUBJECT));
14715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (subject == null || subject.length() == 0) {
14725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /* Get subject from mms text body parts - if any exists */
14735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    subject = BluetoothMapContent.getTextPartsMms(mResolver, id);
14745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
14755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                int tmpPri = c.getInt(c.getColumnIndex(Mms.PRIORITY));
14765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "TEMP handleMsgListChangesMms, " +
14775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        "newMessage 'read' state: " + read +
14785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        "priority: " + tmpPri);
14795a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String address = BluetoothMapContent.getAddressMms(
14815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mResolver,id,BluetoothMapContent.MMS_FROM);
14825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";
14835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(tmpPri == PduHeaders.PRIORITY_HIGH)
14845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority = "yes";
14855a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
14875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
14885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
14895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
14905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            TYPE.MMS, date, subject, address, priority);
14915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
14925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
14935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            TYPE.MMS, date, subject, address, priority,
14945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            (long)threadId, null);
14955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
14965a60e47497f21f64e6d79420dc4c56c1907df22akschulz
14975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else {
14985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /* Incoming message from the network */
14995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, getMmsFolderName(type),
15005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, TYPE.MMS);
1501326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
15025a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
15045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
15055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
15065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (type != msg.type) {
15075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "new type: " + type + " old type: " + msg.type);
15085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Event evt;
15095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
15105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(msg.localInitiatedSend == false) {
15115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Only send events about local initiated changes
15125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_SHIFT, id, getMmsFolderName(type),
15135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type), TYPE.MMS);
15145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.type = type;
15175a60e47497f21f64e6d79420dc4c56c1907df22akschulz
15185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (getMmsFolderName(type).equalsIgnoreCase(
15195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.FOLDER_NAME_SENT)
15205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && msg.localInitiatedSend == true) {
15215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Stop tracking changes for this message
15225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.localInitiatedSend = false;
15235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_SENDING_SUCCESS, id,
15245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(type), null, TYPE.MMS);
15255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
15275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } else if(threadId != msg.threadId) {
15285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                Log.d(TAG, "Message delete change: type: " + type + " old type: "
15295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.type
15305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + "\n    threadId: " + threadId + " old threadId: "
15315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.threadId);
15325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
15335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(threadId == DELETED_THREAD_ID) { // Message deleted
1534cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
15355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_DELETE, id,
1536cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            getMmsFolderName(msg.type), null, TYPE.MMS);
15375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
15395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else { // Undelete
15405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_SHIFT, id,
15415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type),
15425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.FOLDER_NAME_DELETED, TYPE.MMS);
15435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.threadId = threadId;
15455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1546fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                            }
15475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(read != msg.flagRead) {
15485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
15495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.flagRead = read;
15505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
15515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
15525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id,
15535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            getMmsFolderName(msg.type), TYPE.MMS);
15545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
15555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1556326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
15575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgListMms.put(id, msg);
1558fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
15595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
15605a60e47497f21f64e6d79420dc4c56c1907df22akschulz
156128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
156228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
15635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1564fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
15655a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListMms().values()) {
1566cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // "old_folder" used only for MessageShift event
1567326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELETE, msg.id,
1568cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        getMmsFolderName(msg.type), null, TYPE.MMS);
1569fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
15705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1571fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
15725a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListMms(msgListMms, listChanged);
1573fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1574fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
1575fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
15765a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void handleMsgListChangesMsg(Uri uri)  throws RemoteException{
15775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (V) Log.v(TAG, "handleMsgListChangesMsg uri: " + uri.toString());
1578326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1579326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // TODO: Change observer to handle accountId and message ID if present
1580326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
15815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        HashMap<Long, Msg> msgList = new HashMap<Long, Msg>();
15825a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c;
15835a60e47497f21f64e6d79420dc4c56c1907df22akschulz        boolean listChanged = false;
15845a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
15855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT, null, null, null);
15865a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (mMapEventReportVersion == BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
15875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT_EXT, null, null, null);
15885a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else {
15895a60e47497f21f64e6d79420dc4c56c1907df22akschulz            c = mProviderClient.query(mMessageUri, MSG_PROJECTION_SHORT_EXT2, null, null, null);
15905a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
15915a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMsg()) {
159228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
15935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null && c.moveToFirst()) {
15945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    do {
15955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        long id = c.getLong(c.getColumnIndex(
15965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns._ID));
15975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int folderId = c.getInt(c.getColumnIndex(
15985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FOLDER_ID));
15995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        int readFlag = c.getInt(c.getColumnIndex(
16005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContract.MessageColumns.FLAG_READ));
16015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMsg().remove(id);
16025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        BluetoothMapFolderElement folderElement = mFolders.getFolderById(folderId);
16035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        String newFolder;
16045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(folderElement != null) {
16055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            newFolder = folderElement.getFullPath();
16065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
16075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // This can happen if a new folder is created while connected
16085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            newFolder = "unknown";
16095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
16105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We must filter out any actions made by the MCE, hence do not send e.g.
16115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * a message deleted and/or MessageShift for messages deleted by the MCE. */
16125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (msg == null) {
16135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
16145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* New message - created with message unread */
16155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg = new Msg(id, folderId, 0, readFlag);
16165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgList.put(id, msg);
16175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Event evt;
16185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Incoming message from the network */
16195a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
16205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String date = BluetoothMapUtils.getDateTimeString(
16215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        c.getLong(c.getColumnIndex(
16225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.MessageColumns.DATE)));
16235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String subject = c.getString(c.getColumnIndex(
16245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.SUBJECT));
16255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String address = c.getString(c.getColumnIndex(
16265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.FROM_LIST));
16275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String priority = "no";
16285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(c.getInt(c.getColumnIndex(
16295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY))
16305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        == 1)
16315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    priority = "yes";
16325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion ==
16335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
16345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, newFolder,
16355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType(), date, subject, address, priority);
16365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
16375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    long thread_id = c.getLong(c.getColumnIndex(
16385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.MessageColumns.THREAD_ID));
16395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String thread_name = c.getString(c.getColumnIndex(
16405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            BluetoothMapContract.MessageColumns.THREAD_NAME));
16415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    evt = new Event(EVENT_TYPE_NEW, id, newFolder,
16425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType(), date, subject, address, priority,
16435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            thread_id, thread_name);
16445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
1645326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
16465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                evt = new Event(EVENT_TYPE_NEW, id, newFolder, null, TYPE.EMAIL);
1647326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
16485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            sendEvent(evt);
16495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
16505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Existing message */
16515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (folderId != msg.folderId && msg.folderId != -1) {
16525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (D) Log.d(TAG, "new folderId: " + folderId + " old folderId: "
16535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + msg.folderId);
16545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement oldFolderElement =
16555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderById(msg.folderId);
16565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String oldFolder;
16575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
16585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(oldFolderElement != null) {
16595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    oldFolder = oldFolderElement.getFullPath();
1660326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                } else {
16615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // This can happen if a new folder is created while connected
16625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    oldFolder = "unknown";
16635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
16645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement deletedFolder =
16655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderByName(
16665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.FOLDER_NAME_DELETED);
16675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapFolderElement sentFolder =
16685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mFolders.getFolderByName(
16695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapContract.FOLDER_NAME_SENT);
16705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /*
16715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  If the folder is now 'deleted', send a deleted-event in stead of
16725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  a shift or if message is sent initiated by MAP Client, then send
16735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 *  sending-success otherwise send folderShift
16745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 */
16755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if(deletedFolder != null && deletedFolder.getFolderId()
16765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        == folderId) {
1677cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    // "old_folder" used only for MessageShift event
1678cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
1679cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                                            null, mAccount.getType());
16805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    sendEvent(evt);
16815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else if(sentFolder != null
16825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && sentFolder.getFolderId() == folderId
16835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        && msg.localInitiatedSend == true) {
16845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if(msg.transparent) {
16855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        mResolver.delete(
16865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                ContentUris.withAppendedId(mMessageUri, id),
16875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                null, null);
16885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    } else {
16895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        msg.localInitiatedSend = false;
16905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msg.id,
16915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                oldFolder, null, mAccount.getType());
16925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
16935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
16945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
16955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (!oldFolder.equalsIgnoreCase("root")) {
16965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(EVENT_TYPE_SHIFT, id, newFolder,
16975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                oldFolder, mAccount.getType());
16985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
16995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
17005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
17015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                msg.folderId = folderId;
17025a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            }
17035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if(readFlag != msg.flagRead) {
17045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                listChanged = true;
17055a60e47497f21f64e6d79420dc4c56c1907df22akschulz
17065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (mMapEventReportVersion >
17075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapUtils.MAP_EVENT_REPORT_V10) {
17085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Event evt = new Event(EVENT_TYPE_READ_STATUS, id, newFolder,
17095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            mAccount.getType());
1710326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    sendEvent(evt);
17115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    msg.flagRead = readFlag;
1712326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                }
1713326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
17145a60e47497f21f64e6d79420dc4c56c1907df22akschulz
17155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgList.put(id, msg);
1716326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
17175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } while (c.moveToNext());
171828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
171928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
17205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
1721326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1722326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // For all messages no longer in the database send a delete notification
17235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (Msg msg : getMsgListMsg().values()) {
17245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                BluetoothMapFolderElement oldFolderElement = mFolders.getFolderById(msg.folderId);
1725326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String oldFolder;
17265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                listChanged = true;
1727326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(oldFolderElement != null) {
1728326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    oldFolder = oldFolderElement.getFullPath();
1729326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
1730326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    oldFolder = "unknown";
1731326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
17325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Some e-mail clients delete the message after sending, and creates a
17335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * new message in sent. We cannot track the message anymore, hence send both a
17345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * send success and delete message.
1735326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 */
1736326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msg.localInitiatedSend == true) {
1737326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    msg.localInitiatedSend = false;
1738326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // If message is send with transparency don't set folder as message is deleted
1739326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.transparent)
1740326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        oldFolder = null;
17415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msg.id, oldFolder, null,
17425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            mAccount.getType());
1743326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendEvent(evt);
1744326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1745326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* As this message deleted is only send on a real delete - don't set folder.
1746326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 *  - only send delete event if message is not sent with transparency
1747326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 */
1748326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (!msg.transparent) {
1749326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1750cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    // "old_folder" used only for MessageShift event
1751cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    Event evt = new Event(EVENT_TYPE_DELETE, msg.id, oldFolder,
1752cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            null, mAccount.getType());
1753326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendEvent(evt);
1754326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1755326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
17565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            setMsgListMsg(msgList, listChanged);
1757326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1758326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
1759326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1760326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void handleMsgListChanges(Uri uri) {
1761326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(uri.getAuthority().equals(mAuthority)) {
1762326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try {
17635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(D) Log.d(TAG, "handleMsgListChanges: account type = "
17645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + mAccount.getType().toString());
17655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                handleMsgListChangesMsg(uri);
17665a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } catch(RemoteException e) {
1767326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mMasInstance.restartObexServerSession();
17685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG, "Problems contacting the ContentProvider in mas Instance "
17695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + mMasId + " restaring ObexServerSession");
1770326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
1771326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
17725a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
17735a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // TODO: check to see if there could be problem with IM and SMS in one instance
17745a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mEnableSmsMms) {
1775326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            handleMsgListChangesSms();
1776326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            handleMsgListChangesMms();
1777326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
1778326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
1779326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
17805a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private void handleContactListChanges(Uri uri) {
17815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (uri.getAuthority().equals(mAuthority)) {
17825a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try {
17835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (V) Log.v(TAG,"handleContactListChanges uri: " + uri.toString());
17845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Cursor c = null;
17855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                boolean listChanged = false;
17865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                try {
17875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    ConvoContactInfo cInfo = new ConvoContactInfo();
17885a60e47497f21f64e6d79420dc4c56c1907df22akschulz
17895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V10
17905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            && mMapEventReportVersion != BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
17915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        c = mProviderClient
17925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                .query(mContactUri,
17935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BluetoothMapContract.
17945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        BT_CONTACT_CHATSTATE_PRESENCE_PROJECTION,
17955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        null, null, null);
17965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        cInfo.setConvoColunms(c);
17975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } else {
17985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (V) Log.v(TAG,"handleContactListChanges MAP version does not" +
17995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "support convocontact notifications");
18005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        return;
18015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
18025a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18035a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    HashMap<String, BluetoothMapConvoContactElement> contactList =
18045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            new HashMap<String,
18055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            BluetoothMapConvoContactElement>(getContactList().size());
18065a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized (getContactList()) {
18085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (c != null && c.moveToFirst()) {
18095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            do {
18105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                String uci = c.getString(cInfo.mContactColUci);
18115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                long convoId = c.getLong(cInfo.mContactColConvoId);
18125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (convoId == 0)
18135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    continue;
18145a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18155a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (V) BluetoothMapUtils.printCursor(c);
18165a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapConvoContactElement contact =
18185a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        getContactList().remove(uci);
18195a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                /*
18215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * We must filter out any actions made by the
18225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * MCE, hence do not send e.g. a message deleted
18235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * and/or MessageShift for messages deleted by
18245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 * the MCE.
18255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                 */
18265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (contact == null) {
18275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    listChanged = true;
18285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /*
18295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * New contact - added to conversation and
18305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * tracked here
18315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     */
18325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (mMapEventReportVersion
18335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            != BluetoothMapUtils.MAP_EVENT_REPORT_V10
18345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            && mMapEventReportVersion
18355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            != BluetoothMapUtils.MAP_EVENT_REPORT_V11) {
18365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt;
18375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String name = c
18385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColName);
18395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String displayName = c
18405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColNickname);
18415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String presenceStatus = c
18425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColPresenceText);
18435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int presenceState = c
18445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColPresenceState);
18455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastActivity = c
18465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getLong(cInfo.mContactColLastActive);
18475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int chatState = c
18485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColChatState);
18495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        int priority = c
18505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getInt(cInfo.mContactColPriority);
18515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String btUid = c
18525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getString(cInfo.mContactColBtUid);
18535a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // Get Conversation information for
18555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // event
18565a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        Uri convoUri = Uri
18575a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .parse(mAccount.mBase_uri
18585a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        + "/"
18595a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        + BluetoothMapContract.TABLE_CONVERSATION);
18605a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        String whereClause = "contacts._id = "
18615a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                + convoId;
18625a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        Cursor cConvo = mProviderClient
18635a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .query(convoUri,
18645a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                       BluetoothMapContract.BT_CONVERSATION_PROJECTION,
18655a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                       whereClause, null, null);
18665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // TODO: will move out of the loop when merged with CB's
18675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // changes make sure to look up col index out side loop
18685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        String convoName = null;
18695a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        if (cConvo != null
18705a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                && cConvo.moveToFirst()) {
18715a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            convoName = cConvo
18725a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    .getString(cConvo
18735a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                            .getColumnIndex(BluetoothMapContract.ConvoContactColumns.NAME));
18745a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        }
18755a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact = new BluetoothMapConvoContactElement(
18775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci, name, displayName,
18785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                presenceStatus, presenceState,
18795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                lastActivity, chatState,
18805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                priority, btUid);
18815a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contactList.put(uci, contact);
18835a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        evt = new Event(
18855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_CONVERSATION,
18865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
18875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
18885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                name,
18895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(priority),
18905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                BluetoothMapUtils
18915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getDateTimeString(lastActivity),
18925a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                convoId, convoName,
18935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                presenceState, presenceStatus,
18945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                chatState);
18955a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18965a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
18975a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
18985a60e47497f21f64e6d79420dc4c56c1907df22akschulz
18995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                } else {
19005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Not new - compare updated content
19015a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    Uri convoUri = Uri
19025a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            .parse(mAccount.mBase_uri
19035a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    + "/"
19045a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    + BluetoothMapContract.TABLE_CONVERSATION);
19055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // TODO: Should be changed to own provider interface name
19065a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    String whereClause = "contacts._id = "
19075a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            + convoId;
19085a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    Cursor cConvo = mProviderClient
19095a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                            .query(convoUri,
19105a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    BluetoothMapContract.BT_CONVERSATION_PROJECTION,
19115a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                    whereClause, null, null);
19125a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    // TODO: will move out of the loop when merged with CB's
19135a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    // changes make sure to look up col index out side loop
19145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String convoName = null;
19155a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    if (cConvo != null && cConvo.moveToFirst()) {
19165a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                        convoName = cConvo
19175a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                .getString(cConvo
19185a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                                        .getColumnIndex(BluetoothMapContract.ConvoContactColumns.NAME));
19195a60e47497f21f64e6d79420dc4c56c1907df22akschulz//                                    }
19205a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Check if presence is updated
19225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int presenceState = c.getInt(cInfo.mContactColPresenceState);
19235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String presenceStatus = c.getString(
19245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            cInfo.mContactColPresenceText);
19255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    String currentPresenceStatus = contact
19265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            .getPresenceStatus();
19275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (contact.getPresenceAvailability() != presenceState
19285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            || currentPresenceStatus != presenceStatus) {
19295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastOnline = c
19305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .getLong(cInfo.mContactColLastOnline);
19315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setPresenceAvailability(presenceState);
19325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setLastActivity(lastOnline);
19335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        if (currentPresenceStatus != null
19345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                && !currentPresenceStatus
19355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                .equals(presenceStatus)) {
19365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            contact.setPresenceStatus(presenceStatus);
19375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        }
19385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(
19395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_PRESENCE,
19405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
19415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
19425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                contact.getName(),
19435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(contact
19445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getPriority()),
19455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        BluetoothMapUtils
19465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getDateTimeString(lastOnline),
19475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        convoId, convoName,
19485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        presenceState, presenceStatus,
19495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        0);
19505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
19515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
19525a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    // Check if chat state is updated
19545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int chatState = c.getInt(cInfo.mContactColChatState);
19555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if (contact.getChatState() != chatState) {
19565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        // Get DB timestamp
19575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        long lastActivity = c.getLong(cInfo.mContactColLastActive);
19585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setLastActivity(lastActivity);
19595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        contact.setChatState(chatState);
19605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        Event evt = new Event(
19615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                EVENT_TYPE_CHAT_STATE,
19625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                uci,
19635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                mAccount.getType(),
19645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                contact.getName(),
19655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                String.valueOf(contact
19665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getPriority()),
19675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        BluetoothMapUtils
19685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        .getDateTimeString(lastActivity),
19695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        convoId, convoName, 0, null,
19705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                                        chatState);
19715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        sendEvent(evt);
19725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    }
19735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    contactList.put(uci, contact);
19745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                }
19755a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } while (c.moveToNext());
19765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
19775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(getContactList().size() > 0) {
19785a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // one or more contacts were deleted, hence the conversation listing
19795a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // version counter should change.
19805a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            listChanged = true;
19815a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
19825a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        setContactList(contactList, listChanged);
19835a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } // end synchronized
19845a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } finally {
19855a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (c != null) c.close();
19865a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
19875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } catch (RemoteException e) {
19885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mMasInstance.restartObexServerSession();
19895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Log.w(TAG,
19905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        "Problems contacting the ContentProvider in mas Instance "
19915a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                + mMasId + " restaring ObexServerSession");
19925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
19935a60e47497f21f64e6d79420dc4c56c1907df22akschulz
19945a60e47497f21f64e6d79420dc4c56c1907df22akschulz        }
19955a60e47497f21f64e6d79420dc4c56c1907df22akschulz        // TODO: conversation contact updates if IM and SMS(MMS in one instance
19965a60e47497f21f64e6d79420dc4c56c1907df22akschulz    }
19975a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1998326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean setEmailMessageStatusDelete(BluetoothMapFolderElement mCurrentFolder,
1999326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String uriStr, long handle, int status) {
2000326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean res = false;
2001326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Uri.parse(uriStr + BluetoothMapContract.TABLE_MESSAGE);
2002326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2003326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int updateCount = 0;
2004326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        ContentValues contentValues = new ContentValues();
2005326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapFolderElement deleteFolder = mFolders.
20065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getFolderByName(BluetoothMapContract.FOLDER_NAME_DELETED);
2007326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        contentValues.put(BluetoothMapContract.MessageColumns._ID, handle);
20085a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized(getMsgListMsg()) {
20095a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Msg msg = getMsgListMsg().get(handle);
2010326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (status == BluetoothMapAppParams.STATUS_VALUE_YES) {
2011326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Set deleted folder id */
2012326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                long folderId = -1;
2013326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(deleteFolder != null) {
20145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folderId = deleteFolder.getFolderId();
2015326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2016326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                contentValues.put(BluetoothMapContract.MessageColumns.FOLDER_ID,folderId);
2017326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                updateCount = mResolver.update(uri, contentValues, null, null);
2018326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* The race between updating the value in our cached values and the database
2019326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * is handled by the synchronized statement. */
2020326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(updateCount > 0) {
2021326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = true;
2022326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg != null) {
2023326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msg.oldFolderId = msg.folderId;
20245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* Update the folder ID to avoid triggering an event for MCE
20255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * initiated actions. */
2026326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msg.folderId = folderId;
2027326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2028326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(D) Log.d(TAG, "Deleted MSG: " + handle + " from folderId: " + folderId);
2029326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
2030326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, "Msg: " + handle + " - Set delete status " + status
2031326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            + " failed for folderId " + folderId);
2032326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2033326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (status == BluetoothMapAppParams.STATUS_VALUE_NO) {
2034326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Undelete message. move to old folder if we know it,
2035326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * else move to inbox - as dictated by the spec. */
2036326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msg != null && deleteFolder != null &&
20375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msg.folderId == deleteFolder.getFolderId()) {
2038326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Only modify messages in the 'Deleted' folder */
2039326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    long folderId = -1;
20405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    BluetoothMapFolderElement inboxFolder = mCurrentFolder.
20415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            getFolderByName(BluetoothMapContract.FOLDER_NAME_INBOX);
2042326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg != null && msg.oldFolderId != -1) {
2043326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        folderId = msg.oldFolderId;
2044326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
2045326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(inboxFolder != null) {
20465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            folderId = inboxFolder.getFolderId();
2047326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
20485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D)Log.d(TAG,"We did not delete the message, hence the old folder " +
20495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "is unknown. Moving to inbox.");
2050326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2051326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    contentValues.put(BluetoothMapContract.MessageColumns.FOLDER_ID, folderId);
2052326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    updateCount = mResolver.update(uri, contentValues, null, null);
2053326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(updateCount > 0) {
2054326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        res = true;
20555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* Update the folder ID to avoid triggering an event for MCE
20565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * initiated actions. */
20575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* UPDATE: Actually the BT-Spec. states that an undelete is a move of the
20585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * message to INBOX - clearified in errata 5591.
20595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * Therefore we update the cache to INBOX-folderId - to trigger a message
20605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * shift event to the old-folder. */
20615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(inboxFolder != null) {
20625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.folderId = inboxFolder.getFolderId();
20635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        } else {
20645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.folderId = folderId;
20655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        }
2066326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
20675a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D)Log.d(TAG,"We did not delete the message, hence the old folder " +
20685a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                "is unknown. Moving to inbox.");
2069326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2070326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2071326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2072326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(V) {
2073326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                BluetoothMapFolderElement folderElement;
2074326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String folderName = "unknown";
2075326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (msg != null) {
20765a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folderElement = mCurrentFolder.getFolderById(msg.folderId);
2077326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(folderElement != null) {
2078326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        folderName = folderElement.getName();
2079326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2080326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2081326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.d(TAG,"setEmailMessageStatusDelete: " + handle + " from " + folderName
2082326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        + " status: " + status);
2083326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2084326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2085326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(res == false) {
2086326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, "Set delete status " + status + " failed.");
2087326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2088326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return res;
2089326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
2090326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2091326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void updateThreadId(Uri uri, String valueString, long threadId) {
2092326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        ContentValues contentValues = new ContentValues();
2093326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        contentValues.put(valueString, threadId);
2094326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mResolver.update(uri, contentValues, null, null);
2095fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2096fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2097fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean deleteMessageMms(long handle) {
2098fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2099fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2100fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
210128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
210228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
210328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                /* Move to deleted folder, or delete if already in deleted folder */
210428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
210528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId != DELETED_THREAD_ID) {
210628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Set deleted thread id */
21075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
21085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().get(handle);
210928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
211028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = DELETED_THREAD_ID;
211128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2112326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
211328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Mms.THREAD_ID, DELETED_THREAD_ID);
211428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
211528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete from observer message list to avoid delete notifications */
21165a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
21175a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getMsgListMms().remove(handle);
211828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
211928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete message */
212028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    mResolver.delete(uri, null, null);
2121326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
212228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2123fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
212428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
21255a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
212728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
2128fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2129fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2130fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2131fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean unDeleteMessageMms(long handle) {
2132fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2133fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2134fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
213528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
213628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
213728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
213828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId == DELETED_THREAD_ID) {
213928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Restore thread id from address, or if no thread for address
21405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                     * create new thread by insert and remove of fake message */
214128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    String address;
214228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    long id = c.getLong(c.getColumnIndex(Mms._ID));
214328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int msgBox = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
214428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    if (msgBox == Mms.MESSAGE_BOX_INBOX) {
214528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        address = BluetoothMapContent.getAddressMms(mResolver, id,
21465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContent.MMS_FROM);
214728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    } else {
214828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        address = BluetoothMapContent.getAddressMms(mResolver, id,
21495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                BluetoothMapContent.MMS_TO);
215028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
215128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Set<String> recipients = new HashSet<String>();
215228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    recipients.addAll(Arrays.asList(address));
215328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Long oldThreadId = Telephony.Threads.getOrCreateThreadId(mContext, recipients);
21545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListMms()) {
21555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListMms().get(handle);
215628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
215728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = oldThreadId.intValue();
21585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Spec. states that undelete shall shift the message to Inbox.
21595a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // Hence we need to trigger a message shift from INBOX to old-folder
21605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // after undelete.
21615a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // We do this by changing the cached folder value to being inbox - hence
21625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // the event handler will se the update as the message have been shifted
21635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            // from INBOX to old-folder. (Errata 5591 clearifies this)
21645a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.type = Mms.MESSAGE_BOX_INBOX;
216528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2166326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
216728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Mms.THREAD_ID, oldThreadId);
216828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
216928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Log.d(TAG, "Message not in deleted folder: handle " + handle
21705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + " threadId " + threadId);
2171326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
217228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
217428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
21755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2176fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2177fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2178fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean deleteMessageSms(long handle) {
2181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
2183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
218428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
218528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
218628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                /* Move to deleted folder, or delete if already in deleted folder */
218728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
218828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId != DELETED_THREAD_ID) {
21895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
21905a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().get(handle);
219128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        if(msg != null) { // This will always be the case
219228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            msg.threadId = DELETED_THREAD_ID;
219328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2194326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
219528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Set deleted thread id */
219628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Sms.THREAD_ID, DELETED_THREAD_ID);
219728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
219828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete from observer message list to avoid delete notifications */
21995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
22005a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getMsgListSms().remove(handle);
220128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    }
220228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* Delete message */
220328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    mResolver.delete(uri, null, null);
2204326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
220528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2206fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
220728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
22085a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2209fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2210fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2211fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2212fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2213fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private boolean unDeleteMessageSms(long handle) {
2214fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
2216fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Cursor c = mResolver.query(uri, null, null, null, null);
221728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
221828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            if (c != null && c.moveToFirst()) {
221928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
222028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (threadId == DELETED_THREAD_ID) {
222128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    String address = c.getString(c.getColumnIndex(Sms.ADDRESS));
222228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Set<String> recipients = new HashSet<String>();
222328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    recipients.addAll(Arrays.asList(address));
222428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Long oldThreadId = Telephony.Threads.getOrCreateThreadId(mContext, recipients);
22255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    synchronized(getMsgListSms()) {
22265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        Msg msg = getMsgListSms().get(handle);
22275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(msg != null) {
22285a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.threadId = oldThreadId.intValue();
22295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* This will always be the case
22305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * The threadId is specified as an int, so it is safe to truncate
22315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * TODO: Test that this will trigger a message-shift from Inbox
22325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * to old-folder
22335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             **/
22345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Spec. states that undelete shall shift the message to Inbox.
22355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * Hence we need to trigger a message shift from INBOX to old-folder
22365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * after undelete.
22375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * We do this by changing the cached folder value to being inbox - hence
22385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * the event handler will se the update as the message have been shifted
22395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * from INBOX to old-folder. (Errata 5591 clearifies this)
22405a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * */
22415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msg.type = Sms.MESSAGE_TYPE_INBOX;
224228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                        }
2243326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
224428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    updateThreadId(uri, Sms.THREAD_ID, oldThreadId);
224528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                } else {
224628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    Log.d(TAG, "Message not in deleted folder: handle " + handle
22475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + " threadId " + threadId);
2248326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
224928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                res = true;
2250fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
225128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
22525a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
2253fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2254fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2255fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2256fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
22575a60e47497f21f64e6d79420dc4c56c1907df22akschulz    /**
22585a60e47497f21f64e6d79420dc4c56c1907df22akschulz     *
22595a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param handle
22605a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param type
22615a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param mCurrentFolder
22625a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param uriStr
22635a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param statusValue
22645a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @return true is success
22655a60e47497f21f64e6d79420dc4c56c1907df22akschulz     */
2266326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public boolean setMessageStatusDeleted(long handle, TYPE type,
2267326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            BluetoothMapFolderElement mCurrentFolder, String uriStr, int statusValue) {
2268fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean res = false;
2269fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "setMessageStatusDeleted: handle " + handle
22705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + " type " + type + " value " + statusValue);
2271fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2272326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (type == TYPE.EMAIL) {
2273326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            res = setEmailMessageStatusDelete(mCurrentFolder, uriStr, handle, statusValue);
22745a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (type == TYPE.IM) {
22755a60e47497f21f64e6d79420dc4c56c1907df22akschulz            // TODO: to do when deleting IM message
22765a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.d(TAG, "setMessageStatusDeleted: IM not handled" );
2277326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2278326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (statusValue == BluetoothMapAppParams.STATUS_VALUE_YES) {
2279326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
2280326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = deleteMessageSms(handle);
2281326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else if (type == TYPE.MMS) {
2282326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = deleteMessageMms(handle);
2283326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2284326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (statusValue == BluetoothMapAppParams.STATUS_VALUE_NO) {
2285326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
2286326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = unDeleteMessageSms(handle);
2287326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else if (type == TYPE.MMS) {
2288326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    res = unDeleteMessageMms(handle);
2289326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2290fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2291fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2292fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return res;
2293fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2294fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2295326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
2296326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *
2297326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param handle
2298326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param type
2299326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param uriStr
2300326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param statusValue
2301326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return true at success
2302326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
23035a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public boolean setMessageStatusRead(long handle, TYPE type, String uriStr, int statusValue)
23045a60e47497f21f64e6d79420dc4c56c1907df22akschulz            throws RemoteException{
2305326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int count = 0;
2306fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2307fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "setMessageStatusRead: handle " + handle
23085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                + " type " + type + " value " + statusValue);
2309fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
23105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        /* Approved MAP spec errata 3445 states that read status initiated
23115a60e47497f21f64e6d79420dc4c56c1907df22akschulz         * by the MCE shall change the MSE read status. */
2312fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
23135a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Uri uri = Sms.Inbox.CONTENT_URI;
2314fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            ContentValues contentValues = new ContentValues();
2315fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            contentValues.put(Sms.READ, statusValue);
2316326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(Sms.SEEN, statusValue);
2317326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String where = Sms._ID+"="+handle;
2318326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String values = contentValues.toString();
23195a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (D) Log.d(TAG, " -> SMS Uri: " + uri.toString() +
23205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    " Where " + where + " values " + values);
23215a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListSms()) {
23225a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListSms().get(handle);
23235a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
23245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
23255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
23265a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2327326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            count = mResolver.update(uri, contentValues, where, null);
2328326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> "+count +" rows updated!");
232928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
2330fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } else if (type == TYPE.MMS) {
2331fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
2332326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> MMS Uri: " + uri.toString());
2333fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            ContentValues contentValues = new ContentValues();
2334fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            contentValues.put(Mms.READ, statusValue);
23355a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMms()) {
23365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListMms().get(handle);
23375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
23385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
23395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
23405a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2341326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            count = mResolver.update(uri, contentValues, null, null);
2342326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, " -> "+count +" rows updated!");
23435a60e47497f21f64e6d79420dc4c56c1907df22akschulz        } else if (type == TYPE.EMAIL ||
23445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                type == TYPE.IM) {
2345326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uri = mMessageUri;
2346326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ContentValues contentValues = new ContentValues();
2347326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(BluetoothMapContract.MessageColumns.FLAG_READ, statusValue);
2348326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            contentValues.put(BluetoothMapContract.MessageColumns._ID, handle);
23495a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
23505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg msg = getMsgListMsg().get(handle);
23515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(msg != null) { // This will always be the case
23525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msg.flagRead = statusValue;
23535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
23545a60e47497f21f64e6d79420dc4c56c1907df22akschulz            }
2355326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            count = mProviderClient.update(uri, contentValues, null, null);
2356326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
235728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz
235828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        return (count > 0);
2359fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2360fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2361fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class PushMsgInfo {
2362fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long id;
2363fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int transparent;
2364fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int retry;
2365fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String phone;
2366fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri uri;
2367326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long timestamp;
2368fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int parts;
2369fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int partsSent;
2370fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int partsDelivered;
2371fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        boolean resend;
2372326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean sendInProgress;
2373326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean failedSent; // Set to true if a single part sent fail is received.
2374326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int statusDelivered; // Set to != 0 if a single part deliver fail is received.
2375fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2376fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public PushMsgInfo(long id, int transparent,
23775a60e47497f21f64e6d79420dc4c56c1907df22akschulz                int retry, String phone, Uri uri) {
2378fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.id = id;
2379fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.transparent = transparent;
2380fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.retry = retry;
2381fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.phone = phone;
2382fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.uri = uri;
2383fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            this.resend = false;
2384326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.sendInProgress = false;
2385326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.failedSent = false;
2386326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.statusDelivered = 0; /* Assume success */
2387326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            this.timestamp = 0;
2388fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        };
2389fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2390fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2391fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private Map<Long, PushMsgInfo> mPushMsgList =
23925a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Collections.synchronizedMap(new HashMap<Long, PushMsgInfo>());
2393fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2394326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public long pushMessage(BluetoothMapbMessage msg, BluetoothMapFolderElement folderElement,
2395326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            BluetoothMapAppParams ap, String emailBaseUri)
2396326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throws IllegalArgumentException, RemoteException, IOException {
2397fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (D) Log.d(TAG, "pushMessage");
2398fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<BluetoothMapbMessage.vCard> recipientList = msg.getRecipients();
2399fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int transparent = (ap.getTransparent() == BluetoothMapAppParams.INVALID_VALUE_PARAMETER) ?
2400fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                0 : ap.getTransparent();
2401fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int retry = ap.getRetry();
2402fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        int charset = ap.getCharset();
2403fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle = -1;
2404326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        long folderId = -1;
2405fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2406fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (recipientList == null) {
2407326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, "empty recipient list");
2408fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return -1;
2409fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2410fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2411326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if ( msg.getType().equals(TYPE.EMAIL) ) {
2412326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Write the message to the database */
2413326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            String msgBody = ((BluetoothMapbMessageEmail) msg).getEmailBody();
2414326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (V) {
2415326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                int length = msgBody.length();
2416326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.v(TAG, "pushMessage: message string length = " + length);
2417326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                String messages[] = msgBody.split("\r\n");
2418326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.v(TAG, "pushMessage: messages count=" + messages.length);
2419326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                for(int i = 0; i < messages.length; i++) {
2420326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.v(TAG, "part " + i + ":" + messages[i]);
2421326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2422326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2423326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            FileOutputStream os = null;
2424326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ParcelFileDescriptor fdOut = null;
2425326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Uri uriInsert = Uri.parse(emailBaseUri + BluetoothMapContract.TABLE_MESSAGE);
2426326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (D) Log.d(TAG, "pushMessage - uriInsert= " + uriInsert.toString() +
24275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    ", intoFolder id=" + folderElement.getFolderId());
2428326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
24295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            synchronized(getMsgListMsg()) {
2430326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // Now insert the empty message into folder
2431326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                ContentValues values = new ContentValues();
24325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                folderId = folderElement.getFolderId();
2433326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(BluetoothMapContract.MessageColumns.FOLDER_ID, folderId);
2434326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Uri uriNew = mProviderClient.insert(uriInsert, values);
2435326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (D) Log.d(TAG, "pushMessage - uriNew= " + uriNew.toString());
2436326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                handle =  Long.parseLong(uriNew.getLastPathSegment());
2437326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2438326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                try {
2439326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    fdOut = mProviderClient.openFile(uriNew, "w");
2440326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    os = new FileOutputStream(fdOut.getFileDescriptor());
2441326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // Write Email to DB
2442326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    os.write(msgBody.getBytes(), 0, msgBody.getBytes().length);
2443326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } catch (FileNotFoundException e) {
2444326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, e);
2445326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throw(new IOException("Unable to open file stream"));
2446326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } catch (NullPointerException e) {
2447326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.w(TAG, e);
2448326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    throw(new IllegalArgumentException("Unable to parse message."));
2449326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } finally {
2450326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    try {
2451326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(os != null)
2452326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            os.close();
2453326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } catch (IOException e) {Log.w(TAG, e);}
2454326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    try {
2455326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(fdOut != null)
24565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            fdOut.close();
2457326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } catch (IOException e) {Log.w(TAG, e);}
2458326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
2459326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2460326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Extract the data for the inserted message, and store in local mirror, to
2461326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 * avoid sending a NewMessage Event. */
24625a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /*TODO: We need to add the new 1.1 parameter as well:-) e.g. read*/
24635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Msg newMsg = new Msg(handle, folderId, 1); // TODO: Create define for read-state
2464326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                newMsg.transparent = (transparent == 1) ? true : false;
24655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if ( folderId == folderElement.getFolderByName(
24665a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        BluetoothMapContract.FOLDER_NAME_OUTBOX).getFolderId() ) {
2467326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    newMsg.localInitiatedSend = true;
2468326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
24695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                getMsgListMsg().put(handle, newMsg);
2470326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2471326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else { // type SMS_* of MMS
2472326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            for (BluetoothMapbMessage.vCard recipient : recipientList) {
24735a60e47497f21f64e6d79420dc4c56c1907df22akschulz                // Only send the message to the top level recipient
24745a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(recipient.getEnvLevel() == 0)
2475326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                {
2476326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Only send to first address */
2477326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String phone = recipient.getFirstPhoneNumber();
2478326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String email = recipient.getFirstEmail();
2479326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String folder = folderElement.getName();
2480326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    boolean read = false;
2481326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    boolean deliveryReport = true;
2482326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String msgBody = null;
2483326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2484326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* If MMS contains text only and the size is less than ten SMS's
2485326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                     * then convert the MMS to type SMS and then proceed
2486326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                     */
2487326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.getType().equals(TYPE.MMS) &&
24885a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            (((BluetoothMapbMessageMime) msg).getTextOnly() == true)) {
24895a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        msgBody = ((BluetoothMapbMessageMime) msg).getMessageAsText();
2490326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        SmsManager smsMng = SmsManager.getDefault();
2491326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        ArrayList<String> parts = smsMng.divideMessage(msgBody);
2492326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        int smsParts = parts.size();
2493326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (smsParts  <= CONVERT_MMS_TO_SMS_PART_COUNT ) {
24945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (D) Log.d(TAG, "pushMessage - converting MMS to SMS, sms parts="
24955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    + smsParts );
2496326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msg.setType(mSmsType);
2497326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
24985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (D) Log.d(TAG, "pushMessage - MMS text only but to big to " +
24995a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    "convert to SMS");
2500326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msgBody = null;
2501326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2502326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2503fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    }
2504326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2505326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (msg.getType().equals(TYPE.MMS)) {
2506326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        /* Send message if folder is outbox else just store in draft*/
2507ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        handle = sendMmsMessage(folder, phone, (BluetoothMapbMessageMime)msg,
2508ed70219e41ba68196798dcbf75b782d13fb88603kschulz                                transparent, retry);
2509326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else if (msg.getType().equals(TYPE.SMS_GSM) ||
2510326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msg.getType().equals(TYPE.SMS_CDMA) ) {
2511fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        /* Add the message to the database */
2512326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(msgBody == null)
2513326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            msgBody = ((BluetoothMapbMessageSms) msg).getSmsBody();
2514326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2515cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        if (TextUtils.isEmpty(msgBody)) {
2516cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            Log.d(TAG, "PushMsg: Empty msgBody ");
2517cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            /* not allowed to push empty message */
2518cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                            throw new IllegalArgumentException("push EMPTY message: Invalid Body");
2519cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        }
25205a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* We need to lock the SMS list while updating the database,
25215a60e47497f21f64e6d79420dc4c56c1907df22akschulz                         * to avoid sending events on MCE initiated operation. */
2522326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Uri contentUri = Uri.parse(Sms.CONTENT_URI+ "/" + folder);
2523326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Uri uri;
25245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        synchronized(getMsgListSms()) {
2525326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            uri = Sms.addMessageToUri(mResolver, contentUri, phone, msgBody,
25265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    "", System.currentTimeMillis(), read, deliveryReport);
2527326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2528326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(V) Log.v(TAG, "Sms.addMessageToUri() returned: " + uri);
2529326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if (uri == null) {
25305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (D) Log.d(TAG, "pushMessage - failure on add to uri "
25315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        + contentUri);
2532326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                return -1;
2533326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2534326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Cursor c = mResolver.query(uri, SMS_PROJECTION_SHORT, null, null, null);
25355a60e47497f21f64e6d79420dc4c56c1907df22akschulz
25365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* Extract the data for the inserted message, and store in local mirror,
25375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * to avoid sending a NewMessage Event. */
253828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            try {
253928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                if (c != null && c.moveToFirst()) {
254028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    long id = c.getLong(c.getColumnIndex(Sms._ID));
254128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    int type = c.getInt(c.getColumnIndex(Sms.TYPE));
254228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                    int threadId = c.getInt(c.getColumnIndex(Sms.THREAD_ID));
25435a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    int readFlag = c.getInt(c.getColumnIndex(Sms.READ));
25445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    if(V) Log.v(TAG, "add message with id=" + id +
25455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            " type=" + type + " threadId=" + threadId +
25465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                            " readFlag=" + readFlag + "to mMsgListSms");
25475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Msg newMsg = new Msg(id, type, threadId, readFlag);
25485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    getMsgListSms().put(id, newMsg);
25495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    c.close();
255028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                } else {
25515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    Log.w(TAG,"Message: " + uri + " no longer exist!");
25525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    /* This can only happen, if the message is deleted
25535a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                     * just as it is added */
25545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                    return -1;
255528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                                }
255628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                            } finally {
25575a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                if (c != null) c.close();
2558326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2559fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2560326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            handle = Long.parseLong(uri.getLastPathSegment());
2561fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2562326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            /* Send message if folder is outbox */
25635a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            if (folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)) {
2564326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                PushMsgInfo msgInfo = new PushMsgInfo(handle, transparent,
25655a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                        retry, phone, uri);
2566326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                mPushMsgList.put(handle, msgInfo);
2567326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                sendMessage(msgInfo, msgBody);
2568326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                if(V) Log.v(TAG, "sendMessage returned...");
25695a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            } /* else just added to draft */
25705a60e47497f21f64e6d79420dc4c56c1907df22akschulz
25715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            /* sendMessage causes the message to be deleted and reinserted,
25725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                             * hence we need to lock the list while this is happening. */
2573fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        }
2574326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    } else {
2575326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (D) Log.d(TAG, "pushMessage - failure on type " );
2576326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        return -1;
2577fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    }
2578fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
2579fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2580fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2581fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2582fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* If multiple recipients return handle of last */
2583fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return handle;
2584fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2585fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2586ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public long sendMmsMessage(String folder, String to_address, BluetoothMapbMessageMime msg,
2587ed70219e41ba68196798dcbf75b782d13fb88603kschulz            int transparent, int retry) {
2588fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /*
2589fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *strategy:
2590fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *1) parse message into parts
2591fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *if folder is outbox/drafts:
2592fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *2) push message to draft
2593fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *if folder is outbox:
2594fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *3) move message to outbox (to trigger the mms app to add msg to pending_messages list)
2595fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *4) send intent to mms app in order to wake it up.
2596fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *else if folder !outbox:
2597fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         *1) push message to folder
2598fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * */
2599326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (folder != null && (folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)
2600326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                ||  folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_DRAFT))) {
2601326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            long handle = pushMmsToFolder(Mms.MESSAGE_BOX_DRAFTS, to_address, msg);
26025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            /* if invalid handle (-1) then just return the handle
26035a60e47497f21f64e6d79420dc4c56c1907df22akschulz             * - else continue sending (if folder is outbox) */
26045a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (BluetoothMapAppParams.INVALID_VALUE_PARAMETER != handle &&
26055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    folder.equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_OUTBOX)) {
2606ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Uri btMmsUri = MmsFileProvider.CONTENT_URI.buildUpon()
2607ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        .appendPath(Long.toString(handle)).build();
2608ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Intent sentIntent = new Intent(ACTION_MESSAGE_SENT);
2609ed70219e41ba68196798dcbf75b782d13fb88603kschulz                // TODO: update the mmsMsgList <- done in pushMmsToFolder() but check
2610ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.setType("message/" + Long.toString(handle));
2611ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.MMS.ordinal());
2612ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_HANDLE, handle); // needed for notification
2613ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, transparent);
2614ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sentIntent.putExtra(EXTRA_MESSAGE_SENT_RETRY, retry);
2615ed70219e41ba68196798dcbf75b782d13fb88603kschulz                //sentIntent.setDataAndNormalize(btMmsUri);
2616ed70219e41ba68196798dcbf75b782d13fb88603kschulz                PendingIntent pendingSendIntent = PendingIntent.getBroadcast(mContext, 0,
2617ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        sentIntent, 0);
2618ed70219e41ba68196798dcbf75b782d13fb88603kschulz                SmsManager.getDefault().sendMultimediaMessage(mContext,
2619ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        btMmsUri, null/*locationUrl*/, null/*configOverrides*/,
2620ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        pendingSendIntent);
2621326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2622326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return handle;
2623326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2624326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* not allowed to push mms to anything but outbox/draft */
26255a60e47497f21f64e6d79420dc4c56c1907df22akschulz            throw  new IllegalArgumentException("Cannot push message to other " +
26265a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    "folders than outbox/draft");
2627fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2628fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2629fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2630fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void moveDraftToOutbox(long handle) {
2631ed70219e41ba68196798dcbf75b782d13fb88603kschulz        moveMmsToFolder(handle, mResolver, Mms.MESSAGE_BOX_OUTBOX);
2632ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
2633ed70219e41ba68196798dcbf75b782d13fb88603kschulz
2634ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /**
2635ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * Move a MMS to another folder.
2636ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param handle the CP handle of the message to move
2637ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param resolver the ContentResolver to use
2638ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param folder the destination folder - use Mms.MESSAGE_BOX_xxx
2639ed70219e41ba68196798dcbf75b782d13fb88603kschulz     */
2640ed70219e41ba68196798dcbf75b782d13fb88603kschulz    private static void moveMmsToFolder(long handle, ContentResolver resolver, int folder) {
2641fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /*Move message by changing the msg_box value in the content provider database */
26425a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (handle != -1) {
26435a60e47497f21f64e6d79420dc4c56c1907df22akschulz            String whereClause = " _id= " + handle;
26445a60e47497f21f64e6d79420dc4c56c1907df22akschulz            Uri uri = Mms.CONTENT_URI;
2645ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Cursor queryResult = resolver.query(uri, null, whereClause, null, null);
26465a60e47497f21f64e6d79420dc4c56c1907df22akschulz            try {
26475a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (queryResult != null) {
26485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (queryResult.getCount() > 0) {
26495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        queryResult.moveToFirst();
26505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        ContentValues data = new ContentValues();
26515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        /* set folder to be outbox */
2652ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        data.put(Mms.MESSAGE_BOX, folder);
2653ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        resolver.update(uri, data, whereClause, null);
2654ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        if (D) Log.d(TAG, "moved MMS message to " + getMmsFolderName(folder));
26555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
26565a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else {
2657ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Log.w(TAG, "Could not move MMS message to " + getMmsFolderName(folder));
26585a60e47497f21f64e6d79420dc4c56c1907df22akschulz                }
26595a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } finally {
26605a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (queryResult != null) queryResult.close();
2661fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2662fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2663fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
26645a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private long pushMmsToFolder(int folder, String to_address, BluetoothMapbMessageMime msg) {
2665fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /**
2666fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * strategy:
2667fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 1) parse msg into parts + header
2668fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 2) create thread id (abuse the ease of adding an SMS to get id for thread)
2669fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 3) push parts into content://mms/parts/ table
2670fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         * 3)
2671fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie         */
2672fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2673fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ContentValues values = new ContentValues();
2674326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_BOX, folder);
2675326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.READ, 0);
2676326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.SEEN, 0);
2677326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getSubject() != null) {
2678326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT, msg.getSubject());
2679326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2680326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT, "");
2681326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
268270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
2683326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getSubject() != null && msg.getSubject().length() > 0) {
2684326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.SUBJECT_CHARSET, 106);
2685326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2686326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.CONTENT_TYPE, "application/vnd.wap.multipart.related");
2687326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.EXPIRY, 604800);
2688326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_CLASS, PduHeaders.MESSAGE_CLASS_PERSONAL_STR);
2689326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ);
2690326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MMS_VERSION, PduHeaders.CURRENT_MMS_VERSION);
2691326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.PRIORITY, PduHeaders.PRIORITY_NORMAL);
2692326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.READ_REPORT, PduHeaders.VALUE_NO);
2693326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.TRANSACTION_ID, "T"+ Long.toHexString(System.currentTimeMillis()));
2694326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.DELIVERY_REPORT, PduHeaders.VALUE_NO);
2695326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.LOCKED, 0);
2696326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(msg.getTextOnly() == true)
2697326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.TEXT_ONLY, true);
2698326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.MESSAGE_SIZE, msg.getSize());
269970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
2700326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Get thread id
2701fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Set<String> recipients = new HashSet<String>();
2702fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        recipients.addAll(Arrays.asList(to_address));
2703326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.THREAD_ID, Telephony.Threads.getOrCreateThreadId(mContext, recipients));
2704326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Mms.CONTENT_URI;
2705fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
27065a60e47497f21f64e6d79420dc4c56c1907df22akschulz        synchronized (getMsgListMms()) {
27075a60e47497f21f64e6d79420dc4c56c1907df22akschulz
2708326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            uri = mResolver.insert(uri, values);
2709326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2710326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (uri == null) {
2711326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // unable to insert MMS
2712326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "Unabled to insert MMS " + values + "Uri: " + uri);
2713326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return -1;
2714326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2715326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* As we already have all the values we need, we could skip the query, but
2716326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde               doing the query ensures we get any changes made by the content provider
2717326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde               at insert. */
2718326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Cursor c = mResolver.query(uri, MMS_PROJECTION_SHORT, null, null, null);
271928446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            try {
272028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                if (c != null && c.moveToFirst()) {
272128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    long id = c.getLong(c.getColumnIndex(Mms._ID));
272228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
272328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    int threadId = c.getInt(c.getColumnIndex(Mms.THREAD_ID));
2724ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    int readStatus = c.getInt(c.getColumnIndex(Mms.READ));
2725326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
272628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    /* We must filter out any actions made by the MCE. Add the new message to
272728446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                     * the list of known messages. */
2728326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2729ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Msg newMsg = new Msg(id, type, threadId, readStatus);
273028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                    newMsg.localInitiatedSend = true;
27315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    getMsgListMms().put(id, newMsg);
27325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    c.close();
273328446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz                }
273428446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            } finally {
27355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (c != null) c.close();
2736326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2737326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Done adding changes, unlock access to mMsgListMms to allow sending MMS events again
2738fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2739fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        long handle = Long.parseLong(uri.getLastPathSegment());
2740326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (V) Log.v(TAG, " NEW URI " + uri.toString());
2741326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2742fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        try {
2743326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(msg.getMimeParts() == null) {
27445a60e47497f21f64e6d79420dc4c56c1907df22akschulz                /* Perhaps this message have been deleted, and no longer have any content,
27455a60e47497f21f64e6d79420dc4c56c1907df22akschulz                 * but only headers */
2746326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.w(TAG, "No MMS parts present...");
2747326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
27485a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if(V) Log.v(TAG, "Adding " + msg.getMimeParts().size()
27495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        + " parts to the data base.");
2750326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                for(MimePart part : msg.getMimeParts()) {
27515a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    int count = 0;
27525a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    count++;
2753326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    values.clear();
27545a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if(part.mContentType != null &&
27555a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            part.mContentType.toUpperCase().contains("TEXT")) {
2756326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CONTENT_TYPE, "text/plain");
2757326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CHARSET, 106);
2758326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mPartName != null) {
2759326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.FILENAME, part.mPartName);
2760326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.NAME, part.mPartName);
2761326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2762326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.FILENAME, "text_" + count +".txt");
2763326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.NAME, "text_" + count +".txt");
2764326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2765326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        // Ensure we have "ci" set
2766326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentId != null) {
2767326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2768326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2769326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(part.mPartName != null) {
2770326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_ID, "<" + part.mPartName + ">");
2771326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
2772326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_ID, "<text_" + count + ">");
2773326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2774326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2775326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        // Ensure we have "cl" set
2776326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentLocation != null) {
2777326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2778326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2779326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            if(part.mPartName != null) {
2780326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_LOCATION, part.mPartName + ".txt");
2781326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            } else {
2782326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                values.put(Mms.Part.CONTENT_LOCATION, "text_" + count + ".txt");
2783326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            }
2784326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2785326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2786326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentDisposition != null) {
2787326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2788326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2789326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.TEXT, part.getDataAsString());
2790326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = Uri.parse(Mms.CONTENT_URI + "/" + handle + "/part");
2791326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = mResolver.insert(uri, values);
2792326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(V) Log.v(TAG, "Added TEXT part");
2793326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
27945a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    } else if (part.mContentType != null &&
27955a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            part.mContentType.toUpperCase().contains("SMIL")){
2796326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.SEQ, -1);
2797326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.CONTENT_TYPE, "application/smil");
2798326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentId != null) {
2799326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2800326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2801326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_ID, "<smil_" + count + ">");
2802326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2803326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentLocation != null) {
2804326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2805326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        } else {
2806326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_LOCATION, "smil_" + count + ".xml");
2807326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        }
2808326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2809326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if(part.mContentDisposition != null)
2810326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2811326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.FILENAME, "smil.xml");
2812326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.NAME, "smil.xml");
2813326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        values.put(Mms.Part.TEXT, new String(part.mData, "UTF-8"));
2814326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2815326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = Uri.parse(Mms.CONTENT_URI+ "/" + handle + "/part");
2816326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        uri = mResolver.insert(uri, values);
2817326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (V) Log.v(TAG, "Added SMIL part");
2818326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2819326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }else /*VIDEO/AUDIO/IMAGE*/ {
2820326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        writeMmsDataPart(handle, part, count);
2821326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        if (V) Log.v(TAG, "Added OTHER part");
2822326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
2823326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (uri != null){
28245a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if (V) Log.v(TAG, "Added part with content-type: " + part.mContentType
28255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                                + " to Uri: " + uri.toString());
2826326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
282770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
2828fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2829fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (UnsupportedEncodingException e) {
283070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Log.w(TAG, e);
2831fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (IOException e) {
283270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Log.w(TAG, e);
2833fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2834fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2835fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        values.clear();
2836326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CONTACT_ID, "null");
2837326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.ADDRESS, "insert-address-token");
2838326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.TYPE, BluetoothMapContent.MMS_FROM);
2839326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CHARSET, 106);
2840fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2841326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = Uri.parse(Mms.CONTENT_URI + "/"  + handle + "/addr");
2842326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = mResolver.insert(uri, values);
2843fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (uri != null && V){
2844fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.v(TAG, " NEW URI " + uri.toString());
2845fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2846fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2847fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        values.clear();
2848326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CONTACT_ID, "null");
2849326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.ADDRESS, to_address);
2850326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.TYPE, BluetoothMapContent.MMS_TO);
2851326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Addr.CHARSET, 106);
2852fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2853326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = Uri.parse(Mms.CONTENT_URI + "/"  + handle + "/addr");
2854326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        uri = mResolver.insert(uri, values);
2855fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (uri != null && V){
2856fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.v(TAG, " NEW URI " + uri.toString());
2857fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2858fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return handle;
2859fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2860fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2861fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
286270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private void writeMmsDataPart(long handle, MimePart part, int count) throws IOException{
2863fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ContentValues values = new ContentValues();
2864326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        values.put(Mms.Part.MSG_ID, handle);
2865326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentType != null) {
2866326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_TYPE, part.mContentType);
2867326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2868326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, "MMS has no CONTENT_TYPE for part " + count);
2869326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2870326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentId != null) {
2871326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_ID, part.mContentId);
2872326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2873326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(part.mPartName != null) {
2874326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_ID, "<" + part.mPartName + ">");
2875326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
2876326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_ID, "<part_" + count + ">");
2877ed0c6ae1773ad1f4249fe3cf7447d7033195f222Ashwini Munigala            }
2878ed0c6ae1773ad1f4249fe3cf7447d7033195f222Ashwini Munigala        }
2879326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2880326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentLocation != null) {
2881326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_LOCATION, part.mContentLocation);
2882326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
2883326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(part.mPartName != null) {
2884326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_LOCATION, part.mPartName + ".dat");
2885326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
2886326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                values.put(Mms.Part.CONTENT_LOCATION, "part_" + count + ".dat");
2887326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2888326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
2889326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mContentDisposition != null)
2890326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.CONTENT_DISPOSITION, part.mContentDisposition);
2891326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(part.mPartName != null) {
2892326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.FILENAME, part.mPartName);
2893326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.NAME, part.mPartName);
2894326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
289570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            /* We must set at least one part identifier */
2896326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.FILENAME, "part_" + count + ".dat");
2897326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            values.put(Mms.Part.NAME, "part_" + count + ".dat");
289870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
2899326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri partUri = Uri.parse(Mms.CONTENT_URI + "/" + handle + "/part");
2900fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        Uri res = mResolver.insert(partUri, values);
2901fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2902fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        // Add data to part
2903fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        OutputStream os = mResolver.openOutputStream(res);
2904326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        os.write(part.mData);
2905fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        os.close();
2906fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2907fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2908fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2909fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void sendMessage(PushMsgInfo msgInfo, String msgBody) {
2910fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2911fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        SmsManager smsMng = SmsManager.getDefault();
2912fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<String> parts = smsMng.divideMessage(msgBody);
2913fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        msgInfo.parts = parts.size();
2914326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // We add a time stamp to differentiate delivery reports from each other for resent messages
2915326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.timestamp = Calendar.getInstance().getTime().getTime();
2916326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.partsDelivered = 0;
2917326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        msgInfo.partsSent = 0;
2918fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2919fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(msgInfo.parts);
2920fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(msgInfo.parts);
2921fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2922326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /*       We handle the SENT intent in the MAP service, as this object
2923326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       is destroyed at disconnect, hence if a disconnect occur while sending
2924326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       a message, there is no intent handler to move the message from outbox
2925326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       to the correct folder.
2926326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       The correct solution would be to create a service that will start based on
2927326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         *       the intent, if BT is turned off. */
2928326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2929cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta        if (parts != null && parts.size() > 0) {
2930cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            for (int i = 0; i < msgInfo.parts; i++) {
2931cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                Intent intentDelivery, intentSent;
2932cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2933cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery = new Intent(ACTION_MESSAGE_DELIVERY, null);
2934cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                /* Add msgId and part number to ensure the intents are different, and we
2935cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * thereby get an intent for each msg part.
2936cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * setType is needed to create different intents for each message id/ time stamp,
2937cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * as the extras are not used when comparing. */
2938cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.setType("message/" + Long.toString(msgInfo.id) +
2939cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        msgInfo.timestamp + i);
2940cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_HANDLE, msgInfo.id);
2941cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentDelivery.putExtra(EXTRA_MESSAGE_SENT_TIMESTAMP, msgInfo.timestamp);
2942cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                PendingIntent pendingIntentDelivery = PendingIntent.getBroadcast(mContext, 0,
2943cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        intentDelivery, PendingIntent.FLAG_UPDATE_CURRENT);
2944cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2945cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent = new Intent(ACTION_MESSAGE_SENT, null);
2946cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                /* Add msgId and part number to ensure the intents are different, and we
2947cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * thereby get an intent for each msg part.
2948cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * setType is needed to create different intents for each message id/ time stamp,
2949cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                 * as the extras are not used when comparing. */
2950cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.setType("message/" + Long.toString(msgInfo.id) + msgInfo.timestamp + i);
2951cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_HANDLE, msgInfo.id);
2952cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_URI, msgInfo.uri.toString());
2953cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_RETRY, msgInfo.retry);
2954cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                intentSent.putExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, msgInfo.transparent);
2955cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2956cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                PendingIntent pendingIntentSent = PendingIntent.getBroadcast(mContext, 0,
2957cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                        intentSent, PendingIntent.FLAG_UPDATE_CURRENT);
2958cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2959cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                // We use the same pending intent for all parts, but do not set the one shot flag.
2960cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                deliveryIntents.add(pendingIntentDelivery);
2961cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                sentIntents.add(pendingIntentSent);
2962cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            }
2963cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2964cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            Log.d(TAG, "sendMessage to " + msgInfo.phone);
2965cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta
2966cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta            smsMng.sendMultipartTextMessage(msgInfo.phone, null, parts, sentIntents,
2967cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta                    deliveryIntents);
2968cd72c4dfe4db77c6df24db94f8d9a04efff7ab1dHemant Gupta        }
2969fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
2970fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2971fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private class SmsBroadcastReceiver extends BroadcastReceiver {
2972fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        private final String[] ID_PROJECTION = new String[] { Sms._ID };
2973326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        private final Uri UPDATE_STATUS_URI = Uri.withAppendedPath(Sms.CONTENT_URI, "/status");
2974fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2975fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void register() {
2976400eaf8761223196a18b84247b066f0201226c3bHemant Gupta            Handler handler = new Handler(Looper.getMainLooper());
2977fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2978fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            IntentFilter intentFilter = new IntentFilter();
2979fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            intentFilter.addAction(ACTION_MESSAGE_DELIVERY);
2980326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try{
2981326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                intentFilter.addDataType("message/*");
2982326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (MalformedMimeTypeException e) {
2983326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "Wrong mime type!!!", e);
2984326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
2985326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
2986fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mContext.registerReceiver(this, intentFilter, null, handler);
2987fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2988fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2989fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void unregister() {
2990fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
2991fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                mContext.unregisterReceiver(this);
2992fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } catch (IllegalArgumentException e) {
2993fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                /* do nothing */
2994fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
2995fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
2996fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
2997fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
2998fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onReceive(Context context, Intent intent) {
2999fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            String action = intent.getAction();
3000326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3001fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            PushMsgInfo msgInfo = mPushMsgList.get(handle);
3002fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3003fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.d(TAG, "onReceive: action"  + action);
3004fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3005fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (msgInfo == null) {
3006fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                Log.d(TAG, "onReceive: no msgInfo found for handle " + handle);
3007fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                return;
3008fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3009fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
30101983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            if (action.equals(ACTION_MESSAGE_SENT)) {
30111983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                int result = intent.getIntExtra(EXTRA_MESSAGE_SENT_RESULT,
30121983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        Activity.RESULT_CANCELED);
30131983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                msgInfo.partsSent++;
30141983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if(result != Activity.RESULT_OK) {
30151983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    /* If just one of the parts in the message fails, we need to send the
30161983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                     * entire message again
30171983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                     */
30181983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    msgInfo.failedSent = true;
30191983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                }
30201983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if(D) Log.d(TAG, "onReceive: msgInfo.partsSent = " + msgInfo.partsSent
30211983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        + ", msgInfo.parts = " + msgInfo.parts + " result = " + result);
30221983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30231983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if (msgInfo.partsSent == msgInfo.parts) {
30241983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    actionMessageSent(context, intent, msgInfo);
30251983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                }
30261983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            } else if (action.equals(ACTION_MESSAGE_DELIVERY)) {
3027326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                long timestamp = intent.getLongExtra(EXTRA_MESSAGE_SENT_TIMESTAMP, 0);
3028326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                int status = -1;
3029326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(msgInfo.timestamp == timestamp) {
3030326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    msgInfo.partsDelivered++;
3031326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    byte[] pdu = intent.getByteArrayExtra("pdu");
3032326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    String format = intent.getStringExtra("format");
3033326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3034326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    SmsMessage message = SmsMessage.createFromPdu(pdu, format);
3035326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (message == null) {
3036326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Log.d(TAG, "actionMessageDelivery: Can't get message from pdu");
3037326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        return;
3038326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3039326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    status = message.getStatus();
3040326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(status != 0/*0 is success*/) {
3041326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        msgInfo.statusDelivered = status;
30425a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        if(D) Log.d(TAG, "msgInfo.statusDelivered = " + status);
30430ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                        Sms.moveMessageToFolder(mContext, msgInfo.uri, Sms.MESSAGE_TYPE_FAILED, 0);
30440ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                    } else {
30450ebd4e58920add6114b1f345b7d95e0709096fe3Ajay Panicker                        Sms.moveMessageToFolder(mContext, msgInfo.uri, Sms.MESSAGE_TYPE_SENT, 0);
3046326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3047326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3048fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (msgInfo.partsDelivered == msgInfo.parts) {
3049fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    actionMessageDelivery(context, intent, msgInfo);
3050fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
3051fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
3052fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                Log.d(TAG, "onReceive: Unknown action " + action);
3053fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3054fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3055fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
30561983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala        private void actionMessageSent(Context context, Intent intent, PushMsgInfo msgInfo) {
30571983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            /* As the MESSAGE_SENT intent is forwarded from the MAP service, we use the intent
30581983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala             * to carry the result, as getResult() will not return the correct value.
30591983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala             */
30601983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            boolean delete = false;
30611983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30621983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            if(D) Log.d(TAG,"actionMessageSent(): msgInfo.failedSent = " + msgInfo.failedSent);
30631983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30641983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            msgInfo.sendInProgress = false;
30651983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30661983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            if (msgInfo.failedSent == false) {
30671983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if(D) Log.d(TAG, "actionMessageSent: result OK");
30681983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if (msgInfo.transparent == 0) {
30691983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    if (!Sms.moveMessageToFolder(context, msgInfo.uri,
30701983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                            Sms.MESSAGE_TYPE_SENT, 0)) {
30711983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        Log.w(TAG, "Failed to move " + msgInfo.uri + " to SENT");
30721983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    }
30731983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                } else {
30741983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    delete = true;
30751983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                }
30761983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30771983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, msgInfo.id,
30781983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
30791983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                sendEvent(evt);
30801983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
30811983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            } else {
30821983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                if (msgInfo.retry == 1) {
30831983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    /* Notify failure, but keep message in outbox for resending */
30841983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    msgInfo.resend = true;
30851983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    msgInfo.partsSent = 0; // Reset counter for the retry
30861983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    msgInfo.failedSent = false;
30871983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, msgInfo.id,
30881983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                            getSmsFolderName(Sms.MESSAGE_TYPE_OUTBOX), null, mSmsType);
30891983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    sendEvent(evt);
30901983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                } else {
30911983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    if (msgInfo.transparent == 0) {
30921983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        if (!Sms.moveMessageToFolder(context, msgInfo.uri,
30931983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                                Sms.MESSAGE_TYPE_FAILED, 0)) {
30941983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                            Log.w(TAG, "Failed to move " + msgInfo.uri + " to FAILED");
30951983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        }
30961983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    } else {
30971983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                        delete = true;
30981983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    }
30991983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
31001983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, msgInfo.id,
31011983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                            getSmsFolderName(Sms.MESSAGE_TYPE_FAILED), null, mSmsType);
31021983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    sendEvent(evt);
31031983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                }
31041983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            }
31051983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
31061983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            if (delete == true) {
31071983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                /* Delete from Observer message list to avoid delete notifications */
31081983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                synchronized(getMsgListSms()) {
31091983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                    getMsgListSms().remove(msgInfo.id);
31101983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                }
31111983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
31121983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                /* Delete from DB */
31131983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala                mResolver.delete(msgInfo.uri, null, null);
31141983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            }
31151983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala        }
31161983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala
3117326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        private void actionMessageDelivery(Context context, Intent intent, PushMsgInfo msgInfo) {
3118fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Uri messageUri = intent.getData();
3119326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msgInfo.sendInProgress = false;
3120fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Cursor cursor = mResolver.query(msgInfo.uri, ID_PROJECTION, null, null, null);
3122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3123fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            try {
3124fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                if (cursor.moveToFirst()) {
3125fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    int messageId = cursor.getInt(0);
3126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    Uri updateUri = ContentUris.withAppendedId(UPDATE_STATUS_URI, messageId);
3128fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
31295a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if(D) Log.d(TAG, "actionMessageDelivery: uri=" + messageUri + ", status="
31305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            + msgInfo.statusDelivered);
3131fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3132fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    ContentValues contentValues = new ContentValues(2);
3133fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3134326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    contentValues.put(Sms.STATUS, msgInfo.statusDelivered);
3135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    contentValues.put(Inbox.DATE_SENT, System.currentTimeMillis());
3136fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    mResolver.update(updateUri, contentValues, null, null);
3137fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                } else {
3138fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    Log.d(TAG, "Can't find message for status update: " + messageUri);
3139fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
3140fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } finally {
31415a60e47497f21f64e6d79420dc4c56c1907df22akschulz                if (cursor != null) cursor.close();
3142fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3143fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3144326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (msgInfo.statusDelivered == 0) {
3145326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Event evt = new Event(EVENT_TYPE_DELEVERY_SUCCESS, msgInfo.id,
31465a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
3147fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
3148fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            } else {
31495a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Event evt = new Event(EVENT_TYPE_DELIVERY_FAILURE, msgInfo.id,
31505a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        getSmsFolderName(Sms.MESSAGE_TYPE_SENT), null, mSmsType);
3151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                sendEvent(evt);
3152fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mPushMsgList.remove(msgInfo.id);
3155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3157fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3158ed70219e41ba68196798dcbf75b782d13fb88603kschulz    /**
3159ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * Handle MMS sent intents in disconnected(MNS) state, where we do not need to send any
3160ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * notifications.
3161ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param context The context to use for provider operations
3162ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param intent The intent received
3163ed70219e41ba68196798dcbf75b782d13fb88603kschulz     * @param result The result
3164ed70219e41ba68196798dcbf75b782d13fb88603kschulz     */
3165ed70219e41ba68196798dcbf75b782d13fb88603kschulz    static public void actionMmsSent(Context context, Intent intent, int result,
3166ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Map<Long, Msg> mmsMsgList) {
3167ed70219e41ba68196798dcbf75b782d13fb88603kschulz        /*
3168ed70219e41ba68196798dcbf75b782d13fb88603kschulz         * if transparent:
3169ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   delete message and send notification(regardless of result)
3170ed70219e41ba68196798dcbf75b782d13fb88603kschulz         * else
3171ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   Result == Success:
3172ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *     move to sent folder (will trigger notification)
3173ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *   Result == Fail:
3174ed70219e41ba68196798dcbf75b782d13fb88603kschulz         *     move to outbox (send delivery fail notification)
3175ed70219e41ba68196798dcbf75b782d13fb88603kschulz         */
3176ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(D) Log.d(TAG,"actionMmsSent()");
3177ed70219e41ba68196798dcbf75b782d13fb88603kschulz        int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3178ed70219e41ba68196798dcbf75b782d13fb88603kschulz        long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3179ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(handle < 0) {
3180ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Log.w(TAG, "Intent received for an invalid handle");
3181ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return;
3182ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3183ed70219e41ba68196798dcbf75b782d13fb88603kschulz        ContentResolver resolver = context.getContentResolver();
3184ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(transparent == 1) {
3185ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* The specification is a bit unclear about the transparent flag. If it is set
3186ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * no copy of the message shall be kept in the send folder after the message
3187ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * was send, but in the case of a send error, it is unclear what to do.
3188ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * As it will not be transparent if we keep the message in any folder,
3189ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * we delete the message regardless of the result.
3190ed70219e41ba68196798dcbf75b782d13fb88603kschulz             * If we however do have a MNS connection we need to send a notification. */
3191ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, handle);
3192ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Delete from observer message list to avoid delete notifications */
3193ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mmsMsgList != null) {
3194ed70219e41ba68196798dcbf75b782d13fb88603kschulz                synchronized(mmsMsgList) {
3195ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    mmsMsgList.remove(handle);
3196ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3197ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3198ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Delete message */
3199ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(D) Log.d(TAG,"Transparent in use - delete");
3200ed70219e41ba68196798dcbf75b782d13fb88603kschulz            resolver.delete(uri, null, null);
3201ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else if (result == Activity.RESULT_OK) {
3202ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* This will trigger a notification */
3203ed70219e41ba68196798dcbf75b782d13fb88603kschulz            moveMmsToFolder(handle, resolver, Mms.MESSAGE_BOX_SENT);
3204ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3205ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mmsMsgList != null) {
3206ed70219e41ba68196798dcbf75b782d13fb88603kschulz                synchronized(mmsMsgList) {
3207ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Msg msg = mmsMsgList.get(handle);
3208ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    if(msg != null) {
3209ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    msg.type=Mms.MESSAGE_BOX_OUTBOX;
3210ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    }
3211ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3212ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3213ed70219e41ba68196798dcbf75b782d13fb88603kschulz            /* Hand further retries over to the MMS application */
3214ed70219e41ba68196798dcbf75b782d13fb88603kschulz            moveMmsToFolder(handle, resolver, Mms.MESSAGE_BOX_OUTBOX);
3215ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3216ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3217ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3218326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    static public void actionMessageSentDisconnected(Context context, Intent intent, int result) {
3219ed70219e41ba68196798dcbf75b782d13fb88603kschulz        TYPE type = TYPE.fromOrdinal(
3220ed70219e41ba68196798dcbf75b782d13fb88603kschulz        intent.getIntExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.NONE.ordinal()));
3221ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(type == TYPE.MMS) {
3222edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            actionMmsSent(context, intent, result, null);
3223ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3224edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            actionSmsSentDisconnected(context, intent, result);
3225ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3226ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3227ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3228ed70219e41ba68196798dcbf75b782d13fb88603kschulz    static public void actionSmsSentDisconnected(Context context, Intent intent, int result) {
3229edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        /* Check permission for message deletion. */
3230edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        if ((Binder.getCallingPid() != Process.myPid()) ||
3231edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            (context.checkCallingOrSelfPermission("android.Manifest.permission.WRITE_SMS")
3232edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou                    != PackageManager.PERMISSION_GRANTED)) {
3233edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            Log.w(TAG, "actionSmsSentDisconnected: Not allowed to delete SMS/MMS messages");
32341983bccf614d61dfcf20ba3cbf14f4ebf7f49943Ashwini Munigala            EventLog.writeEvent(0x534e4554, "b/22343270", Binder.getCallingUid(), "");
3235edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            return;
3236edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        }
3237edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou
3238326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean delete = false;
3239326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        //int retry = intent.getIntExtra(EXTRA_MESSAGE_SENT_RETRY, 0);
3240326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3241326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        String uriString = intent.getStringExtra(EXTRA_MESSAGE_SENT_URI);
3242326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(uriString == null) {
3243326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            // Nothing we can do about it, just bail out
3244326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return;
3245326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3246326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Uri uri = Uri.parse(uriString);
3247326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3248326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (result == Activity.RESULT_OK) {
3249326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.d(TAG, "actionMessageSentDisconnected: result OK");
3250326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if (transparent == 0) {
3251326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (!Sms.moveMessageToFolder(context, uri,
3252326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Sms.MESSAGE_TYPE_SENT, 0)) {
3253326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    Log.d(TAG, "Failed to move " + uri + " to SENT");
3254326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3255326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
3256326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                delete = true;
3257326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3258326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
3259326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /*if (retry == 1) {
3260326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                 The retry feature only works while connected, else we fail the send,
32615a60e47497f21f64e6d79420dc4c56c1907df22akschulz             * and move the message to failed, to let the user/app resend manually later.
3262326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else */{
3263326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (transparent == 0) {
3264326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (!Sms.moveMessageToFolder(context, uri,
3265326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            Sms.MESSAGE_TYPE_FAILED, 0)) {
3266326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Log.d(TAG, "Failed to move " + uri + " to FAILED");
3267326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
3268326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
3269326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    delete = true;
3270326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
3271326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3272326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3273326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3274edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou        if (delete) {
3275326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Delete from DB */
3276326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            ContentResolver resolver = context.getContentResolver();
3277edb6da171b8b7a6f9d4aa5a773d734a464f1ec66Miao Chou            if (resolver != null) {
3278326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                resolver.delete(uri, null, null);
3279326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else {
3280326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.w(TAG, "Unable to get resolver");
3281326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
3282326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3283326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
3284326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3285fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void registerPhoneServiceStateListener() {
32865a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
32875a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
3288fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        tm.listen(mPhoneListener, PhoneStateListener.LISTEN_SERVICE_STATE);
3289fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3290fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3291fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void unRegisterPhoneServiceStateListener() {
32925a60e47497f21f64e6d79420dc4c56c1907df22akschulz        TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
32935a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Context.TELEPHONY_SERVICE);
3294fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        tm.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
3295fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3296fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3297fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void resendPendingMessages() {
3298fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Send pending messages in outbox */
3299fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
33005a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
33015a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null);
330228446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
33035a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
33045a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
33055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long id = c.getLong(c.getColumnIndex(Sms._ID));
33065a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
33075a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    PushMsgInfo msgInfo = mPushMsgList.get(id);
33085a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (msgInfo == null || msgInfo.resend == false ||
33095a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            msgInfo.sendInProgress == true) {
33105a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
33115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
33125a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    msgInfo.sendInProgress = true;
33135a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    sendMessage(msgInfo, msgBody);
33145a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
331528446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            }
331628446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
33175a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
3318fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
33195a60e47497f21f64e6d79420dc4c56c1907df22akschulz
33205a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3321fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3322fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3323fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void failPendingMessages() {
3324fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Move pending messages from outbox to failed */
3325fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
33265a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
33275a60e47497f21f64e6d79420dc4c56c1907df22akschulz                null);
332828446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        try {
33295a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null && c.moveToFirst()) {
33305a60e47497f21f64e6d79420dc4c56c1907df22akschulz                do {
33315a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    long id = c.getLong(c.getColumnIndex(Sms._ID));
33325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
33335a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    PushMsgInfo msgInfo = mPushMsgList.get(id);
33345a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    if (msgInfo == null || msgInfo.resend == false) {
33355a60e47497f21f64e6d79420dc4c56c1907df22akschulz                        continue;
33365a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    }
33375a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    Sms.moveMessageToFolder(mContext, msgInfo.uri,
33385a60e47497f21f64e6d79420dc4c56c1907df22akschulz                            Sms.MESSAGE_TYPE_FAILED, 0);
33395a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } while (c.moveToNext());
334028446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz            }
334128446a56718e80574ba7b81901fc5a1368bf5839Kim Schulz        } finally {
33425a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (c != null) c.close();
3343fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
33445a60e47497f21f64e6d79420dc4c56c1907df22akschulz
3345fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3346fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3347fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void removeDeletedMessages() {
3348fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        /* Remove messages from virtual "deleted" folder (thread_id -1) */
3349326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mResolver.delete(Sms.CONTENT_URI,
3350fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                "thread_id = " + DELETED_THREAD_ID, null);
3351fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3352fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3353fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
3354fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
3355fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void onServiceStateChanged(ServiceState serviceState) {
3356fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            Log.d(TAG, "Phone service state change: " + serviceState.getState());
3357fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
3358fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                resendPendingMessages();
3359fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
3360fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
3361fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
3362fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3363fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void init() {
3364fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mSmsBroadcastReceiver.register();
3365fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        registerPhoneServiceStateListener();
3366326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mInitialized = true;
3367fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3368fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3369fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void deinit() {
3370326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mInitialized = false;
3371326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        unregisterObserver();
3372fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mSmsBroadcastReceiver.unregister();
3373fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        unRegisterPhoneServiceStateListener();
3374fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        failPendingMessages();
3375fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        removeDeletedMessages();
3376fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
3377326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
3378326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public boolean handleSmsSendIntent(Context context, Intent intent){
3379ed70219e41ba68196798dcbf75b782d13fb88603kschulz        TYPE type = TYPE.fromOrdinal(
3380ed70219e41ba68196798dcbf75b782d13fb88603kschulz            intent.getIntExtra(EXTRA_MESSAGE_SENT_MSG_TYPE, TYPE.NONE.ordinal()));
3381ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(type == TYPE.MMS) {
3382ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return handleMmsSendIntent(context, intent);
3383ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3384ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mInitialized) {
3385ed70219e41ba68196798dcbf75b782d13fb88603kschulz                mSmsBroadcastReceiver.onReceive(context, intent);
3386ed70219e41ba68196798dcbf75b782d13fb88603kschulz                return true;
3387ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3388326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
3389326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return false;
3390326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
3391ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3392ed70219e41ba68196798dcbf75b782d13fb88603kschulz    public boolean handleMmsSendIntent(Context context, Intent intent){
3393ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(D) Log.w(TAG, "handleMmsSendIntent()");
3394ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(mMnsClient.isConnected() == false) {
3395ed70219e41ba68196798dcbf75b782d13fb88603kschulz            // No need to handle notifications, just use default handling
3396ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(D) Log.w(TAG, "MNS not connected - use static handling");
3397ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return false;
3398ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3399ed70219e41ba68196798dcbf75b782d13fb88603kschulz        long handle = intent.getLongExtra(EXTRA_MESSAGE_SENT_HANDLE, -1);
3400ed70219e41ba68196798dcbf75b782d13fb88603kschulz        int result = intent.getIntExtra(EXTRA_MESSAGE_SENT_RESULT, Activity.RESULT_CANCELED);
3401ed70219e41ba68196798dcbf75b782d13fb88603kschulz        actionMmsSent(context, intent, result, getMsgListMms());
3402ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(handle < 0) {
3403ed70219e41ba68196798dcbf75b782d13fb88603kschulz            Log.w(TAG, "Intent received for an invalid handle");
3404ed70219e41ba68196798dcbf75b782d13fb88603kschulz            return true;
3405ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3406ed70219e41ba68196798dcbf75b782d13fb88603kschulz        if(result != Activity.RESULT_OK) {
3407ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(mObserverRegistered) {
3408ed70219e41ba68196798dcbf75b782d13fb88603kschulz                Event evt = new Event(EVENT_TYPE_SENDING_FAILURE, handle,
3409ed70219e41ba68196798dcbf75b782d13fb88603kschulz                        getMmsFolderName(Mms.MESSAGE_BOX_OUTBOX), null, TYPE.MMS);
3410ed70219e41ba68196798dcbf75b782d13fb88603kschulz                sendEvent(evt);
3411ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3412ed70219e41ba68196798dcbf75b782d13fb88603kschulz        } else {
3413ed70219e41ba68196798dcbf75b782d13fb88603kschulz            int transparent = intent.getIntExtra(EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
3414ed70219e41ba68196798dcbf75b782d13fb88603kschulz            if(transparent != 0) {
3415ed70219e41ba68196798dcbf75b782d13fb88603kschulz                if(mObserverRegistered) {
3416ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    Event evt = new Event(EVENT_TYPE_SENDING_SUCCESS, handle,
3417ed70219e41ba68196798dcbf75b782d13fb88603kschulz                            getMmsFolderName(Mms.MESSAGE_BOX_OUTBOX), null, TYPE.MMS);
3418ed70219e41ba68196798dcbf75b782d13fb88603kschulz                    sendEvent(evt);
3419ed70219e41ba68196798dcbf75b782d13fb88603kschulz                }
3420ed70219e41ba68196798dcbf75b782d13fb88603kschulz            }
3421ed70219e41ba68196798dcbf75b782d13fb88603kschulz        }
3422ed70219e41ba68196798dcbf75b782d13fb88603kschulz        return true;
3423ed70219e41ba68196798dcbf75b782d13fb88603kschulz    }
3424ed70219e41ba68196798dcbf75b782d13fb88603kschulz
3425fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie}
3426