1 /*
2  * Copyright 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.map;
18 
19 import static org.junit.Assert.assertThrows;
20 import static org.mockito.Mockito.*;
21 
22 import android.app.Activity;
23 import android.content.ContentProviderClient;
24 import android.content.ContentValues;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.database.Cursor;
28 import android.database.MatrixCursor;
29 import android.database.sqlite.SQLiteException;
30 import android.net.Uri;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.os.RemoteException;
34 import android.os.UserManager;
35 import android.platform.test.flag.junit.SetFlagsRule;
36 import android.provider.ContactsContract;
37 import android.provider.Telephony;
38 import android.provider.Telephony.Mms;
39 import android.provider.Telephony.Sms;
40 import android.telephony.TelephonyManager;
41 import android.test.mock.MockContentProvider;
42 import android.test.mock.MockContentResolver;
43 
44 import androidx.test.filters.MediumTest;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import com.android.bluetooth.BluetoothMethodProxy;
48 import com.android.bluetooth.flags.Flags;
49 import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
50 import com.android.bluetooth.mapapi.BluetoothMapContract;
51 import com.android.bluetooth.mapapi.BluetoothMapContract.MessageColumns;
52 import com.android.obex.ResponseCodes;
53 
54 import com.google.android.mms.pdu.PduHeaders;
55 
56 import org.junit.After;
57 import org.junit.Assert;
58 import org.junit.Before;
59 import org.junit.Rule;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 import org.mockito.Mock;
63 import org.mockito.Mockito;
64 import org.mockito.Spy;
65 import org.mockito.junit.MockitoJUnit;
66 import org.mockito.junit.MockitoRule;
67 
68 import java.text.SimpleDateFormat;
69 import java.time.Instant;
70 import java.util.Calendar;
71 import java.util.HashMap;
72 import java.util.HashSet;
73 import java.util.Map;
74 import java.util.concurrent.TimeUnit;
75 
76 @MediumTest
77 @RunWith(AndroidJUnit4.class)
78 public class BluetoothMapContentObserverTest {
79     static final String TEST_NUMBER_ONE = "5551212";
80     static final String TEST_NUMBER_TWO = "5551234";
81     static final int TEST_ID = 1;
82     static final long TEST_HANDLE_ONE = 1;
83     static final long TEST_HANDLE_TWO = 2;
84     static final String TEST_URI_STR = "http://www.google.com";
85     static final int TEST_STATUS_VALUE = 1;
86     static final int TEST_THREAD_ID = 1;
87     static final long TEST_OLD_THREAD_ID = 2;
88     static final int TEST_PLACEHOLDER_INT = 1;
89     static final String TEST_ADDRESS = "test_address";
90     static final long TEST_DELETE_FOLDER_ID = BluetoothMapContract.FOLDER_ID_DELETED;
91     static final long TEST_INBOX_FOLDER_ID = BluetoothMapContract.FOLDER_ID_INBOX;
92     static final long TEST_SENT_FOLDER_ID = BluetoothMapContract.FOLDER_ID_SENT;
93     static final long TEST_DRAFT_FOLDER_ID = BluetoothMapContract.FOLDER_ID_DRAFT;
94     static final long TEST_OLD_FOLDER_ID = 6;
95     static final int TEST_READ_FLAG_ONE = 1;
96     static final int TEST_READ_FLAG_ZERO = 0;
97     static final long TEST_DATE_MS = Calendar.getInstance().getTimeInMillis();
98     static final long TEST_DATE_SEC = TimeUnit.MILLISECONDS.toSeconds(TEST_DATE_MS);
99     static final String TEST_SUBJECT = "subject";
100     static final int TEST_MMS_MTYPE = 1;
101     static final int TEST_MMS_TYPE_ALL = Telephony.BaseMmsColumns.MESSAGE_BOX_ALL;
102     static final int TEST_MMS_TYPE_INBOX = Telephony.BaseMmsColumns.MESSAGE_BOX_INBOX;
103     static final int TEST_SMS_TYPE_ALL = Telephony.TextBasedSmsColumns.MESSAGE_TYPE_ALL;
104     static final int TEST_SMS_TYPE_INBOX = Telephony.BaseMmsColumns.MESSAGE_BOX_INBOX;
105     static final Uri TEST_URI = Mms.CONTENT_URI;
106     static final String TEST_AUTHORITY = "test_authority";
107 
108     static final long TEST_CONVO_ID = 1;
109     static final String TEST_NAME = "col_name";
110     static final String TEST_DISPLAY_NAME = "col_nickname";
111     static final String TEST_BT_UID = "1111";
112     static final int TEST_CHAT_STATE = 1;
113     static final int TEST_CHAT_STATE_DIFFERENT = 2;
114     static final String TEST_UCI = "col_uci";
115     static final String TEST_UCI_DIFFERENT = "col_uci_different";
116     static final long TEST_LAST_ACTIVITY = 1;
117     static final int TEST_PRESENCE_STATE = 1;
118     static final int TEST_PRESENCE_STATE_DIFFERENT = 2;
119     static final String TEST_STATUS_TEXT = "col_status_text";
120     static final String TEST_STATUS_TEXT_DIFFERENT = "col_status_text_different";
121     static final int TEST_PRIORITY = 1;
122     static final int TEST_LAST_ONLINE = 1;
123 
124     @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
125     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
126 
127     @Mock private BluetoothMnsObexClient mClient;
128     @Mock private BluetoothMapMasInstance mInstance;
129     @Mock private TelephonyManager mTelephonyManager;
130     @Mock private UserManager mUserService;
131     @Mock private Context mContext;
132     @Mock private ContentProviderClient mProviderClient;
133     @Mock private BluetoothMapAccountItem mItem;
134     @Mock private Intent mIntent;
135     @Spy private BluetoothMethodProxy mMapMethodProxy = BluetoothMethodProxy.getInstance();
136 
137     private ExceptionTestProvider mProvider;
138     private MockContentResolver mMockContentResolver;
139     private BluetoothMapContentObserver mObserver;
140     private BluetoothMapFolderElement mFolders;
141     private BluetoothMapFolderElement mCurrentFolder;
142 
143     static class ExceptionTestProvider extends MockContentProvider {
144         HashSet<String> mContents = new HashSet<String>();
145 
ExceptionTestProvider(Context context)146         public ExceptionTestProvider(Context context) {
147             super(context);
148         }
149 
150         @Override
query(Uri uri, String[] b, String s, String[] c, String d)151         public Cursor query(Uri uri, String[] b, String s, String[] c, String d) {
152             // Throw exception for SMS queries for easy initialization
153             if (Sms.CONTENT_URI.equals(uri)) throw new SQLiteException();
154 
155             // Return a cursor otherwise for Thread IDs
156             Cursor cursor = Mockito.mock(Cursor.class);
157             when(cursor.moveToFirst()).thenReturn(true);
158             when(cursor.getLong(anyInt())).thenReturn(0L);
159             return cursor;
160         }
161 
162         @Override
insert(Uri uri, ContentValues values)163         public Uri insert(Uri uri, ContentValues values) {
164             // Store addresses for later verification
165             Object address = values.get(Mms.Addr.ADDRESS);
166             if (address != null) mContents.add((String) address);
167             return Uri.withAppendedPath(Mms.Outbox.CONTENT_URI, "0");
168         }
169     }
170 
171     @Before
setUp()172     public void setUp() throws Exception {
173         BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy);
174         if (Looper.myLooper() == null) {
175             Looper.prepare();
176         }
177         mMockContentResolver = new MockContentResolver();
178         mProvider = new ExceptionTestProvider(mContext);
179         mMockContentResolver.addProvider("sms", mProvider);
180         mFolders = new BluetoothMapFolderElement("placeholder", null);
181         mCurrentFolder = new BluetoothMapFolderElement("current", null);
182 
183         // Functions that get called when BluetoothMapContentObserver is created
184         when(mUserService.isUserUnlocked()).thenReturn(true);
185         when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
186         when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
187         when(mContext.getSystemServiceName(TelephonyManager.class))
188                 .thenReturn(Context.TELEPHONY_SERVICE);
189         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserService);
190         when(mContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
191         when(mInstance.getMasId()).thenReturn(TEST_ID);
192 
193         mObserver = new BluetoothMapContentObserver(mContext, mClient, mInstance, null, true);
194         mObserver.mProviderClient = mProviderClient;
195         mObserver.mAccount = mItem;
196         when(mItem.getType()).thenReturn(TYPE.IM);
197     }
198 
199     @After
tearDown()200     public void tearDown() throws Exception {
201         BluetoothMethodProxy.setInstanceForTesting(null);
202     }
203 
204     @Test
testPushGroupMMS()205     public void testPushGroupMMS() throws RemoteException {
206         if (Looper.myLooper() == null) {
207             Looper.prepare();
208         }
209         mMockContentResolver.addProvider("mms", mProvider);
210         mMockContentResolver.addProvider("mms-sms", mProvider);
211 
212         BluetoothMapbMessageMime message = new BluetoothMapbMessageMime();
213         message.setType(BluetoothMapUtils.TYPE.MMS);
214         message.setFolder("telecom/msg/outbox");
215         message.addSender("Zero", "0");
216         message.addRecipient("One", new String[] {TEST_NUMBER_ONE}, null);
217         message.addRecipient("Two", new String[] {TEST_NUMBER_TWO}, null);
218         BluetoothMapbMessageMime.MimePart body = message.addMimePart();
219 
220         body.mContentType = "text/plain";
221         body.mData = "HelloWorld".getBytes(java.nio.charset.StandardCharsets.UTF_8);
222 
223         BluetoothMapAppParams appParams = new BluetoothMapAppParams();
224         BluetoothMapFolderElement folderElement = new BluetoothMapFolderElement("outbox", null);
225 
226         BluetoothMapContentObserver observer =
227                 new BluetoothMapContentObserver(mContext, null, mInstance, null, true);
228 
229         // The test end in a NPE as part of the sendMultimediaMessage pendingSendIntent
230         assertThrows(
231                 NullPointerException.class,
232                 () -> observer.pushMessage(message, folderElement, appParams, null));
233 
234         // Validate that 3 addresses were inserted into the database with 2 being the recipients
235         Assert.assertEquals(3, mProvider.mContents.size());
236         Assert.assertTrue(mProvider.mContents.contains(TEST_NUMBER_ONE));
237         Assert.assertTrue(mProvider.mContents.contains(TEST_NUMBER_TWO));
238     }
239 
240     @Test
testSendEvent_withZeroEventFilter()241     public void testSendEvent_withZeroEventFilter() {
242         when(mClient.isConnected()).thenReturn(true);
243         mObserver.setNotificationFilter(0);
244 
245         String eventType = BluetoothMapContentObserver.EVENT_TYPE_NEW;
246         BluetoothMapContentObserver.Event event =
247                 mObserver.new Event(eventType, TEST_HANDLE_ONE, null, null);
248         mObserver.sendEvent(event);
249         verify(mClient, never()).sendEvent(any(), anyInt());
250 
251         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_DELETE;
252         mObserver.sendEvent(event);
253         verify(mClient, never()).sendEvent(any(), anyInt());
254 
255         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_REMOVED;
256         mObserver.sendEvent(event);
257         verify(mClient, never()).sendEvent(any(), anyInt());
258 
259         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SHIFT;
260         mObserver.sendEvent(event);
261         verify(mClient, never()).sendEvent(any(), anyInt());
262 
263         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_DELEVERY_SUCCESS;
264         mObserver.sendEvent(event);
265         verify(mClient, never()).sendEvent(any(), anyInt());
266 
267         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SENDING_SUCCESS;
268         mObserver.sendEvent(event);
269         verify(mClient, never()).sendEvent(any(), anyInt());
270 
271         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SENDING_FAILURE;
272         mObserver.sendEvent(event);
273         verify(mClient, never()).sendEvent(any(), anyInt());
274 
275         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_READ_STATUS;
276         mObserver.sendEvent(event);
277         verify(mClient, never()).sendEvent(any(), anyInt());
278 
279         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_CONVERSATION;
280         mObserver.sendEvent(event);
281         verify(mClient, never()).sendEvent(any(), anyInt());
282 
283         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_PRESENCE;
284         mObserver.sendEvent(event);
285         verify(mClient, never()).sendEvent(any(), anyInt());
286 
287         event.eventType = BluetoothMapContentObserver.EVENT_TYPE_CHAT_STATE;
288         mObserver.sendEvent(event);
289         verify(mClient, never()).sendEvent(any(), anyInt());
290     }
291 
292     @Test
testEvent_withNonZeroEventFilter()293     public void testEvent_withNonZeroEventFilter() throws Exception {
294         when(mClient.isConnected()).thenReturn(true);
295 
296         String eventType = BluetoothMapContentObserver.EVENT_TYPE_NEW;
297         BluetoothMapContentObserver.Event event =
298                 mObserver.new Event(eventType, TEST_HANDLE_ONE, null, null);
299 
300         mObserver.sendEvent(event);
301 
302         verify(mClient).sendEvent(event.encode(), TEST_ID);
303     }
304 
305     @Test
testSetContactList()306     public void testSetContactList() {
307         Map<String, BluetoothMapConvoContactElement> map = Map.of();
308 
309         mObserver.setContactList(map, true);
310 
311         Assert.assertEquals(mObserver.getContactList(), map);
312     }
313 
314     @Test
testSetMsgListSms()315     public void testSetMsgListSms() {
316         Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
317 
318         mObserver.setMsgListSms(map, true);
319 
320         Assert.assertEquals(mObserver.getMsgListSms(), map);
321     }
322 
323     @Test
testSetMsgListMsg()324     public void testSetMsgListMsg() {
325         Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
326 
327         mObserver.setMsgListMsg(map, true);
328 
329         Assert.assertEquals(mObserver.getMsgListMsg(), map);
330     }
331 
332     @Test
testSetMsgListMms()333     public void testSetMsgListMms() {
334         Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
335 
336         mObserver.setMsgListMms(map, true);
337 
338         Assert.assertEquals(mObserver.getMsgListMms(), map);
339     }
340 
341     @Test
testSetNotificationRegistration_withNullHandler()342     public void testSetNotificationRegistration_withNullHandler() throws Exception {
343         when(mClient.getMessageHandler()).thenReturn(null);
344 
345         Assert.assertEquals(
346                 mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
347                 ResponseCodes.OBEX_HTTP_UNAVAILABLE);
348     }
349 
350     @Test
testSetNotificationRegistration_withInvalidMnsRecord()351     public void testSetNotificationRegistration_withInvalidMnsRecord() throws Exception {
352         if (Looper.myLooper() == null) {
353             Looper.prepare();
354         }
355         Handler handler = new Handler();
356         when(mClient.getMessageHandler()).thenReturn(handler);
357         when(mClient.isValidMnsRecord()).thenReturn(false);
358 
359         Assert.assertEquals(
360                 mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
361                 ResponseCodes.OBEX_HTTP_OK);
362     }
363 
364     @Test
testSetNotificationRegistration_withValidMnsRecord()365     public void testSetNotificationRegistration_withValidMnsRecord() throws Exception {
366         if (Looper.myLooper() == null) {
367             Looper.prepare();
368         }
369         Handler handler = new Handler();
370         when(mClient.getMessageHandler()).thenReturn(handler);
371         when(mClient.isValidMnsRecord()).thenReturn(true);
372 
373         Assert.assertEquals(
374                 mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
375                 ResponseCodes.OBEX_HTTP_OK);
376     }
377 
378     @Test
testSetMessageStatusRead_withTypeSmsGsm()379     public void testSetMessageStatusRead_withTypeSmsGsm() throws Exception {
380         TYPE type = TYPE.SMS_GSM;
381         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
382         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
383         map.put(TEST_HANDLE_ONE, msg);
384         mObserver.setMsgListSms(map, true);
385         doReturn(TEST_PLACEHOLDER_INT)
386                 .when(mMapMethodProxy)
387                 .contentResolverUpdate(any(), any(), any(), any(), any());
388 
389         Assert.assertTrue(
390                 mObserver.setMessageStatusRead(
391                         TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE));
392 
393         Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE);
394     }
395 
396     @Test
testSetMessageStatusRead_withTypeMms()397     public void testSetMessageStatusRead_withTypeMms() throws Exception {
398         TYPE type = TYPE.MMS;
399         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
400         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
401         map.put(TEST_HANDLE_ONE, msg);
402         mObserver.setMsgListMms(map, true);
403         doReturn(TEST_PLACEHOLDER_INT)
404                 .when(mMapMethodProxy)
405                 .contentResolverUpdate(any(), any(), any(), any(), any());
406 
407         Assert.assertTrue(
408                 mObserver.setMessageStatusRead(
409                         TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE));
410 
411         Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE);
412     }
413 
414     @Test
testSetMessageStatusRead_withTypeEmail()415     public void testSetMessageStatusRead_withTypeEmail() throws Exception {
416         TYPE type = TYPE.EMAIL;
417         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
418         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
419         map.put(TEST_HANDLE_ONE, msg);
420         mObserver.setMsgListMsg(map, true);
421         mObserver.mProviderClient = mProviderClient;
422         when(mProviderClient.update(any(), any(), any(), any())).thenReturn(TEST_PLACEHOLDER_INT);
423 
424         Assert.assertTrue(
425                 mObserver.setMessageStatusRead(
426                         TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE));
427 
428         Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE);
429     }
430 
431     @Test
testDeleteMessageMms_withNonDeletedThreadId()432     public void testDeleteMessageMms_withNonDeletedThreadId() {
433         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
434         BluetoothMapContentObserver.Msg msg =
435                 createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID);
436         map.put(TEST_HANDLE_ONE, msg);
437         mObserver.setMsgListMms(map, true);
438         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
439 
440         MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID});
441         cursor.addRow(new Object[] {TEST_THREAD_ID});
442         doReturn(cursor)
443                 .when(mMapMethodProxy)
444                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
445         doReturn(TEST_PLACEHOLDER_INT)
446                 .when(mMapMethodProxy)
447                 .contentResolverUpdate(any(), any(), any(), any(), any());
448 
449         Assert.assertTrue(mObserver.deleteMessageMms(TEST_HANDLE_ONE));
450 
451         Assert.assertEquals(msg.threadId, BluetoothMapContentObserver.DELETED_THREAD_ID);
452     }
453 
454     @Test
testDeleteMessageMms_withDeletedThreadId()455     public void testDeleteMessageMms_withDeletedThreadId() {
456         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
457         BluetoothMapContentObserver.Msg msg =
458                 createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID);
459         map.put(TEST_HANDLE_ONE, msg);
460         mObserver.setMsgListMms(map, true);
461         Assert.assertNotNull(mObserver.getMsgListMms().get(TEST_HANDLE_ONE));
462 
463         MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID});
464         cursor.addRow(new Object[] {BluetoothMapContentObserver.DELETED_THREAD_ID});
465         doReturn(cursor)
466                 .when(mMapMethodProxy)
467                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
468         doReturn(TEST_PLACEHOLDER_INT)
469                 .when(mMapMethodProxy)
470                 .contentResolverDelete(any(), any(), any(), any());
471 
472         Assert.assertTrue(mObserver.deleteMessageMms(TEST_HANDLE_ONE));
473 
474         Assert.assertNull(mObserver.getMsgListMms().get(TEST_HANDLE_ONE));
475     }
476 
477     @Test
testDeleteMessageSms_withNonDeletedThreadId()478     public void testDeleteMessageSms_withNonDeletedThreadId() {
479         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
480         BluetoothMapContentObserver.Msg msg =
481                 createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID);
482         map.put(TEST_HANDLE_ONE, msg);
483         mObserver.setMsgListSms(map, true);
484         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
485 
486         MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID});
487         cursor.addRow(new Object[] {TEST_THREAD_ID});
488         doReturn(cursor)
489                 .when(mMapMethodProxy)
490                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
491         doReturn(TEST_PLACEHOLDER_INT)
492                 .when(mMapMethodProxy)
493                 .contentResolverUpdate(any(), any(), any(), any(), any());
494 
495         Assert.assertTrue(mObserver.deleteMessageSms(TEST_HANDLE_ONE));
496 
497         Assert.assertEquals(msg.threadId, BluetoothMapContentObserver.DELETED_THREAD_ID);
498     }
499 
500     @Test
testDeleteMessageSms_withDeletedThreadId()501     public void testDeleteMessageSms_withDeletedThreadId() {
502         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
503         BluetoothMapContentObserver.Msg msg =
504                 createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID);
505         map.put(TEST_HANDLE_ONE, msg);
506         mObserver.setMsgListSms(map, true);
507         Assert.assertNotNull(mObserver.getMsgListSms().get(TEST_HANDLE_ONE));
508 
509         MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID});
510         cursor.addRow(new Object[] {BluetoothMapContentObserver.DELETED_THREAD_ID});
511         doReturn(cursor)
512                 .when(mMapMethodProxy)
513                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
514         doReturn(TEST_PLACEHOLDER_INT)
515                 .when(mMapMethodProxy)
516                 .contentResolverDelete(any(), any(), any(), any());
517 
518         Assert.assertTrue(mObserver.deleteMessageSms(TEST_HANDLE_ONE));
519 
520         Assert.assertNull(mObserver.getMsgListSms().get(TEST_HANDLE_ONE));
521     }
522 
523     @Test
testUnDeleteMessageMms_withDeletedThreadId_andMessageBoxInbox()524     public void testUnDeleteMessageMms_withDeletedThreadId_andMessageBoxInbox() {
525         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
526         BluetoothMapContentObserver.Msg msg =
527                 createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID);
528         map.put(TEST_HANDLE_ONE, msg);
529         mObserver.setMsgListMms(map, true);
530         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
531         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL);
532 
533         MatrixCursor cursor =
534                 new MatrixCursor(
535                         new String[] {Mms.THREAD_ID, Mms._ID, Mms.MESSAGE_BOX, Mms.Addr.ADDRESS});
536         cursor.addRow(
537                 new Object[] {
538                     BluetoothMapContentObserver.DELETED_THREAD_ID,
539                     1L,
540                     Mms.MESSAGE_BOX_INBOX,
541                     TEST_ADDRESS
542                 });
543         doReturn(cursor)
544                 .when(mMapMethodProxy)
545                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
546         doReturn(TEST_PLACEHOLDER_INT)
547                 .when(mMapMethodProxy)
548                 .contentResolverUpdate(any(), any(), any(), any(), any());
549         doReturn(TEST_OLD_THREAD_ID)
550                 .when(mMapMethodProxy)
551                 .telephonyGetOrCreateThreadId(any(), any());
552 
553         Assert.assertTrue(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE));
554 
555         Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID);
556         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_INBOX);
557     }
558 
559     @Test
testUnDeleteMessageMms_withDeletedThreadId_andMessageBoxSent()560     public void testUnDeleteMessageMms_withDeletedThreadId_andMessageBoxSent() {
561         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
562         BluetoothMapContentObserver.Msg msg =
563                 createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID);
564         map.put(TEST_HANDLE_ONE, msg);
565         mObserver.setMsgListMms(map, true);
566         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
567         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL);
568 
569         MatrixCursor cursor =
570                 new MatrixCursor(
571                         new String[] {Mms.THREAD_ID, Mms._ID, Mms.MESSAGE_BOX, Mms.Addr.ADDRESS});
572         cursor.addRow(
573                 new Object[] {
574                     BluetoothMapContentObserver.DELETED_THREAD_ID,
575                     1L,
576                     Mms.MESSAGE_BOX_SENT,
577                     TEST_ADDRESS
578                 });
579         doReturn(cursor)
580                 .when(mMapMethodProxy)
581                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
582         doReturn(TEST_PLACEHOLDER_INT)
583                 .when(mMapMethodProxy)
584                 .contentResolverUpdate(any(), any(), any(), any(), any());
585         doReturn(TEST_OLD_THREAD_ID)
586                 .when(mMapMethodProxy)
587                 .telephonyGetOrCreateThreadId(any(), any());
588 
589         Assert.assertTrue(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE));
590 
591         Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID);
592         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_INBOX);
593     }
594 
595     @Test
testUnDeleteMessageMms_withoutDeletedThreadId()596     public void testUnDeleteMessageMms_withoutDeletedThreadId() {
597         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
598         BluetoothMapContentObserver.Msg msg =
599                 createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID);
600         map.put(TEST_HANDLE_ONE, msg);
601         mObserver.setMsgListMms(map, true);
602         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
603         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL);
604 
605         MatrixCursor cursor =
606                 new MatrixCursor(
607                         new String[] {
608                             Mms.THREAD_ID, Mms._ID, Mms.MESSAGE_BOX, Mms.Addr.ADDRESS,
609                         });
610         cursor.addRow(new Object[] {TEST_THREAD_ID, 1L, Mms.MESSAGE_BOX_SENT, TEST_ADDRESS});
611         doReturn(cursor)
612                 .when(mMapMethodProxy)
613                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
614         doReturn(TEST_OLD_THREAD_ID)
615                 .when(mMapMethodProxy)
616                 .telephonyGetOrCreateThreadId(any(), any());
617 
618         Assert.assertTrue(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE));
619 
620         // Nothing changes when thread id is not BluetoothMapContentObserver.DELETED_THREAD_ID
621         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
622         Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL);
623     }
624 
625     @Test
testUnDeleteMessageSms_withDeletedThreadId()626     public void testUnDeleteMessageSms_withDeletedThreadId() {
627         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
628         BluetoothMapContentObserver.Msg msg =
629                 createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID);
630         map.put(TEST_HANDLE_ONE, msg);
631         mObserver.setMsgListSms(map, true);
632         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
633         Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL);
634 
635         MatrixCursor cursor = new MatrixCursor(new String[] {Sms.THREAD_ID, Sms.ADDRESS});
636         cursor.addRow(new Object[] {BluetoothMapContentObserver.DELETED_THREAD_ID, TEST_ADDRESS});
637         doReturn(cursor)
638                 .when(mMapMethodProxy)
639                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
640         doReturn(TEST_PLACEHOLDER_INT)
641                 .when(mMapMethodProxy)
642                 .contentResolverUpdate(any(), any(), any(), any(), any());
643         doReturn(TEST_OLD_THREAD_ID)
644                 .when(mMapMethodProxy)
645                 .telephonyGetOrCreateThreadId(any(), any());
646 
647         Assert.assertTrue(mObserver.unDeleteMessageSms(TEST_HANDLE_ONE));
648 
649         Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID);
650         Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_INBOX);
651     }
652 
653     @Test
testUnDeleteMessageSms_withoutDeletedThreadId()654     public void testUnDeleteMessageSms_withoutDeletedThreadId() {
655         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
656         BluetoothMapContentObserver.Msg msg =
657                 createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID);
658         map.put(TEST_HANDLE_ONE, msg);
659         mObserver.setMsgListSms(map, true);
660         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
661         Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL);
662 
663         MatrixCursor cursor = new MatrixCursor(new String[] {Sms.THREAD_ID, Sms.ADDRESS});
664         cursor.addRow(new Object[] {TEST_THREAD_ID, TEST_ADDRESS});
665         doReturn(cursor)
666                 .when(mMapMethodProxy)
667                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
668         doReturn(TEST_OLD_THREAD_ID)
669                 .when(mMapMethodProxy)
670                 .telephonyGetOrCreateThreadId(any(), any());
671 
672         Assert.assertTrue(mObserver.unDeleteMessageSms(TEST_HANDLE_ONE));
673 
674         // Nothing changes when thread id is not BluetoothMapContentObserver.DELETED_THREAD_ID
675         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
676         Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL);
677     }
678 
679     @Test
testPushMsgInfo()680     public void testPushMsgInfo() {
681         long id = 1;
682         int transparent = 1;
683         int retry = 1;
684         String phone = "test_phone";
685         Uri uri = mock(Uri.class);
686 
687         BluetoothMapContentObserver.PushMsgInfo msgInfo =
688                 new BluetoothMapContentObserver.PushMsgInfo(id, transparent, retry, phone, uri);
689 
690         Assert.assertEquals(msgInfo.id, id);
691         Assert.assertEquals(msgInfo.transparent, transparent);
692         Assert.assertEquals(msgInfo.retry, retry);
693         Assert.assertEquals(msgInfo.phone, phone);
694         Assert.assertEquals(msgInfo.uri, uri);
695     }
696 
697     @Test
setEmailMessageStatusDelete_withStatusValueYes()698     public void setEmailMessageStatusDelete_withStatusValueYes() {
699         setFolderStructureWithTelecomAndMsg(
700                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
701         mObserver.setFolderStructure(mFolders);
702 
703         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
704         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
705         map.put(TEST_HANDLE_ONE, msg);
706         mObserver.setMsgListMsg(map, true);
707         doReturn(TEST_PLACEHOLDER_INT)
708                 .when(mMapMethodProxy)
709                 .contentResolverUpdate(any(), any(), any(), any(), any());
710 
711         Assert.assertTrue(
712                 mObserver.setEmailMessageStatusDelete(
713                         mCurrentFolder,
714                         TEST_URI_STR,
715                         TEST_HANDLE_ONE,
716                         BluetoothMapAppParams.STATUS_VALUE_YES));
717         Assert.assertEquals(msg.folderId, TEST_DELETE_FOLDER_ID);
718     }
719 
720     @Test
setEmailMessageStatusDelete_withStatusValueYes_andUpdateCountZero()721     public void setEmailMessageStatusDelete_withStatusValueYes_andUpdateCountZero() {
722         setFolderStructureWithTelecomAndMsg(
723                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
724         mObserver.setFolderStructure(mFolders);
725 
726         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
727         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
728         map.put(TEST_HANDLE_ONE, msg);
729         mObserver.setMsgListMsg(map, true);
730         doReturn(0).when(mMapMethodProxy).contentResolverUpdate(any(), any(), any(), any(), any());
731 
732         Assert.assertFalse(
733                 mObserver.setEmailMessageStatusDelete(
734                         mCurrentFolder,
735                         TEST_URI_STR,
736                         TEST_HANDLE_ONE,
737                         BluetoothMapAppParams.STATUS_VALUE_YES));
738     }
739 
740     @Test
setEmailMessageStatusDelete_withStatusValueNo()741     public void setEmailMessageStatusDelete_withStatusValueNo() {
742         setFolderStructureWithTelecomAndMsg(
743                 mCurrentFolder, BluetoothMapContract.FOLDER_NAME_INBOX, TEST_INBOX_FOLDER_ID);
744         setFolderStructureWithTelecomAndMsg(
745                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
746         mObserver.setFolderStructure(mFolders);
747 
748         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
749         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
750         msg.oldFolderId = TEST_OLD_FOLDER_ID;
751         msg.folderId = TEST_DELETE_FOLDER_ID;
752         map.put(TEST_HANDLE_ONE, msg);
753         mObserver.setMsgListMsg(map, true);
754         doReturn(TEST_PLACEHOLDER_INT)
755                 .when(mMapMethodProxy)
756                 .contentResolverUpdate(any(), any(), any(), any(), any());
757 
758         Assert.assertTrue(
759                 mObserver.setEmailMessageStatusDelete(
760                         mCurrentFolder,
761                         TEST_URI_STR,
762                         TEST_HANDLE_ONE,
763                         BluetoothMapAppParams.STATUS_VALUE_NO));
764         Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID);
765     }
766 
767     @Test
setEmailMessageStatusDelete_withStatusValueNo_andOldFolderIdMinusOne()768     public void setEmailMessageStatusDelete_withStatusValueNo_andOldFolderIdMinusOne() {
769         int oldFolderId = -1;
770         setFolderStructureWithTelecomAndMsg(
771                 mCurrentFolder, BluetoothMapContract.FOLDER_NAME_INBOX, TEST_INBOX_FOLDER_ID);
772         setFolderStructureWithTelecomAndMsg(
773                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
774         mObserver.setFolderStructure(mFolders);
775 
776         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
777         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
778         msg.oldFolderId = oldFolderId;
779         msg.folderId = TEST_DELETE_FOLDER_ID;
780         map.put(TEST_HANDLE_ONE, msg);
781         mObserver.setMsgListMsg(map, true);
782         doReturn(TEST_PLACEHOLDER_INT)
783                 .when(mMapMethodProxy)
784                 .contentResolverUpdate(any(), any(), any(), any(), any());
785 
786         Assert.assertTrue(
787                 mObserver.setEmailMessageStatusDelete(
788                         mCurrentFolder,
789                         TEST_URI_STR,
790                         TEST_HANDLE_ONE,
791                         BluetoothMapAppParams.STATUS_VALUE_NO));
792         Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID);
793     }
794 
795     @Test
setEmailMessageStatusDelete_withStatusValueNo_andInboxFolderNull()796     public void setEmailMessageStatusDelete_withStatusValueNo_andInboxFolderNull() {
797         // This sets mCurrentFolder to have a sent folder, but not an inbox folder
798         setFolderStructureWithTelecomAndMsg(
799                 mCurrentFolder,
800                 BluetoothMapContract.FOLDER_NAME_SENT,
801                 BluetoothMapContract.FOLDER_ID_SENT);
802         setFolderStructureWithTelecomAndMsg(
803                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
804         mObserver.setFolderStructure(mFolders);
805 
806         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
807         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
808         msg.oldFolderId = TEST_OLD_FOLDER_ID;
809         msg.folderId = TEST_DELETE_FOLDER_ID;
810         map.put(TEST_HANDLE_ONE, msg);
811         mObserver.setMsgListMsg(map, true);
812         doReturn(TEST_PLACEHOLDER_INT)
813                 .when(mMapMethodProxy)
814                 .contentResolverUpdate(any(), any(), any(), any(), any());
815 
816         Assert.assertTrue(
817                 mObserver.setEmailMessageStatusDelete(
818                         mCurrentFolder,
819                         TEST_URI_STR,
820                         TEST_HANDLE_ONE,
821                         BluetoothMapAppParams.STATUS_VALUE_NO));
822         Assert.assertEquals(msg.folderId, TEST_OLD_FOLDER_ID);
823     }
824 
825     @Test
setMessageStatusDeleted_withTypeEmail()826     public void setMessageStatusDeleted_withTypeEmail() {
827         setFolderStructureWithTelecomAndMsg(
828                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
829         mObserver.setFolderStructure(mFolders);
830 
831         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
832         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
833         map.put(TEST_HANDLE_ONE, msg);
834         mObserver.setMsgListMsg(map, true);
835         doReturn(TEST_PLACEHOLDER_INT)
836                 .when(mMapMethodProxy)
837                 .contentResolverUpdate(any(), any(), any(), any(), any());
838 
839         Assert.assertTrue(
840                 mObserver.setMessageStatusDeleted(
841                         TEST_HANDLE_ONE,
842                         TYPE.EMAIL,
843                         mCurrentFolder,
844                         TEST_URI_STR,
845                         BluetoothMapAppParams.STATUS_VALUE_YES));
846     }
847 
848     @Test
setMessageStatusDeleted_withTypeIm()849     public void setMessageStatusDeleted_withTypeIm() {
850         Assert.assertFalse(
851                 mObserver.setMessageStatusDeleted(
852                         TEST_HANDLE_ONE,
853                         TYPE.IM,
854                         mCurrentFolder,
855                         TEST_URI_STR,
856                         BluetoothMapAppParams.STATUS_VALUE_YES));
857     }
858 
859     @Test
setMessageStatusDeleted_withTypeGsmOrMms_andStatusValueNo()860     public void setMessageStatusDeleted_withTypeGsmOrMms_andStatusValueNo() {
861         doReturn(null)
862                 .when(mMapMethodProxy)
863                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
864         doReturn(TEST_OLD_THREAD_ID)
865                 .when(mMapMethodProxy)
866                 .telephonyGetOrCreateThreadId(any(), any());
867 
868         // setMessageStatusDeleted with type Gsm or Mms calls either deleteMessage() or
869         // unDeleteMessage(), which returns false when no cursor is set with BluetoothMethodProxy.
870         Assert.assertFalse(
871                 mObserver.setMessageStatusDeleted(
872                         TEST_HANDLE_ONE,
873                         TYPE.MMS,
874                         mCurrentFolder,
875                         TEST_URI_STR,
876                         BluetoothMapAppParams.STATUS_VALUE_NO));
877         Assert.assertFalse(
878                 mObserver.setMessageStatusDeleted(
879                         TEST_HANDLE_ONE,
880                         TYPE.SMS_GSM,
881                         mCurrentFolder,
882                         TEST_URI_STR,
883                         BluetoothMapAppParams.STATUS_VALUE_NO));
884     }
885 
886     @Test
setMessageStatusDeleted_withTypeGsmOrMms_andStatusValueYes()887     public void setMessageStatusDeleted_withTypeGsmOrMms_andStatusValueYes() {
888         doReturn(null)
889                 .when(mMapMethodProxy)
890                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
891         doReturn(TEST_PLACEHOLDER_INT)
892                 .when(mMapMethodProxy)
893                 .contentResolverUpdate(any(), any(), any(), any(), any());
894 
895         // setMessageStatusDeleted with type Gsm or Mms calls either deleteMessage() or
896         // unDeleteMessage(), which returns false when no cursor is set with BluetoothMethodProxy.
897         Assert.assertFalse(
898                 mObserver.setMessageStatusDeleted(
899                         TEST_HANDLE_ONE,
900                         TYPE.MMS,
901                         mCurrentFolder,
902                         TEST_URI_STR,
903                         BluetoothMapAppParams.STATUS_VALUE_YES));
904         Assert.assertFalse(
905                 mObserver.setMessageStatusDeleted(
906                         TEST_HANDLE_ONE,
907                         TYPE.SMS_GSM,
908                         mCurrentFolder,
909                         TEST_URI_STR,
910                         BluetoothMapAppParams.STATUS_VALUE_YES));
911     }
912 
913     @Test
initMsgList_withMsgSms()914     public void initMsgList_withMsgSms() throws Exception {
915         MatrixCursor cursor =
916                 new MatrixCursor(new String[] {Sms._ID, Sms.TYPE, Sms.THREAD_ID, Sms.READ});
917         cursor.addRow(
918                 new Object[] {
919                     (long) TEST_ID, TEST_SMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ONE
920                 });
921         doReturn(cursor)
922                 .when(mMapMethodProxy)
923                 .contentResolverQuery(
924                         any(),
925                         any(),
926                         eq(BluetoothMapContentObserver.SMS_PROJECTION_SHORT),
927                         any(),
928                         any(),
929                         any());
930         cursor.moveToFirst();
931         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
932         mObserver.setMsgListMsg(map, true);
933 
934         mObserver.initMsgList();
935 
936         BluetoothMapContentObserver.Msg msg = mObserver.getMsgListSms().get((long) TEST_ID);
937         Assert.assertEquals(msg.id, TEST_ID);
938         Assert.assertEquals(msg.type, TEST_SMS_TYPE_ALL);
939         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
940         Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ONE);
941     }
942 
943     @Test
initMsgList_withMsgMms()944     public void initMsgList_withMsgMms() throws Exception {
945         MatrixCursor cursor =
946                 new MatrixCursor(new String[] {Mms._ID, Mms.MESSAGE_BOX, Mms.THREAD_ID, Mms.READ});
947         cursor.addRow(
948                 new Object[] {
949                     (long) TEST_ID, TEST_MMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ZERO
950                 });
951         doReturn(null)
952                 .when(mMapMethodProxy)
953                 .contentResolverQuery(
954                         any(),
955                         any(),
956                         eq(BluetoothMapContentObserver.SMS_PROJECTION_SHORT),
957                         any(),
958                         any(),
959                         any());
960         doReturn(cursor)
961                 .when(mMapMethodProxy)
962                 .contentResolverQuery(
963                         any(),
964                         any(),
965                         eq(BluetoothMapContentObserver.MMS_PROJECTION_SHORT),
966                         any(),
967                         any(),
968                         any());
969         cursor.moveToFirst();
970         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
971         mObserver.setMsgListMsg(map, true);
972 
973         mObserver.initMsgList();
974 
975         BluetoothMapContentObserver.Msg msg = mObserver.getMsgListMms().get((long) TEST_ID);
976         Assert.assertEquals(msg.id, TEST_ID);
977         Assert.assertEquals(msg.type, TEST_MMS_TYPE_ALL);
978         Assert.assertEquals(msg.threadId, TEST_THREAD_ID);
979         Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ZERO);
980     }
981 
982     @Test
initMsgList_withMsg()983     public void initMsgList_withMsg() throws Exception {
984         MatrixCursor cursor =
985                 new MatrixCursor(
986                         new String[] {
987                             MessageColumns._ID, MessageColumns.FOLDER_ID, MessageColumns.FLAG_READ
988                         });
989         cursor.addRow(new Object[] {(long) TEST_ID, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE});
990         doReturn(null)
991                 .when(mMapMethodProxy)
992                 .contentResolverQuery(
993                         any(),
994                         any(),
995                         eq(BluetoothMapContentObserver.SMS_PROJECTION_SHORT),
996                         any(),
997                         any(),
998                         any());
999         doReturn(null)
1000                 .when(mMapMethodProxy)
1001                 .contentResolverQuery(
1002                         any(),
1003                         any(),
1004                         eq(BluetoothMapContentObserver.MMS_PROJECTION_SHORT),
1005                         any(),
1006                         any(),
1007                         any());
1008         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1009         cursor.moveToFirst();
1010         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1011         mObserver.setMsgListMsg(map, true);
1012 
1013         mObserver.initMsgList();
1014 
1015         BluetoothMapContentObserver.Msg msg = mObserver.getMsgListMsg().get((long) TEST_ID);
1016         Assert.assertEquals(msg.id, TEST_ID);
1017         Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID);
1018         Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ONE);
1019     }
1020 
1021     @Test
initContactsList()1022     public void initContactsList() throws Exception {
1023         MatrixCursor cursor =
1024                 new MatrixCursor(
1025                         new String[] {
1026                             BluetoothMapContract.ConvoContactColumns.CONVO_ID,
1027                             BluetoothMapContract.ConvoContactColumns.NAME,
1028                             BluetoothMapContract.ConvoContactColumns.NICKNAME,
1029                             BluetoothMapContract.ConvoContactColumns.X_BT_UID,
1030                             BluetoothMapContract.ConvoContactColumns.CHAT_STATE,
1031                             BluetoothMapContract.ConvoContactColumns.UCI,
1032                             BluetoothMapContract.ConvoContactColumns.LAST_ACTIVE,
1033                             BluetoothMapContract.ConvoContactColumns.PRESENCE_STATE,
1034                             BluetoothMapContract.ConvoContactColumns.STATUS_TEXT,
1035                             BluetoothMapContract.ConvoContactColumns.PRIORITY,
1036                             BluetoothMapContract.ConvoContactColumns.LAST_ONLINE
1037                         });
1038         cursor.addRow(
1039                 new Object[] {
1040                     TEST_CONVO_ID,
1041                     TEST_NAME,
1042                     TEST_DISPLAY_NAME,
1043                     TEST_BT_UID,
1044                     TEST_CHAT_STATE,
1045                     TEST_UCI,
1046                     TEST_LAST_ACTIVITY,
1047                     TEST_PRESENCE_STATE,
1048                     TEST_STATUS_TEXT,
1049                     TEST_PRIORITY,
1050                     TEST_LAST_ONLINE
1051                 });
1052         doReturn(cursor)
1053                 .when(mMapMethodProxy)
1054                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1055 
1056         mObserver.mContactUri = mock(Uri.class);
1057         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1058 
1059         Map<String, BluetoothMapConvoContactElement> map = new HashMap<>();
1060         mObserver.setContactList(map, true);
1061         mObserver.initContactsList();
1062         BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI);
1063 
1064         final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
1065         Assert.assertEquals(contactElement.getContactId(), TEST_UCI);
1066         Assert.assertEquals(contactElement.getName(), TEST_NAME);
1067         Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME);
1068         Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID);
1069         Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE);
1070         Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT);
1071         Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE);
1072         Assert.assertEquals(
1073                 contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY));
1074         Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY);
1075     }
1076 
1077     @Test
handleMsgListChangesMsg_withNonExistingMessage_andVersion11()1078     public void handleMsgListChangesMsg_withNonExistingMessage_andVersion11() throws Exception {
1079         MatrixCursor cursor =
1080                 new MatrixCursor(
1081                         new String[] {
1082                             BluetoothMapContract.MessageColumns._ID,
1083                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1084                             BluetoothMapContract.MessageColumns.FLAG_READ,
1085                             BluetoothMapContract.MessageColumns.DATE,
1086                             BluetoothMapContract.MessageColumns.SUBJECT,
1087                             BluetoothMapContract.MessageColumns.FROM_LIST,
1088                             BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY
1089                         });
1090         cursor.addRow(
1091                 new Object[] {
1092                     TEST_HANDLE_ONE,
1093                     TEST_INBOX_FOLDER_ID,
1094                     TEST_READ_FLAG_ONE,
1095                     TEST_DATE_MS,
1096                     TEST_SUBJECT,
1097                     TEST_ADDRESS,
1098                     1
1099                 });
1100         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1101 
1102         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1103         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMsg()
1104         // function for a non-existing message
1105         BluetoothMapContentObserver.Msg msg =
1106                 new BluetoothMapContentObserver.Msg(
1107                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1108         msg.localInitiatedSend = true;
1109         msg.transparent = true;
1110         map.put(TEST_HANDLE_TWO, msg);
1111         mObserver.setMsgListMsg(map, true);
1112         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1113         mFolders.setFolderId(TEST_INBOX_FOLDER_ID);
1114         mObserver.setFolderStructure(mFolders);
1115 
1116         mObserver.handleMsgListChangesMsg(TEST_URI);
1117 
1118         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1119         Assert.assertEquals(
1120                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID);
1121         Assert.assertEquals(
1122                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1123     }
1124 
1125     @Test
handleMsgListChangesMsg_withNonExistingMessage_andVersion12()1126     public void handleMsgListChangesMsg_withNonExistingMessage_andVersion12() throws Exception {
1127         MatrixCursor cursor =
1128                 new MatrixCursor(
1129                         new String[] {
1130                             BluetoothMapContract.MessageColumns._ID,
1131                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1132                             BluetoothMapContract.MessageColumns.FLAG_READ,
1133                             BluetoothMapContract.MessageColumns.DATE,
1134                             BluetoothMapContract.MessageColumns.SUBJECT,
1135                             BluetoothMapContract.MessageColumns.FROM_LIST,
1136                             BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY,
1137                             BluetoothMapContract.MessageColumns.THREAD_ID,
1138                             BluetoothMapContract.MessageColumns.THREAD_NAME
1139                         });
1140         cursor.addRow(
1141                 new Object[] {
1142                     TEST_HANDLE_ONE,
1143                     TEST_INBOX_FOLDER_ID,
1144                     TEST_READ_FLAG_ONE,
1145                     TEST_DATE_MS,
1146                     TEST_SUBJECT,
1147                     TEST_ADDRESS,
1148                     1,
1149                     1,
1150                     "threadName"
1151                 });
1152         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1153 
1154         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1155         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMsg()
1156         // function for a non-existing message
1157         BluetoothMapContentObserver.Msg msg =
1158                 new BluetoothMapContentObserver.Msg(
1159                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1160         msg.localInitiatedSend = false;
1161         msg.transparent = false;
1162         map.put(TEST_HANDLE_TWO, msg);
1163         mObserver.setMsgListMsg(map, true);
1164         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1165 
1166         mObserver.handleMsgListChangesMsg(TEST_URI);
1167 
1168         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1169         Assert.assertEquals(
1170                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID);
1171         Assert.assertEquals(
1172                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1173     }
1174 
1175     @Test
handleMsgListChangesMsg_withNonExistingMessage_andVersion10()1176     public void handleMsgListChangesMsg_withNonExistingMessage_andVersion10() throws Exception {
1177         MatrixCursor cursor =
1178                 new MatrixCursor(
1179                         new String[] {
1180                             BluetoothMapContract.MessageColumns._ID,
1181                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1182                             BluetoothMapContract.MessageColumns.FLAG_READ
1183                         });
1184         cursor.addRow(new Object[] {TEST_HANDLE_ONE, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE});
1185         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1186 
1187         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1188         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMsg()
1189         // function for a non-existing message
1190         BluetoothMapContentObserver.Msg msg =
1191                 new BluetoothMapContentObserver.Msg(
1192                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1193         msg.localInitiatedSend = false;
1194         msg.transparent = false;
1195         map.put(TEST_HANDLE_TWO, msg);
1196         mObserver.setMsgListMsg(map, true);
1197         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V10;
1198         mFolders.setFolderId(TEST_HANDLE_TWO);
1199         mObserver.setFolderStructure(mFolders);
1200 
1201         mObserver.handleMsgListChangesMsg(TEST_URI);
1202 
1203         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1204         Assert.assertEquals(
1205                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID);
1206         Assert.assertEquals(
1207                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1208     }
1209 
1210     @Test
handleMsgListChangesMsg_withExistingMessage_andNonNullDeletedFolder()1211     public void handleMsgListChangesMsg_withExistingMessage_andNonNullDeletedFolder()
1212             throws Exception {
1213         MatrixCursor cursor =
1214                 new MatrixCursor(
1215                         new String[] {
1216                             BluetoothMapContract.MessageColumns._ID,
1217                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1218                             BluetoothMapContract.MessageColumns.FLAG_READ,
1219                         });
1220         cursor.addRow(new Object[] {TEST_HANDLE_ONE, TEST_DELETE_FOLDER_ID, TEST_READ_FLAG_ONE});
1221         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1222 
1223         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1224         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMsg()
1225         // function for an existing message
1226         BluetoothMapContentObserver.Msg msg =
1227                 new BluetoothMapContentObserver.Msg(
1228                         TEST_HANDLE_ONE, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ZERO);
1229         map.put(TEST_HANDLE_ONE, msg);
1230         mObserver.setMsgListMsg(map, true);
1231         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1232         setFolderStructureWithTelecomAndMsg(
1233                 mFolders, BluetoothMapContract.FOLDER_NAME_DELETED, TEST_DELETE_FOLDER_ID);
1234         mObserver.setFolderStructure(mFolders);
1235 
1236         mObserver.handleMsgListChangesMsg(TEST_URI);
1237 
1238         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1239         Assert.assertEquals(
1240                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_DELETE_FOLDER_ID);
1241         Assert.assertEquals(
1242                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1243     }
1244 
1245     @Test
handleMsgListChangesMsg_withExistingMessage_andNonNullSentFolder()1246     public void handleMsgListChangesMsg_withExistingMessage_andNonNullSentFolder()
1247             throws Exception {
1248         MatrixCursor cursor =
1249                 new MatrixCursor(
1250                         new String[] {
1251                             BluetoothMapContract.MessageColumns._ID,
1252                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1253                             BluetoothMapContract.MessageColumns.FLAG_READ,
1254                         });
1255         cursor.addRow(new Object[] {TEST_HANDLE_ONE, TEST_SENT_FOLDER_ID, TEST_READ_FLAG_ONE});
1256         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1257 
1258         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1259         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMsg()
1260         // function for an existing message
1261         BluetoothMapContentObserver.Msg msg =
1262                 new BluetoothMapContentObserver.Msg(
1263                         TEST_HANDLE_ONE, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ZERO);
1264         msg.localInitiatedSend = true;
1265         msg.transparent = false;
1266         map.put(TEST_HANDLE_ONE, msg);
1267         mObserver.setMsgListMsg(map, true);
1268         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1269         setFolderStructureWithTelecomAndMsg(
1270                 mFolders, BluetoothMapContract.FOLDER_NAME_SENT, TEST_SENT_FOLDER_ID);
1271         mObserver.setFolderStructure(mFolders);
1272 
1273         mObserver.handleMsgListChangesMsg(TEST_URI);
1274 
1275         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1276         Assert.assertEquals(
1277                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_SENT_FOLDER_ID);
1278         Assert.assertEquals(
1279                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1280     }
1281 
1282     @Test
handleMsgListChangesMsg_withExistingMessage_andNonNullTransparentSentFolder()1283     public void handleMsgListChangesMsg_withExistingMessage_andNonNullTransparentSentFolder()
1284             throws Exception {
1285         MatrixCursor cursor =
1286                 new MatrixCursor(
1287                         new String[] {
1288                             BluetoothMapContract.MessageColumns._ID,
1289                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1290                             BluetoothMapContract.MessageColumns.FLAG_READ,
1291                         });
1292         cursor.addRow(new Object[] {TEST_HANDLE_ONE, TEST_SENT_FOLDER_ID, TEST_READ_FLAG_ONE});
1293         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1294 
1295         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1296         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMsg()
1297         // function for an existing message
1298         BluetoothMapContentObserver.Msg msg =
1299                 new BluetoothMapContentObserver.Msg(
1300                         TEST_HANDLE_ONE, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ZERO);
1301         msg.localInitiatedSend = true;
1302         msg.transparent = true;
1303         map.put(TEST_HANDLE_ONE, msg);
1304         mObserver.setMsgListMsg(map, true);
1305         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1306         doReturn(TEST_PLACEHOLDER_INT)
1307                 .when(mMapMethodProxy)
1308                 .contentResolverDelete(any(), any(), any(), any());
1309         setFolderStructureWithTelecomAndMsg(
1310                 mFolders, BluetoothMapContract.FOLDER_NAME_SENT, TEST_SENT_FOLDER_ID);
1311         mObserver.setFolderStructure(mFolders);
1312         mObserver.mMessageUri = Mms.CONTENT_URI;
1313 
1314         mObserver.handleMsgListChangesMsg(TEST_URI);
1315 
1316         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1317         Assert.assertEquals(
1318                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_SENT_FOLDER_ID);
1319         Assert.assertEquals(
1320                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1321     }
1322 
1323     @Test
handleMsgListChangesMsg_withExistingMessage_andUnknownOldFolder()1324     public void handleMsgListChangesMsg_withExistingMessage_andUnknownOldFolder() throws Exception {
1325         MatrixCursor cursor =
1326                 new MatrixCursor(
1327                         new String[] {
1328                             BluetoothMapContract.MessageColumns._ID,
1329                             BluetoothMapContract.MessageColumns.FOLDER_ID,
1330                             BluetoothMapContract.MessageColumns.FLAG_READ,
1331                         });
1332         cursor.addRow(new Object[] {TEST_HANDLE_ONE, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE});
1333         when(mProviderClient.query(any(), any(), any(), any(), any())).thenReturn(cursor);
1334 
1335         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1336         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMsg()
1337         // function for an existing message
1338         BluetoothMapContentObserver.Msg msg =
1339                 new BluetoothMapContentObserver.Msg(
1340                         TEST_HANDLE_ONE, TEST_SENT_FOLDER_ID, TEST_READ_FLAG_ZERO);
1341         msg.localInitiatedSend = true;
1342         msg.transparent = false;
1343         map.put(TEST_HANDLE_ONE, msg);
1344         mObserver.setMsgListMsg(map, true);
1345         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1346         setFolderStructureWithTelecomAndMsg(
1347                 mFolders, BluetoothMapContract.FOLDER_NAME_DRAFT, TEST_DRAFT_FOLDER_ID);
1348         mObserver.setFolderStructure(mFolders);
1349 
1350         mObserver.handleMsgListChangesMsg(TEST_URI);
1351 
1352         Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1353         Assert.assertEquals(
1354                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_INBOX_FOLDER_ID);
1355         Assert.assertEquals(
1356                 mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1357     }
1358 
1359     @Test
handleMsgListChangesMms_withNonExistingMessage_andVersion11()1360     public void handleMsgListChangesMms_withNonExistingMessage_andVersion11() {
1361         MatrixCursor cursor =
1362                 new MatrixCursor(
1363                         new String[] {
1364                             Mms._ID,
1365                             Mms.MESSAGE_BOX,
1366                             Mms.MESSAGE_TYPE,
1367                             Mms.THREAD_ID,
1368                             Mms.READ,
1369                             Mms.DATE,
1370                             Mms.SUBJECT,
1371                             Mms.PRIORITY,
1372                             Mms.Addr.ADDRESS
1373                         });
1374         cursor.addRow(
1375                 new Object[] {
1376                     TEST_HANDLE_ONE,
1377                     TEST_MMS_TYPE_ALL,
1378                     TEST_MMS_MTYPE,
1379                     TEST_THREAD_ID,
1380                     TEST_READ_FLAG_ONE,
1381                     TEST_DATE_SEC,
1382                     TEST_SUBJECT,
1383                     PduHeaders.PRIORITY_HIGH,
1384                     null
1385                 });
1386         doReturn(cursor)
1387                 .when(mMapMethodProxy)
1388                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1389 
1390         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1391         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1392         // function for a non-existing message
1393         BluetoothMapContentObserver.Msg msg =
1394                 new BluetoothMapContentObserver.Msg(
1395                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1396         map.put(TEST_HANDLE_TWO, msg);
1397         mObserver.setMsgListMms(map, true);
1398         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1399 
1400         mObserver.handleMsgListChangesMms();
1401 
1402         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1403         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1404         Assert.assertEquals(
1405                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1406         Assert.assertEquals(
1407                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1408     }
1409 
1410     @Test
handleMsgListChangesMms_withNonExistingMessage_andVersion12()1411     public void handleMsgListChangesMms_withNonExistingMessage_andVersion12() {
1412         MatrixCursor cursor =
1413                 new MatrixCursor(
1414                         new String[] {
1415                             Mms._ID,
1416                             Mms.MESSAGE_BOX,
1417                             Mms.MESSAGE_TYPE,
1418                             Mms.THREAD_ID,
1419                             Mms.READ,
1420                             Mms.DATE,
1421                             Mms.SUBJECT,
1422                             Mms.PRIORITY,
1423                             Mms.Addr.ADDRESS
1424                         });
1425         cursor.addRow(
1426                 new Object[] {
1427                     TEST_HANDLE_ONE,
1428                     TEST_MMS_TYPE_ALL,
1429                     TEST_MMS_MTYPE,
1430                     TEST_THREAD_ID,
1431                     TEST_READ_FLAG_ONE,
1432                     TEST_DATE_SEC,
1433                     TEST_SUBJECT,
1434                     PduHeaders.PRIORITY_HIGH,
1435                     null
1436                 });
1437         doReturn(cursor)
1438                 .when(mMapMethodProxy)
1439                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1440 
1441         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1442         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1443         // function for a non-existing message
1444         BluetoothMapContentObserver.Msg msg =
1445                 new BluetoothMapContentObserver.Msg(
1446                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1447         map.put(TEST_HANDLE_TWO, msg);
1448         mObserver.setMsgListMms(map, true);
1449         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1450 
1451         mObserver.handleMsgListChangesMms();
1452 
1453         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1454         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1455         Assert.assertEquals(
1456                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1457         Assert.assertEquals(
1458                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1459     }
1460 
1461     @Test
handleMsgListChangesMms_withNonExistingOldMessage_andVersion12()1462     public void handleMsgListChangesMms_withNonExistingOldMessage_andVersion12() {
1463         mSetFlagsRule.disableFlags(Flags.FLAG_MAP_LIMIT_NOTIFICATION);
1464         Calendar cal = Calendar.getInstance();
1465         cal.add(Calendar.YEAR, -1);
1466         cal.add(Calendar.DATE, -1);
1467         long timestampSec = TimeUnit.MILLISECONDS.toSeconds(cal.getTimeInMillis());
1468 
1469         MatrixCursor cursor =
1470                 new MatrixCursor(
1471                         new String[] {
1472                             Mms._ID,
1473                             Mms.MESSAGE_BOX,
1474                             Mms.MESSAGE_TYPE,
1475                             Mms.THREAD_ID,
1476                             Mms.READ,
1477                             Mms.DATE,
1478                             Mms.SUBJECT,
1479                             Mms.PRIORITY,
1480                             Mms.Addr.ADDRESS
1481                         });
1482         cursor.addRow(
1483                 new Object[] {
1484                     TEST_HANDLE_ONE,
1485                     TEST_MMS_TYPE_ALL,
1486                     TEST_MMS_MTYPE,
1487                     TEST_THREAD_ID,
1488                     TEST_READ_FLAG_ONE,
1489                     timestampSec,
1490                     TEST_SUBJECT,
1491                     PduHeaders.PRIORITY_HIGH,
1492                     null
1493                 });
1494         doReturn(cursor)
1495                 .when(mMapMethodProxy)
1496                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1497 
1498         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1499         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1500         // function for a non-existing message
1501         BluetoothMapContentObserver.Msg msg =
1502                 new BluetoothMapContentObserver.Msg(
1503                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1504         map.put(TEST_HANDLE_TWO, msg);
1505         mObserver.setMsgListMms(map, true);
1506         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1507 
1508         mObserver.handleMsgListChangesMms();
1509 
1510         Assert.assertEquals(null, mObserver.getMsgListMms().get(TEST_HANDLE_ONE));
1511     }
1512 
1513     @Test
handleMsgListChangesMms_withNonExistingOldMessage_andVersion12_andOneWeekLimit()1514     public void handleMsgListChangesMms_withNonExistingOldMessage_andVersion12_andOneWeekLimit() {
1515         mSetFlagsRule.enableFlags(Flags.FLAG_MAP_LIMIT_NOTIFICATION);
1516         Instant oldInstant =
1517                 Instant.now()
1518                         .minus(BluetoothMapContentObserver.NEW_MESSAGE_DURATION_FOR_NOTIFICATION);
1519         long timestampSec = oldInstant.getEpochSecond();
1520 
1521         MatrixCursor cursor =
1522                 new MatrixCursor(
1523                         new String[] {
1524                             Mms._ID,
1525                             Mms.MESSAGE_BOX,
1526                             Mms.MESSAGE_TYPE,
1527                             Mms.THREAD_ID,
1528                             Mms.READ,
1529                             Mms.DATE,
1530                             Mms.SUBJECT,
1531                             Mms.PRIORITY,
1532                             Mms.Addr.ADDRESS
1533                         });
1534         cursor.addRow(
1535                 new Object[] {
1536                     TEST_HANDLE_ONE,
1537                     TEST_MMS_TYPE_ALL,
1538                     TEST_MMS_MTYPE,
1539                     TEST_THREAD_ID,
1540                     TEST_READ_FLAG_ONE,
1541                     timestampSec,
1542                     TEST_SUBJECT,
1543                     PduHeaders.PRIORITY_HIGH,
1544                     null
1545                 });
1546         doReturn(cursor)
1547                 .when(mMapMethodProxy)
1548                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1549 
1550         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1551         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1552 
1553         BluetoothMapContentObserver.Msg msg =
1554                 new BluetoothMapContentObserver.Msg(
1555                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1556         map.put(TEST_HANDLE_TWO, msg);
1557         mObserver.setMsgListMms(map, true);
1558         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1559 
1560         mObserver.handleMsgListChangesMms();
1561 
1562         Assert.assertEquals(null, mObserver.getMsgListMms().get(TEST_HANDLE_ONE));
1563     }
1564 
1565     @Test
handleMsgListChangesMms_withNonExistingMessage_andVersion10()1566     public void handleMsgListChangesMms_withNonExistingMessage_andVersion10() {
1567         MatrixCursor cursor =
1568                 new MatrixCursor(
1569                         new String[] {
1570                             Mms._ID, Mms.MESSAGE_BOX, Mms.MESSAGE_TYPE, Mms.THREAD_ID, Mms.READ
1571                         });
1572         cursor.addRow(
1573                 new Object[] {
1574                     TEST_HANDLE_ONE,
1575                     TEST_MMS_TYPE_ALL,
1576                     TEST_MMS_MTYPE,
1577                     TEST_THREAD_ID,
1578                     TEST_READ_FLAG_ONE
1579                 });
1580         doReturn(cursor)
1581                 .when(mMapMethodProxy)
1582                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1583 
1584         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1585         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1586         // function for a non-existing message
1587         BluetoothMapContentObserver.Msg msg =
1588                 new BluetoothMapContentObserver.Msg(
1589                         TEST_HANDLE_TWO, TEST_INBOX_FOLDER_ID, TEST_READ_FLAG_ONE);
1590         map.put(TEST_HANDLE_TWO, msg);
1591         mObserver.setMsgListMms(map, true);
1592         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V10;
1593 
1594         mObserver.handleMsgListChangesMms();
1595 
1596         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1597         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1598         Assert.assertEquals(
1599                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1600         Assert.assertEquals(
1601                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1602     }
1603 
1604     @Test
handleMsgListChangesMms_withExistingMessage_withNonEqualType_andLocalSendFalse()1605     public void handleMsgListChangesMms_withExistingMessage_withNonEqualType_andLocalSendFalse() {
1606         MatrixCursor cursor =
1607                 new MatrixCursor(
1608                         new String[] {
1609                             Mms._ID, Mms.MESSAGE_BOX, Mms.MESSAGE_TYPE, Mms.THREAD_ID, Mms.READ
1610                         });
1611         cursor.addRow(
1612                 new Object[] {
1613                     TEST_HANDLE_ONE,
1614                     TEST_MMS_TYPE_ALL,
1615                     TEST_MMS_MTYPE,
1616                     TEST_THREAD_ID,
1617                     TEST_READ_FLAG_ONE
1618                 });
1619         doReturn(cursor)
1620                 .when(mMapMethodProxy)
1621                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1622 
1623         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1624         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMms()
1625         // function for an existing message
1626         BluetoothMapContentObserver.Msg msg =
1627                 new BluetoothMapContentObserver.Msg(
1628                         TEST_HANDLE_ONE, TEST_MMS_TYPE_INBOX, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
1629         map.put(TEST_HANDLE_ONE, msg);
1630         msg.localInitiatedSend = false;
1631         mObserver.setMsgListMms(map, true);
1632         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1633 
1634         mObserver.handleMsgListChangesMms();
1635 
1636         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1637         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1638         Assert.assertEquals(
1639                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1640         Assert.assertEquals(
1641                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1642     }
1643 
1644     @Test
handleMsgListChangesMms_withExistingMessage_withNonEqualType_andLocalSendTrue()1645     public void handleMsgListChangesMms_withExistingMessage_withNonEqualType_andLocalSendTrue() {
1646         MatrixCursor cursor =
1647                 new MatrixCursor(
1648                         new String[] {
1649                             Mms._ID, Mms.MESSAGE_BOX, Mms.MESSAGE_TYPE, Mms.THREAD_ID, Mms.READ
1650                         });
1651         cursor.addRow(
1652                 new Object[] {
1653                     TEST_HANDLE_ONE,
1654                     TEST_MMS_TYPE_ALL,
1655                     TEST_MMS_MTYPE,
1656                     TEST_THREAD_ID,
1657                     TEST_READ_FLAG_ONE
1658                 });
1659         doReturn(cursor)
1660                 .when(mMapMethodProxy)
1661                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1662 
1663         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1664         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMms()
1665         // function for an existing message
1666         BluetoothMapContentObserver.Msg msg =
1667                 new BluetoothMapContentObserver.Msg(
1668                         TEST_HANDLE_ONE, TEST_MMS_TYPE_INBOX, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
1669         map.put(TEST_HANDLE_ONE, msg);
1670         msg.localInitiatedSend = true;
1671         mObserver.setMsgListMms(map, true);
1672         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1673 
1674         mObserver.handleMsgListChangesMms();
1675 
1676         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1677         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1678         Assert.assertEquals(
1679                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1680         Assert.assertEquals(
1681                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1682     }
1683 
1684     @Test
handleMsgListChangesMms_withExistingMessage_withDeletedThreadId()1685     public void handleMsgListChangesMms_withExistingMessage_withDeletedThreadId() {
1686         MatrixCursor cursor =
1687                 new MatrixCursor(
1688                         new String[] {
1689                             Mms._ID, Mms.MESSAGE_BOX, Mms.MESSAGE_TYPE, Mms.THREAD_ID, Mms.READ
1690                         });
1691         cursor.addRow(
1692                 new Object[] {
1693                     TEST_HANDLE_ONE,
1694                     TEST_MMS_TYPE_ALL,
1695                     TEST_MMS_MTYPE,
1696                     BluetoothMapContentObserver.DELETED_THREAD_ID,
1697                     TEST_READ_FLAG_ONE
1698                 });
1699         doReturn(cursor)
1700                 .when(mMapMethodProxy)
1701                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1702 
1703         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1704         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMms()
1705         // function for an existing message
1706         BluetoothMapContentObserver.Msg msg =
1707                 new BluetoothMapContentObserver.Msg(
1708                         TEST_HANDLE_ONE, TEST_MMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
1709         map.put(TEST_HANDLE_ONE, msg);
1710         msg.localInitiatedSend = true;
1711         mObserver.setMsgListMms(map, true);
1712         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1713 
1714         mObserver.handleMsgListChangesMms();
1715 
1716         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1717         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1718         Assert.assertEquals(
1719                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId,
1720                 BluetoothMapContentObserver.DELETED_THREAD_ID);
1721         Assert.assertEquals(
1722                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1723     }
1724 
1725     @Test
handleMsgListChangesMms_withExistingMessage_withUndeletedThreadId()1726     public void handleMsgListChangesMms_withExistingMessage_withUndeletedThreadId() {
1727         int undeletedThreadId = 0;
1728         MatrixCursor cursor =
1729                 new MatrixCursor(
1730                         new String[] {
1731                             Mms._ID, Mms.MESSAGE_BOX, Mms.MESSAGE_TYPE, Mms.THREAD_ID, Mms.READ
1732                         });
1733         cursor.addRow(
1734                 new Object[] {
1735                     TEST_HANDLE_ONE,
1736                     TEST_MMS_TYPE_ALL,
1737                     TEST_MMS_MTYPE,
1738                     undeletedThreadId,
1739                     TEST_READ_FLAG_ONE
1740                 });
1741         doReturn(cursor)
1742                 .when(mMapMethodProxy)
1743                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1744 
1745         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1746         // Giving the same handle for msg below and cursor above makes handleMsgListChangesMms()
1747         // function for an existing message
1748         BluetoothMapContentObserver.Msg msg =
1749                 new BluetoothMapContentObserver.Msg(
1750                         TEST_HANDLE_ONE, TEST_MMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
1751         map.put(TEST_HANDLE_ONE, msg);
1752         msg.localInitiatedSend = true;
1753         mObserver.setMsgListMms(map, true);
1754         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1755 
1756         mObserver.handleMsgListChangesMms();
1757 
1758         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1759         Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL);
1760         Assert.assertEquals(
1761                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, undeletedThreadId);
1762         Assert.assertEquals(
1763                 mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1764     }
1765 
1766     @Test
handleMsgListChangesSms_withNonExistingMessage_andVersion11()1767     public void handleMsgListChangesSms_withNonExistingMessage_andVersion11() {
1768         MatrixCursor cursor =
1769                 new MatrixCursor(
1770                         new String[] {
1771                             Sms._ID,
1772                             Sms.TYPE,
1773                             Sms.THREAD_ID,
1774                             Sms.READ,
1775                             Sms.DATE,
1776                             Sms.BODY,
1777                             Sms.ADDRESS,
1778                             ContactsContract.Contacts.DISPLAY_NAME
1779                         });
1780         cursor.addRow(
1781                 new Object[] {
1782                     TEST_HANDLE_ONE,
1783                     TEST_SMS_TYPE_INBOX,
1784                     TEST_THREAD_ID,
1785                     TEST_READ_FLAG_ONE,
1786                     TEST_DATE_MS,
1787                     TEST_SUBJECT,
1788                     TEST_ADDRESS,
1789                     null
1790                 });
1791         doReturn(cursor)
1792                 .when(mMapMethodProxy)
1793                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1794 
1795         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1796         // Giving a different handle for msg below and cursor above makes handleMsgListChangesSms()
1797         // function for a non-existing message
1798         BluetoothMapContentObserver.Msg msg =
1799                 new BluetoothMapContentObserver.Msg(
1800                         TEST_HANDLE_TWO, TEST_SMS_TYPE_ALL, TEST_READ_FLAG_ONE);
1801         map.put(TEST_HANDLE_TWO, msg);
1802         mObserver.setMsgListSms(map, true);
1803         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
1804 
1805         mObserver.handleMsgListChangesSms();
1806 
1807         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1808         Assert.assertEquals(
1809                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_INBOX);
1810         Assert.assertEquals(
1811                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1812         Assert.assertEquals(
1813                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1814     }
1815 
1816     @Test
handleMsgListChangesSms_withNonExistingMessage_andVersion12()1817     public void handleMsgListChangesSms_withNonExistingMessage_andVersion12() {
1818         MatrixCursor cursor =
1819                 new MatrixCursor(
1820                         new String[] {
1821                             Sms._ID,
1822                             Sms.TYPE,
1823                             Sms.THREAD_ID,
1824                             Sms.READ,
1825                             Sms.DATE,
1826                             Sms.BODY,
1827                             Sms.ADDRESS
1828                         });
1829         cursor.addRow(
1830                 new Object[] {
1831                     TEST_HANDLE_ONE,
1832                     TEST_SMS_TYPE_ALL,
1833                     TEST_THREAD_ID,
1834                     TEST_READ_FLAG_ONE,
1835                     TEST_DATE_MS,
1836                     "",
1837                     null
1838                 });
1839         doReturn(cursor)
1840                 .when(mMapMethodProxy)
1841                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1842 
1843         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1844         // Giving a different handle for msg below and cursor above makes handleMsgListChangesSms()
1845         // function for a non-existing message
1846         BluetoothMapContentObserver.Msg msg =
1847                 new BluetoothMapContentObserver.Msg(
1848                         TEST_HANDLE_TWO, TEST_SMS_TYPE_INBOX, TEST_READ_FLAG_ONE);
1849         map.put(TEST_HANDLE_TWO, msg);
1850         mObserver.setMsgListSms(map, true);
1851         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1852 
1853         mObserver.handleMsgListChangesSms();
1854 
1855         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1856         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL);
1857         Assert.assertEquals(
1858                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1859         Assert.assertEquals(
1860                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1861     }
1862 
1863     @Test
handleMsgListChangesSms_withNonExistingOldMessage_andVersion12()1864     public void handleMsgListChangesSms_withNonExistingOldMessage_andVersion12() {
1865         mSetFlagsRule.disableFlags(Flags.FLAG_MAP_LIMIT_NOTIFICATION);
1866         Calendar cal = Calendar.getInstance();
1867         cal.add(Calendar.YEAR, -1);
1868         cal.add(Calendar.DATE, -1);
1869 
1870         MatrixCursor cursor =
1871                 new MatrixCursor(
1872                         new String[] {
1873                             Sms._ID,
1874                             Sms.TYPE,
1875                             Sms.THREAD_ID,
1876                             Sms.READ,
1877                             Sms.DATE,
1878                             Sms.BODY,
1879                             Sms.ADDRESS
1880                         });
1881         cursor.addRow(
1882                 new Object[] {
1883                     TEST_HANDLE_ONE,
1884                     TEST_SMS_TYPE_ALL,
1885                     TEST_THREAD_ID,
1886                     TEST_READ_FLAG_ONE,
1887                     cal.getTimeInMillis(),
1888                     "",
1889                     null
1890                 });
1891         doReturn(cursor)
1892                 .when(mMapMethodProxy)
1893                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1894 
1895         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1896         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1897         // function for a non-existing message
1898         BluetoothMapContentObserver.Msg msg =
1899                 new BluetoothMapContentObserver.Msg(
1900                         TEST_HANDLE_TWO, TEST_SMS_TYPE_INBOX, TEST_READ_FLAG_ONE);
1901         map.put(TEST_HANDLE_TWO, msg);
1902         mObserver.setMsgListSms(map, true);
1903         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1904 
1905         mObserver.handleMsgListChangesSms();
1906 
1907         Assert.assertEquals(null, mObserver.getMsgListSms().get(TEST_HANDLE_ONE));
1908     }
1909 
1910     @Test
handleMsgListChangesSms_withNonExistingOldMessage_andVersion12_andOneWeekLimit()1911     public void handleMsgListChangesSms_withNonExistingOldMessage_andVersion12_andOneWeekLimit() {
1912         mSetFlagsRule.enableFlags(Flags.FLAG_MAP_LIMIT_NOTIFICATION);
1913         Instant oldInstant =
1914                 Instant.now()
1915                         .minus(BluetoothMapContentObserver.NEW_MESSAGE_DURATION_FOR_NOTIFICATION);
1916 
1917         MatrixCursor cursor =
1918                 new MatrixCursor(
1919                         new String[] {
1920                             Sms._ID,
1921                             Sms.TYPE,
1922                             Sms.THREAD_ID,
1923                             Sms.READ,
1924                             Sms.DATE,
1925                             Sms.BODY,
1926                             Sms.ADDRESS
1927                         });
1928         cursor.addRow(
1929                 new Object[] {
1930                     TEST_HANDLE_ONE,
1931                     TEST_SMS_TYPE_ALL,
1932                     TEST_THREAD_ID,
1933                     TEST_READ_FLAG_ONE,
1934                     oldInstant.toEpochMilli(),
1935                     "",
1936                     null
1937                 });
1938         doReturn(cursor)
1939                 .when(mMapMethodProxy)
1940                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1941 
1942         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1943         // Giving a different handle for msg below and cursor above makes handleMsgListChangesMms()
1944         // function for a non-existing message
1945         BluetoothMapContentObserver.Msg msg =
1946                 new BluetoothMapContentObserver.Msg(
1947                         TEST_HANDLE_TWO, TEST_SMS_TYPE_INBOX, TEST_READ_FLAG_ONE);
1948         map.put(TEST_HANDLE_TWO, msg);
1949         mObserver.setMsgListSms(map, true);
1950         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
1951 
1952         mObserver.handleMsgListChangesSms();
1953 
1954         Assert.assertEquals(null, mObserver.getMsgListSms().get(TEST_HANDLE_ONE));
1955     }
1956 
1957     @Test
handleMsgListChangesSms_withNonExistingMessage_andVersion10()1958     public void handleMsgListChangesSms_withNonExistingMessage_andVersion10() {
1959         MatrixCursor cursor =
1960                 new MatrixCursor(new String[] {Sms._ID, Sms.TYPE, Sms.THREAD_ID, Sms.READ});
1961         cursor.addRow(
1962                 new Object[] {
1963                     TEST_HANDLE_ONE, TEST_SMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ONE
1964                 });
1965         doReturn(cursor)
1966                 .when(mMapMethodProxy)
1967                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
1968 
1969         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
1970         // Giving a different handle for msg below and cursor above makes handleMsgListChangesSms()
1971         // function for a non-existing message
1972         BluetoothMapContentObserver.Msg msg =
1973                 new BluetoothMapContentObserver.Msg(
1974                         TEST_HANDLE_TWO, TEST_SMS_TYPE_INBOX, TEST_READ_FLAG_ONE);
1975         map.put(TEST_HANDLE_TWO, msg);
1976         mObserver.setMsgListSms(map, true);
1977         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V10;
1978 
1979         mObserver.handleMsgListChangesSms();
1980 
1981         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
1982         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL);
1983         Assert.assertEquals(
1984                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
1985         Assert.assertEquals(
1986                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
1987     }
1988 
1989     @Test
handleMsgListChangesSms_withExistingMessage_withNonEqualType()1990     public void handleMsgListChangesSms_withExistingMessage_withNonEqualType() {
1991         MatrixCursor cursor =
1992                 new MatrixCursor(new String[] {Sms._ID, Sms.TYPE, Sms.THREAD_ID, Sms.READ});
1993         cursor.addRow(
1994                 new Object[] {
1995                     TEST_HANDLE_ONE, TEST_SMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ONE
1996                 });
1997         doReturn(cursor)
1998                 .when(mMapMethodProxy)
1999                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
2000 
2001         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
2002         // Giving the same handle for msg below and cursor above makes handleMsgListChangesSms()
2003         // function for an existing message
2004         BluetoothMapContentObserver.Msg msg =
2005                 new BluetoothMapContentObserver.Msg(
2006                         TEST_HANDLE_ONE, TEST_SMS_TYPE_INBOX, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
2007         map.put(TEST_HANDLE_ONE, msg);
2008         mObserver.setMsgListSms(map, true);
2009         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2010 
2011         mObserver.handleMsgListChangesSms();
2012 
2013         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
2014         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL);
2015         Assert.assertEquals(
2016                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID);
2017         Assert.assertEquals(
2018                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
2019     }
2020 
2021     @Test
handleMsgListChangesSms_withExistingMessage_withDeletedThreadId()2022     public void handleMsgListChangesSms_withExistingMessage_withDeletedThreadId() {
2023         MatrixCursor cursor =
2024                 new MatrixCursor(new String[] {Sms._ID, Sms.TYPE, Sms.THREAD_ID, Sms.READ});
2025         cursor.addRow(
2026                 new Object[] {
2027                     TEST_HANDLE_ONE,
2028                     TEST_SMS_TYPE_ALL,
2029                     BluetoothMapContentObserver.DELETED_THREAD_ID,
2030                     TEST_READ_FLAG_ONE
2031                 });
2032         doReturn(cursor)
2033                 .when(mMapMethodProxy)
2034                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
2035 
2036         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
2037         // Giving the same handle for msg below and cursor above makes handleMsgListChangesSms()
2038         // function for an existing message
2039         BluetoothMapContentObserver.Msg msg =
2040                 new BluetoothMapContentObserver.Msg(
2041                         TEST_HANDLE_ONE, TEST_SMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
2042         map.put(TEST_HANDLE_ONE, msg);
2043         mObserver.setMsgListSms(map, true);
2044         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2045 
2046         mObserver.handleMsgListChangesSms();
2047 
2048         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
2049         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL);
2050         Assert.assertEquals(
2051                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId,
2052                 BluetoothMapContentObserver.DELETED_THREAD_ID);
2053         Assert.assertEquals(
2054                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
2055     }
2056 
2057     @Test
handleMsgListChangesSms_withExistingMessage_withUndeletedThreadId()2058     public void handleMsgListChangesSms_withExistingMessage_withUndeletedThreadId() {
2059         int undeletedThreadId = 0;
2060         MatrixCursor cursor =
2061                 new MatrixCursor(new String[] {Sms._ID, Sms.TYPE, Sms.THREAD_ID, Sms.READ});
2062         cursor.addRow(
2063                 new Object[] {
2064                     TEST_HANDLE_ONE, TEST_SMS_TYPE_ALL, undeletedThreadId, TEST_READ_FLAG_ONE
2065                 });
2066         doReturn(cursor)
2067                 .when(mMapMethodProxy)
2068                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
2069 
2070         Map<Long, BluetoothMapContentObserver.Msg> map = new HashMap<>();
2071         // Giving the same handle for msg below and cursor above makes handleMsgListChangesSms()
2072         // function for an existing message
2073         BluetoothMapContentObserver.Msg msg =
2074                 new BluetoothMapContentObserver.Msg(
2075                         TEST_HANDLE_ONE, TEST_SMS_TYPE_ALL, TEST_THREAD_ID, TEST_READ_FLAG_ZERO);
2076         map.put(TEST_HANDLE_ONE, msg);
2077         mObserver.setMsgListSms(map, true);
2078         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2079 
2080         mObserver.handleMsgListChangesSms();
2081 
2082         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE);
2083         Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL);
2084         Assert.assertEquals(
2085                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, undeletedThreadId);
2086         Assert.assertEquals(
2087                 mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE);
2088     }
2089 
2090     @Test
handleMmsSendIntent_withMnsClientNotConnected()2091     public void handleMmsSendIntent_withMnsClientNotConnected() {
2092         when(mClient.isConnected()).thenReturn(false);
2093 
2094         Assert.assertFalse(mObserver.handleMmsSendIntent(mContext, mIntent));
2095     }
2096 
2097     @Test
handleMmsSendIntent_withInvalidHandle()2098     public void handleMmsSendIntent_withInvalidHandle() {
2099         when(mClient.isConnected()).thenReturn(true);
2100         doReturn((long) -1)
2101                 .when(mIntent)
2102                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2103 
2104         Assert.assertTrue(mObserver.handleMmsSendIntent(mContext, mIntent));
2105     }
2106 
2107     @Test
handleMmsSendIntent_withActivityResultOk()2108     public void handleMmsSendIntent_withActivityResultOk() {
2109         when(mClient.isConnected()).thenReturn(true);
2110         doReturn(TEST_HANDLE_ONE)
2111                 .when(mIntent)
2112                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2113         doReturn(Activity.RESULT_OK)
2114                 .when(mIntent)
2115                 .getIntExtra(
2116                         BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_RESULT,
2117                         Activity.RESULT_CANCELED);
2118         doReturn(0)
2119                 .when(mIntent)
2120                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2121         mObserver.mObserverRegistered = true;
2122 
2123         Assert.assertTrue(mObserver.handleMmsSendIntent(mContext, mIntent));
2124     }
2125 
2126     @Test
handleMmsSendIntent_withActivityResultFirstUser()2127     public void handleMmsSendIntent_withActivityResultFirstUser() {
2128         when(mClient.isConnected()).thenReturn(true);
2129         doReturn(TEST_HANDLE_ONE)
2130                 .when(mIntent)
2131                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2132         doReturn(Activity.RESULT_FIRST_USER)
2133                 .when(mIntent)
2134                 .getIntExtra(
2135                         BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_RESULT,
2136                         Activity.RESULT_CANCELED);
2137         mObserver.mObserverRegistered = true;
2138         doReturn(TEST_PLACEHOLDER_INT)
2139                 .when(mMapMethodProxy)
2140                 .contentResolverDelete(any(), any(), any(), any());
2141 
2142         Assert.assertTrue(mObserver.handleMmsSendIntent(mContext, mIntent));
2143     }
2144 
2145     @Test
actionMessageSentDisconnected_withTypeMms()2146     public void actionMessageSentDisconnected_withTypeMms() {
2147         Map<Long, BluetoothMapContentObserver.Msg> mmsMsgList = new HashMap<>();
2148         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
2149         mmsMsgList.put(TEST_HANDLE_ONE, msg);
2150         doReturn(1)
2151                 .when(mIntent)
2152                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2153         doReturn((long) -1)
2154                 .when(mIntent)
2155                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2156         // This mock sets type to MMS
2157         doReturn(4)
2158                 .when(mIntent)
2159                 .getIntExtra(
2160                         BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE,
2161                         TYPE.NONE.ordinal());
2162 
2163         mObserver.actionMessageSentDisconnected(mContext, mIntent, 1);
2164 
2165         Assert.assertTrue(mmsMsgList.containsKey(TEST_HANDLE_ONE));
2166     }
2167 
2168     @Test
actionMessageSentDisconnected_withTypeEmail()2169     public void actionMessageSentDisconnected_withTypeEmail() {
2170         // This sets to null uriString
2171         doReturn(null)
2172                 .when(mIntent)
2173                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2174         doReturn(1)
2175                 .when(mIntent)
2176                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2177         // This mock sets type to Email
2178         doReturn(1)
2179                 .when(mIntent)
2180                 .getIntExtra(
2181                         BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE,
2182                         TYPE.NONE.ordinal());
2183         clearInvocations(mContext);
2184 
2185         mObserver.actionMessageSentDisconnected(mContext, mIntent, Activity.RESULT_FIRST_USER);
2186 
2187         verify(mContext, never()).getContentResolver();
2188     }
2189 
2190     @Test
actionMmsSent_withInvalidHandle()2191     public void actionMmsSent_withInvalidHandle() {
2192         Map<Long, BluetoothMapContentObserver.Msg> mmsMsgList = new HashMap<>();
2193         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
2194         mmsMsgList.put(TEST_HANDLE_ONE, msg);
2195         doReturn(1)
2196                 .when(mIntent)
2197                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2198         doReturn((long) -1)
2199                 .when(mIntent)
2200                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2201 
2202         mObserver.actionMmsSent(mContext, mIntent, 1, mmsMsgList);
2203 
2204         Assert.assertTrue(mmsMsgList.containsKey(TEST_HANDLE_ONE));
2205     }
2206 
2207     @Test
actionMmsSent_withTransparency()2208     public void actionMmsSent_withTransparency() {
2209         Map<Long, BluetoothMapContentObserver.Msg> mmsMsgList = new HashMap<>();
2210         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
2211         mmsMsgList.put(TEST_HANDLE_ONE, msg);
2212         // This mock turns on the transparent flag
2213         doReturn(1)
2214                 .when(mIntent)
2215                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2216         doReturn(TEST_HANDLE_ONE)
2217                 .when(mIntent)
2218                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2219         doReturn(TEST_PLACEHOLDER_INT)
2220                 .when(mMapMethodProxy)
2221                 .contentResolverDelete(any(), any(), any(), any());
2222 
2223         mObserver.actionMmsSent(mContext, mIntent, 1, mmsMsgList);
2224 
2225         Assert.assertFalse(mmsMsgList.containsKey(TEST_HANDLE_ONE));
2226     }
2227 
2228     @Test
actionMmsSent_withActivityResultOk()2229     public void actionMmsSent_withActivityResultOk() {
2230         Map<Long, BluetoothMapContentObserver.Msg> mmsMsgList = new HashMap<>();
2231         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
2232         mmsMsgList.put(TEST_HANDLE_ONE, msg);
2233         // This mock turns off the transparent flag
2234         doReturn(0)
2235                 .when(mIntent)
2236                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2237         doReturn(TEST_HANDLE_ONE)
2238                 .when(mIntent)
2239                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2240 
2241         MatrixCursor cursor = new MatrixCursor(new String[] {});
2242         doReturn(cursor)
2243                 .when(mMapMethodProxy)
2244                 .contentResolverQuery(any(), any(), any(), any(), any(), any());
2245         doReturn(TEST_PLACEHOLDER_INT)
2246                 .when(mMapMethodProxy)
2247                 .contentResolverUpdate(any(), any(), any(), any(), any());
2248 
2249         mObserver.actionMmsSent(mContext, mIntent, Activity.RESULT_OK, mmsMsgList);
2250 
2251         Assert.assertTrue(mmsMsgList.containsKey(TEST_HANDLE_ONE));
2252     }
2253 
2254     @Test
actionMmsSent_withActivityResultFirstUser()2255     public void actionMmsSent_withActivityResultFirstUser() {
2256         Map<Long, BluetoothMapContentObserver.Msg> mmsMsgList = new HashMap<>();
2257         BluetoothMapContentObserver.Msg msg = createSimpleMsg();
2258         mmsMsgList.put(TEST_HANDLE_ONE, msg);
2259         // This mock turns off the transparent flag
2260         doReturn(0)
2261                 .when(mIntent)
2262                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2263         doReturn(TEST_HANDLE_ONE)
2264                 .when(mIntent)
2265                 .getLongExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_HANDLE, -1);
2266 
2267         mObserver.actionMmsSent(mContext, mIntent, Activity.RESULT_FIRST_USER, mmsMsgList);
2268 
2269         Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_OUTBOX);
2270     }
2271 
2272     @Test
actionSmsSentDisconnected_withNullUriString()2273     public void actionSmsSentDisconnected_withNullUriString() {
2274         // This sets to null uriString
2275         doReturn(null)
2276                 .when(mIntent)
2277                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2278         doReturn(1)
2279                 .when(mIntent)
2280                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2281 
2282         clearInvocations(mContext);
2283         mObserver.actionSmsSentDisconnected(mContext, mIntent, Activity.RESULT_FIRST_USER);
2284 
2285         verify(mContext, never()).getContentResolver();
2286     }
2287 
2288     @Test
actionSmsSentDisconnected_withActivityResultOk_andTransparentOff()2289     public void actionSmsSentDisconnected_withActivityResultOk_andTransparentOff() {
2290         doReturn(TEST_URI_STR)
2291                 .when(mIntent)
2292                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2293         // This mock turns off the transparent flag
2294         doReturn(0)
2295                 .when(mIntent)
2296                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2297         doReturn(TEST_PLACEHOLDER_INT)
2298                 .when(mMapMethodProxy)
2299                 .contentResolverUpdate(any(), any(), any(), any(), any());
2300 
2301         clearInvocations(mContext);
2302         mObserver.actionSmsSentDisconnected(mContext, mIntent, Activity.RESULT_OK);
2303 
2304         verify(mContext).getContentResolver();
2305     }
2306 
2307     @Test
actionSmsSentDisconnected_withActivityResultOk_andTransparentOn()2308     public void actionSmsSentDisconnected_withActivityResultOk_andTransparentOn() {
2309         doReturn(TEST_URI_STR)
2310                 .when(mIntent)
2311                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2312         // This mock turns on the transparent flag
2313         doReturn(1)
2314                 .when(mIntent)
2315                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2316         doReturn(TEST_PLACEHOLDER_INT)
2317                 .when(mMapMethodProxy)
2318                 .contentResolverDelete(any(), any(), any(), any());
2319 
2320         clearInvocations(mContext);
2321         mObserver.actionSmsSentDisconnected(mContext, mIntent, Activity.RESULT_OK);
2322 
2323         verify(mContext).getContentResolver();
2324     }
2325 
2326     @Test
actionSmsSentDisconnected_withActivityResultFirstUser_andTransparentOff()2327     public void actionSmsSentDisconnected_withActivityResultFirstUser_andTransparentOff() {
2328         doReturn(TEST_URI_STR)
2329                 .when(mIntent)
2330                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2331         // This mock turns off the transparent flag
2332         doReturn(0)
2333                 .when(mIntent)
2334                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2335         doReturn(TEST_PLACEHOLDER_INT)
2336                 .when(mMapMethodProxy)
2337                 .contentResolverUpdate(any(), any(), any(), any(), any());
2338 
2339         clearInvocations(mContext);
2340         mObserver.actionSmsSentDisconnected(mContext, mIntent, Activity.RESULT_OK);
2341 
2342         verify(mContext).getContentResolver();
2343     }
2344 
2345     @Test
actionSmsSentDisconnected_withActivityResultFirstUser_andTransparentOn()2346     public void actionSmsSentDisconnected_withActivityResultFirstUser_andTransparentOn() {
2347         doReturn(TEST_URI_STR)
2348                 .when(mIntent)
2349                 .getStringExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_URI);
2350         // This mock turns on the transparent flag
2351         doReturn(1)
2352                 .when(mIntent)
2353                 .getIntExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_TRANSPARENT, 0);
2354         doReturn(null).when(mContext).getContentResolver();
2355 
2356         clearInvocations(mContext);
2357         mObserver.actionSmsSentDisconnected(mContext, mIntent, Activity.RESULT_OK);
2358 
2359         verify(mContext).getContentResolver();
2360     }
2361 
2362     @Test
handleContactListChanges_withNullContactForUci()2363     public void handleContactListChanges_withNullContactForUci() throws Exception {
2364         Uri uri = mock(Uri.class);
2365         mObserver.mAuthority = TEST_AUTHORITY;
2366         when(uri.getAuthority()).thenReturn(TEST_AUTHORITY);
2367 
2368         MatrixCursor cursor =
2369                 new MatrixCursor(
2370                         new String[] {
2371                             BluetoothMapContract.ConvoContactColumns.CONVO_ID,
2372                             BluetoothMapContract.ConvoContactColumns.NAME,
2373                             BluetoothMapContract.ConvoContactColumns.NICKNAME,
2374                             BluetoothMapContract.ConvoContactColumns.X_BT_UID,
2375                             BluetoothMapContract.ConvoContactColumns.CHAT_STATE,
2376                             BluetoothMapContract.ConvoContactColumns.UCI,
2377                             BluetoothMapContract.ConvoContactColumns.LAST_ACTIVE,
2378                             BluetoothMapContract.ConvoContactColumns.PRESENCE_STATE,
2379                             BluetoothMapContract.ConvoContactColumns.STATUS_TEXT,
2380                             BluetoothMapContract.ConvoContactColumns.PRIORITY,
2381                             BluetoothMapContract.ConvoContactColumns.LAST_ONLINE
2382                         });
2383         cursor.addRow(
2384                 new Object[] {
2385                     TEST_CONVO_ID,
2386                     TEST_NAME,
2387                     TEST_DISPLAY_NAME,
2388                     TEST_BT_UID,
2389                     TEST_CHAT_STATE,
2390                     TEST_UCI,
2391                     TEST_LAST_ACTIVITY,
2392                     TEST_PRESENCE_STATE,
2393                     TEST_STATUS_TEXT,
2394                     TEST_PRIORITY,
2395                     TEST_LAST_ONLINE
2396                 });
2397         doReturn(cursor).when(mProviderClient).query(any(), any(), any(), any(), any());
2398 
2399         Map<String, BluetoothMapConvoContactElement> map = new HashMap<>();
2400         map.put(TEST_UCI_DIFFERENT, null);
2401         mObserver.setContactList(map, true);
2402         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2403 
2404         mObserver.handleContactListChanges(uri);
2405 
2406         BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI);
2407         final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
2408         Assert.assertEquals(contactElement.getContactId(), TEST_UCI);
2409         Assert.assertEquals(contactElement.getName(), TEST_NAME);
2410         Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME);
2411         Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID);
2412         Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE);
2413         Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT);
2414         Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE);
2415         Assert.assertEquals(
2416                 contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY));
2417         Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY);
2418     }
2419 
2420     @Test
handleContactListChanges_withNonNullContactForUci()2421     public void handleContactListChanges_withNonNullContactForUci() throws Exception {
2422         Uri uri = mock(Uri.class);
2423         mObserver.mAuthority = TEST_AUTHORITY;
2424         when(uri.getAuthority()).thenReturn(TEST_AUTHORITY);
2425 
2426         MatrixCursor cursor =
2427                 new MatrixCursor(
2428                         new String[] {
2429                             BluetoothMapContract.ConvoContactColumns.CONVO_ID,
2430                             BluetoothMapContract.ConvoContactColumns.NAME,
2431                             BluetoothMapContract.ConvoContactColumns.NICKNAME,
2432                             BluetoothMapContract.ConvoContactColumns.X_BT_UID,
2433                             BluetoothMapContract.ConvoContactColumns.CHAT_STATE,
2434                             BluetoothMapContract.ConvoContactColumns.UCI,
2435                             BluetoothMapContract.ConvoContactColumns.LAST_ACTIVE,
2436                             BluetoothMapContract.ConvoContactColumns.PRESENCE_STATE,
2437                             BluetoothMapContract.ConvoContactColumns.STATUS_TEXT,
2438                             BluetoothMapContract.ConvoContactColumns.PRIORITY,
2439                             BluetoothMapContract.ConvoContactColumns.LAST_ONLINE
2440                         });
2441         cursor.addRow(
2442                 new Object[] {
2443                     TEST_CONVO_ID,
2444                     TEST_NAME,
2445                     TEST_DISPLAY_NAME,
2446                     TEST_BT_UID,
2447                     TEST_CHAT_STATE,
2448                     TEST_UCI,
2449                     TEST_LAST_ACTIVITY,
2450                     TEST_PRESENCE_STATE,
2451                     TEST_STATUS_TEXT,
2452                     TEST_PRIORITY,
2453                     TEST_LAST_ONLINE
2454                 });
2455         doReturn(cursor).when(mProviderClient).query(any(), any(), any(), any(), any());
2456 
2457         Map<String, BluetoothMapConvoContactElement> map = new HashMap<>();
2458         map.put(TEST_UCI_DIFFERENT, null);
2459         BluetoothMapConvoContactElement contact =
2460                 new BluetoothMapConvoContactElement(
2461                         TEST_UCI,
2462                         TEST_NAME,
2463                         TEST_DISPLAY_NAME,
2464                         TEST_STATUS_TEXT_DIFFERENT,
2465                         TEST_PRESENCE_STATE_DIFFERENT,
2466                         TEST_LAST_ACTIVITY,
2467                         TEST_CHAT_STATE_DIFFERENT,
2468                         TEST_PRIORITY,
2469                         TEST_BT_UID);
2470         map.put(TEST_UCI, contact);
2471         mObserver.setContactList(map, true);
2472         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
2473         when(mTelephonyManager.getLine1Number()).thenReturn("");
2474 
2475         mObserver.handleContactListChanges(uri);
2476 
2477         BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI);
2478         final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
2479         Assert.assertEquals(contactElement.getContactId(), TEST_UCI);
2480         Assert.assertEquals(contactElement.getName(), TEST_NAME);
2481         Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME);
2482         Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID);
2483         Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE);
2484         Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT);
2485         Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE);
2486         Assert.assertEquals(
2487                 contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY));
2488         Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY);
2489     }
2490 
2491     @Test
handleContactListChanges_withMapEventReportVersion11()2492     public void handleContactListChanges_withMapEventReportVersion11() throws Exception {
2493         Uri uri = mock(Uri.class);
2494         mObserver.mAuthority = TEST_AUTHORITY;
2495         when(uri.getAuthority()).thenReturn(TEST_AUTHORITY);
2496         mObserver.mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
2497 
2498         mObserver.handleContactListChanges(uri);
2499 
2500         verify(mProviderClient, never()).query(any(), any(), any(), any(), any(), any());
2501     }
2502 
createSimpleMsg()2503     private BluetoothMapContentObserver.Msg createSimpleMsg() {
2504         return new BluetoothMapContentObserver.Msg(1, 1L, 1);
2505     }
2506 
createMsgWithTypeAndThreadId(int type, int threadId)2507     private BluetoothMapContentObserver.Msg createMsgWithTypeAndThreadId(int type, int threadId) {
2508         return new BluetoothMapContentObserver.Msg(1, type, threadId, 1);
2509     }
2510 
setFolderStructureWithTelecomAndMsg( BluetoothMapFolderElement folderElement, String folderName, long folderId)2511     private void setFolderStructureWithTelecomAndMsg(
2512             BluetoothMapFolderElement folderElement, String folderName, long folderId) {
2513         folderElement.addFolder("telecom");
2514         folderElement.getSubFolder("telecom").addFolder("msg");
2515         BluetoothMapFolderElement subFolder =
2516                 folderElement.getSubFolder("telecom").getSubFolder("msg").addFolder(folderName);
2517         subFolder.setFolderId(folderId);
2518     }
2519 }
2520