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