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(); + } +}