diff --git a/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java b/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java
index 932e2dd485a5b0901ce27eac9049d5f2eb2a23e5..b02d14819a16e32b351e12c6a0ee2b074935a6b4 100644
--- a/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java
+++ b/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java
@@ -26,6 +26,9 @@ import android.provider.Telephony.CanonicalAddressesColumns;
 import android.provider.Telephony.MmsSms;
 import android.util.Log;
 
+import com.android.bluetooth.BluetoothMethodProxy;
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.regex.Pattern;
@@ -40,7 +43,8 @@ public class SmsMmsContacts {
     private static final String TAG = "SmsMmsContacts";
 
     private HashMap<Long, String> mPhoneNumbers = null;
-    private final HashMap<String, MapContact> mNames = new HashMap<String, MapContact>(10);
+    @VisibleForTesting
+    final HashMap<String, MapContact> mNames = new HashMap<String, MapContact>(10);
 
     private static final Uri ADDRESS_URI =
             MmsSms.CONTENT_URI.buildUpon().appendPath("canonical-addresses").build();
@@ -78,7 +82,8 @@ public class SmsMmsContacts {
 
     public static String getPhoneNumberUncached(ContentResolver resolver, long id) {
         String where = CanonicalAddressesColumns._ID + " = " + id;
-        Cursor c = resolver.query(ADDRESS_URI, ADDRESS_PROJECTION, where, null, null);
+        Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(resolver, ADDRESS_URI,
+                ADDRESS_PROJECTION, where, null, null);
         try {
             if (c != null) {
                 if (c.moveToPosition(0)) {
@@ -111,8 +116,10 @@ public class SmsMmsContacts {
      * a new query.
      * @param resolver the ContantResolver to be used.
      */
-    private void fillPhoneCache(ContentResolver resolver) {
-        Cursor c = resolver.query(ADDRESS_URI, ADDRESS_PROJECTION, null, null, null);
+    @VisibleForTesting
+    void fillPhoneCache(ContentResolver resolver) {
+        Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(resolver, ADDRESS_URI,
+                ADDRESS_PROJECTION, null, null, null);
         if (mPhoneNumbers == null) {
             int size = 0;
             if (c != null) {
@@ -184,7 +191,8 @@ public class SmsMmsContacts {
             selectionArgs = new String[]{"%" + contactNameFilter.replace("*", "%") + "%"};
         }
 
-        Cursor c = resolver.query(uri, CONTACT_PROJECTION, selection, selectionArgs, null);
+        Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(resolver, uri,
+                CONTACT_PROJECTION, selection, selectionArgs, null);
         try {
             if (c != null && c.getCount() >= 1) {
                 c.moveToFirst();
diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9195ead8051c7f8ed0eaae67adf6491bb957549e
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bluetooth.map;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.bluetooth.SignedLongLong;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MapContactTest {
+    private static final long TEST_NON_ZERO_ID = 1;
+    private static final long TEST_ZERO_ID = 0;
+    private static final String TEST_NAME = "test_name";
+
+    @Test
+    public void constructor() {
+        MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.getId()).isEqualTo(TEST_NON_ZERO_ID);
+        assertThat(contact.getName()).isEqualTo(TEST_NAME);
+    }
+
+    @Test
+    public void getXBtUidString_withZeroId() {
+        MapContact contact = MapContact.create(TEST_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.getXBtUidString()).isNull();
+    }
+
+    @Test
+    public void getXBtUidString_withNonZeroId() {
+        MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.getXBtUidString()).isEqualTo(
+                BluetoothMapUtils.getLongLongAsString(TEST_NON_ZERO_ID, 0));
+    }
+
+    @Test
+    public void getXBtUid_withZeroId() {
+        MapContact contact = MapContact.create(TEST_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.getXBtUid()).isNull();
+    }
+
+    @Test
+    public void getXBtUid_withNonZeroId() {
+        MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.getXBtUid()).isEqualTo(new SignedLongLong(TEST_NON_ZERO_ID, 0));
+    }
+
+    @Test
+    public void toString_returnsName() {
+        MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME);
+
+        assertThat(contact.toString()).isEqualTo(TEST_NAME);
+    }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c65053e81c9d17acf9e5b2a11201b8c736e46996
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bluetooth.map;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.ContentResolver;
+import android.database.MatrixCursor;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.bluetooth.BluetoothMethodProxy;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SmsMmsContactsTest {
+    private static final long TEST_ID = 1;
+    private static final String TEST_NAME = "test_name";
+    private static final String TEST_PHONE_NUMBER = "111-1111-1111";
+    private static final String TEST_PHONE = "test_phone";
+    private static final String TEST_CONTACT_NAME_FILTER = "test_contact_name_filter";
+
+    @Mock
+    private ContentResolver mResolver;
+    @Spy
+    private BluetoothMethodProxy mMapMethodProxy = BluetoothMethodProxy.getInstance();
+
+    private SmsMmsContacts mContacts;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy);
+        mContacts = new SmsMmsContacts();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        BluetoothMethodProxy.setInstanceForTesting(null);
+    }
+
+    @Test
+    public void getPhoneNumberUncached_withNonEmptyCursor() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"COL_ARRR_ID", "COL_ADDR_ADDR"});
+        cursor.addRow(new Object[]{null, TEST_PHONE_NUMBER});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        assertThat(SmsMmsContacts.getPhoneNumberUncached(mResolver, TEST_ID)).isEqualTo(
+                TEST_PHONE_NUMBER);
+    }
+
+    @Test
+    public void getPhoneNumberUncached_withEmptyCursor() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        assertThat(SmsMmsContacts.getPhoneNumberUncached(mResolver, TEST_ID)).isNull();
+    }
+
+    @Test
+    public void fillPhoneCache() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"COL_ADDR_ID", "COL_ADDR_ADDR"});
+        cursor.addRow(new Object[]{TEST_ID, TEST_PHONE_NUMBER});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        mContacts.fillPhoneCache(mResolver);
+
+        assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isEqualTo(TEST_PHONE_NUMBER);
+    }
+
+    @Test
+    public void fillPhoneCache_withNonNullPhoneNumbers() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"COL_ADDR_ID", "COL_ADDR_ADDR"});
+        cursor.addRow(new Object[]{TEST_ID, TEST_PHONE_NUMBER});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        mContacts.fillPhoneCache(mResolver);
+        assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isEqualTo(TEST_PHONE_NUMBER);
+        doReturn(null).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+        mContacts.fillPhoneCache(mResolver);
+
+        assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isNull();
+    }
+
+    @Test
+    public void clearCache() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"COL_ADDR_ID", "COL_ADDR_ADDR"});
+        cursor.addRow(new Object[]{TEST_ID, TEST_PHONE_NUMBER});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+        MapContact contact = MapContact.create(TEST_ID, TEST_PHONE);
+
+        mContacts.mNames.put(TEST_PHONE, contact);
+        mContacts.fillPhoneCache(mResolver);
+        assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isEqualTo(TEST_PHONE_NUMBER);
+        mContacts.clearCache();
+
+        doReturn(null).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+        assertThat(mContacts.mNames).isEmpty();
+        assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isEqualTo(null);
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNonNullCursor() {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"COL_CONTACT_ID", "COL_CONTACT_NAME"});
+        cursor.addRow(new Object[]{TEST_ID, TEST_NAME});
+        doReturn(cursor).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        MapContact expected = MapContact.create(TEST_ID, TEST_NAME);
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver,
+                TEST_CONTACT_NAME_FILTER).toString()).isEqualTo(expected.toString());
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNullCursor() {
+        doReturn(null).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver,
+                TEST_CONTACT_NAME_FILTER)).isNull();
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNoParameterForContactNameFilter() {
+        doReturn(null).when(mMapMethodProxy).contentResolverQuery(any(), any(), any(), any(),
+                any(), any());
+
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver)).isNull();
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNonNullContact_andZeroId() {
+        long zeroId = 0;
+        MapContact contact = MapContact.create(zeroId, TEST_PHONE);
+        mContacts.mNames.put(TEST_PHONE, contact);
+
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver,
+                TEST_CONTACT_NAME_FILTER)).isNull();
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNonNullContact_andNullFilter() {
+        MapContact contact = MapContact.create(TEST_ID, TEST_PHONE);
+        mContacts.mNames.put(TEST_PHONE, contact);
+
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver, null)).isEqualTo(
+                contact);
+    }
+
+    @Test
+    public void getContactNameFromPhone_withNonNullContact_andNonMatchingFilter() {
+        MapContact contact = MapContact.create(TEST_ID, TEST_PHONE);
+        mContacts.mNames.put(TEST_PHONE, contact);
+        String nonMatchingFilter = "non_matching_filter";
+
+        assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver,
+                nonMatchingFilter)).isNull();
+    }
+}