blob: 33d3a28e711051fc7fd0493bbec5203ce524c0e5 [file] [log] [blame]
/*
* Copyright (C) 2010 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 android.provider.cts;
import static android.provider.ContactsContract.CommonDataKinds;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.SystemClock;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Callable;
import android.provider.ContactsContract.CommonDataKinds.Contactables;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Contacts.Entity;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
import android.provider.cts.ContactsContract_TestDataBuilder.TestData;
import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
import android.provider.cts.contacts.ContactUtil;
import android.provider.cts.contacts.DataUtil;
import android.provider.cts.contacts.DatabaseAsserts;
import android.provider.cts.contacts.RawContactUtil;
import android.test.InstrumentationTestCase;
import java.util.ArrayList;
public class ContactsContract_DataTest extends InstrumentationTestCase {
private ContentResolver mResolver;
private ContactsContract_TestDataBuilder mBuilder;
static final String[] DATA_PROJECTION = new String[]{
Data._ID,
Data.RAW_CONTACT_ID,
Data.CONTACT_ID,
Data.NAME_RAW_CONTACT_ID,
RawContacts.RAW_CONTACT_IS_USER_PROFILE,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15,
Data.CARRIER_PRESENCE,
Data.DATA_VERSION,
Data.IS_PRIMARY,
Data.IS_SUPER_PRIMARY,
Data.MIMETYPE,
Data.RES_PACKAGE,
Data.SYNC1,
Data.SYNC2,
Data.SYNC3,
Data.SYNC4,
GroupMembership.GROUP_SOURCE_ID,
Data.PRESENCE,
Data.CHAT_CAPABILITY,
Data.STATUS,
Data.STATUS_TIMESTAMP,
Data.STATUS_RES_PACKAGE,
Data.STATUS_LABEL,
Data.STATUS_ICON,
RawContacts.ACCOUNT_NAME,
RawContacts.ACCOUNT_TYPE,
RawContacts.DATA_SET,
RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
RawContacts.DIRTY,
RawContacts.SOURCE_ID,
RawContacts.VERSION,
Contacts.CUSTOM_RINGTONE,
Contacts.DISPLAY_NAME,
Contacts.DISPLAY_NAME_ALTERNATIVE,
Contacts.DISPLAY_NAME_SOURCE,
Contacts.IN_DEFAULT_DIRECTORY,
Contacts.IN_VISIBLE_GROUP,
Contacts.LAST_TIME_CONTACTED,
Contacts.LOOKUP_KEY,
Contacts.PHONETIC_NAME,
Contacts.PHONETIC_NAME_STYLE,
Contacts.PHOTO_ID,
Contacts.PHOTO_FILE_ID,
Contacts.PHOTO_URI,
Contacts.PHOTO_THUMBNAIL_URI,
Contacts.SEND_TO_VOICEMAIL,
Contacts.SORT_KEY_ALTERNATIVE,
Contacts.SORT_KEY_PRIMARY,
Contacts.STARRED,
Contacts.PINNED,
Contacts.TIMES_CONTACTED,
Contacts.HAS_PHONE_NUMBER,
Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
Contacts.CONTACT_PRESENCE,
Contacts.CONTACT_CHAT_CAPABILITY,
Contacts.CONTACT_STATUS,
Contacts.CONTACT_STATUS_TIMESTAMP,
Contacts.CONTACT_STATUS_RES_PACKAGE,
Contacts.CONTACT_STATUS_LABEL,
Contacts.CONTACT_STATUS_ICON,
Data.TIMES_USED,
Data.LAST_TIME_USED};
static final String[] RAW_CONTACTS_ENTITY_PROJECTION = new String[]{
};
static final String[] NTITY_PROJECTION = new String[]{
};
private static ContentValues[] sContentValues = new ContentValues[7];
static {
ContentValues cv1 = new ContentValues();
cv1.put(Contacts.DISPLAY_NAME, "Hot Tamale");
cv1.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
cv1.put(Email.DATA, "tamale@acme.com");
cv1.put(Email.TYPE, Email.TYPE_HOME);
sContentValues[0] = cv1;
ContentValues cv2 = new ContentValues();
cv2.put(Contacts.DISPLAY_NAME, "Hot Tamale");
cv2.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
cv2.put(Phone.DATA, "510-123-5769");
cv2.put(Phone.TYPE, Phone.TYPE_HOME);
sContentValues[1] = cv2;
ContentValues cv3 = new ContentValues();
cv3.put(Contacts.DISPLAY_NAME, "Hot Tamale");
cv3.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
cv3.put(Email.DATA, "hot@google.com");
cv3.put(Email.TYPE, Email.TYPE_WORK);
sContentValues[2] = cv3;
ContentValues cv4 = new ContentValues();
cv4.put(Contacts.DISPLAY_NAME, "Cold Tamago");
cv4.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
cv4.put(Email.DATA, "eggs@farmers.org");
cv4.put(Email.TYPE, Email.TYPE_HOME);
sContentValues[3] = cv4;
ContentValues cv5 = new ContentValues();
cv5.put(Contacts.DISPLAY_NAME, "John Doe");
cv5.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
cv5.put(Email.DATA, "doeassociates@deer.com");
cv5.put(Email.TYPE, Email.TYPE_WORK);
sContentValues[4] = cv5;
ContentValues cv6 = new ContentValues();
cv6.put(Contacts.DISPLAY_NAME, "John Doe");
cv6.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
cv6.put(Phone.DATA, "518-354-1111");
cv6.put(Phone.TYPE, Phone.TYPE_HOME);
sContentValues[5] = cv6;
ContentValues cv7 = new ContentValues();
cv7.put(Contacts.DISPLAY_NAME, "Cold Tamago");
cv7.put(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
cv7.put(SipAddress.DATA, "mysip@sipaddress.com");
cv7.put(SipAddress.TYPE, SipAddress.TYPE_HOME);
sContentValues[6] = cv7;
}
private TestRawContact[] mRawContacts = new TestRawContact[3];
@Override
protected void setUp() throws Exception {
super.setUp();
mResolver = getInstrumentation().getTargetContext().getContentResolver();
ContentProviderClient provider =
mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
mBuilder = new ContactsContract_TestDataBuilder(provider);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mBuilder.cleanup();
}
public void testGetLookupUriBySourceId() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_type")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.with(RawContacts.SOURCE_ID, "source_id")
.insert();
// TODO remove this. The method under test is currently broken: it will not
// work without at least one data row in the raw contact.
TestData data = rawContact.newDataRow(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredName.DISPLAY_NAME, "test name")
.insert();
Uri lookupUri = Data.getContactLookupUri(mResolver, data.getUri());
assertNotNull("Could not produce a lookup URI", lookupUri);
TestContact lookupContact = mBuilder.newContact().setUri(lookupUri).load();
assertEquals("Lookup URI matched the wrong contact",
lookupContact.getId(), data.load().getRawContact().load().getContactId());
}
public void testDataProjection() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_type")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.with(RawContacts.SOURCE_ID, "source_id")
.insert();
TestData data = rawContact.newDataRow(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredName.DISPLAY_NAME, "test name")
.insert();
DatabaseAsserts.checkProjection(mResolver, Data.CONTENT_URI,
DATA_PROJECTION,
new long[]{data.load().getId()}
);
}
public void testRawContactsEntityProjection() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_type")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.with(RawContacts.SOURCE_ID, "source_id")
.insert();
TestData data = rawContact.newDataRow(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredName.DISPLAY_NAME, "test name")
.insert();
DatabaseAsserts.checkProjection(mResolver, RawContactsEntity.CONTENT_URI,
new String[]{
RawContacts._ID,
RawContacts.CONTACT_ID,
RawContacts.Entity.DATA_ID,
RawContacts.DELETED,
RawContacts.STARRED,
RawContacts.RAW_CONTACT_IS_USER_PROFILE,
RawContacts.ACCOUNT_NAME,
RawContacts.ACCOUNT_TYPE,
RawContacts.DATA_SET,
RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
RawContacts.DIRTY,
RawContacts.SOURCE_ID,
RawContacts.BACKUP_ID,
RawContacts.VERSION,
RawContacts.SYNC1,
RawContacts.SYNC2,
RawContacts.SYNC3,
RawContacts.SYNC4,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15,
Data.CARRIER_PRESENCE,
Data.DATA_VERSION,
Data.IS_PRIMARY,
Data.IS_SUPER_PRIMARY,
Data.MIMETYPE,
Data.RES_PACKAGE,
Data.SYNC1,
Data.SYNC2,
Data.SYNC3,
Data.SYNC4,
GroupMembership.GROUP_SOURCE_ID},
new long[]{rawContact.getId()}
);
}
public void testEntityProjection() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_type")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.with(RawContacts.SOURCE_ID, "source_id")
.insert();
TestData data = rawContact.newDataRow(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredName.DISPLAY_NAME, "test name")
.insert();
long contactId = rawContact.load().getContactId();
DatabaseAsserts.checkProjection(mResolver, Contacts.CONTENT_URI.buildUpon().appendPath(
String.valueOf(contactId)).appendPath(
Entity.CONTENT_DIRECTORY).build(),
new String[]{
Contacts.Entity._ID,
Contacts.Entity.CONTACT_ID,
Contacts.Entity.RAW_CONTACT_ID,
Contacts.Entity.DATA_ID,
Contacts.Entity.NAME_RAW_CONTACT_ID,
Contacts.Entity.DELETED,
Contacts.IS_USER_PROFILE,
Contacts.CUSTOM_RINGTONE,
Contacts.DISPLAY_NAME,
Contacts.DISPLAY_NAME_ALTERNATIVE,
Contacts.DISPLAY_NAME_SOURCE,
Contacts.IN_DEFAULT_DIRECTORY,
Contacts.IN_VISIBLE_GROUP,
Contacts.LAST_TIME_CONTACTED,
Contacts.LOOKUP_KEY,
Contacts.PHONETIC_NAME,
Contacts.PHONETIC_NAME_STYLE,
Contacts.PHOTO_ID,
Contacts.PHOTO_FILE_ID,
Contacts.PHOTO_URI,
Contacts.PHOTO_THUMBNAIL_URI,
Contacts.SEND_TO_VOICEMAIL,
Contacts.SORT_KEY_ALTERNATIVE,
Contacts.SORT_KEY_PRIMARY,
Contacts.STARRED,
Contacts.PINNED,
Contacts.TIMES_CONTACTED,
Contacts.HAS_PHONE_NUMBER,
Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
Contacts.CONTACT_PRESENCE,
Contacts.CONTACT_CHAT_CAPABILITY,
Contacts.CONTACT_STATUS,
Contacts.CONTACT_STATUS_TIMESTAMP,
Contacts.CONTACT_STATUS_RES_PACKAGE,
Contacts.CONTACT_STATUS_LABEL,
Contacts.CONTACT_STATUS_ICON,
RawContacts.ACCOUNT_NAME,
RawContacts.ACCOUNT_TYPE,
RawContacts.DATA_SET,
RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
RawContacts.DIRTY,
RawContacts.SOURCE_ID,
RawContacts.BACKUP_ID,
RawContacts.VERSION,
RawContacts.SYNC1,
RawContacts.SYNC2,
RawContacts.SYNC3,
RawContacts.SYNC4,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15,
Data.CARRIER_PRESENCE,
Data.DATA_VERSION,
Data.IS_PRIMARY,
Data.IS_SUPER_PRIMARY,
Data.MIMETYPE,
Data.RES_PACKAGE,
Data.SYNC1,
Data.SYNC2,
Data.SYNC3,
Data.SYNC4,
GroupMembership.GROUP_SOURCE_ID,
Data.PRESENCE,
Data.CHAT_CAPABILITY,
Data.STATUS,
Data.STATUS_TIMESTAMP,
Data.STATUS_RES_PACKAGE,
Data.STATUS_LABEL,
Data.STATUS_ICON,
Data.TIMES_USED,
Data.LAST_TIME_USED},
new long[]{contactId}
);
}
public void testGetLookupUriByDisplayName() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_type")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.insert();
TestData data = rawContact.newDataRow(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredName.DISPLAY_NAME, "test name")
.insert();
Uri lookupUri = Data.getContactLookupUri(mResolver, data.getUri());
assertNotNull("Could not produce a lookup URI", lookupUri);
TestContact lookupContact = mBuilder.newContact().setUri(lookupUri).load();
assertEquals("Lookup URI matched the wrong contact",
lookupContact.getId(), data.load().getRawContact().load().getContactId());
}
public void testContactablesUri() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_account")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.insert();
rawContact.newDataRow(CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "test@test.com")
.with(Email.TYPE, Email.TYPE_WORK)
.insert();
ContentValues cv = new ContentValues();
cv.put(Email.DATA, "test@test.com");
cv.put(Email.TYPE, Email.TYPE_WORK);
Uri contentUri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
try {
assertCursorStoredValuesWithRawContactsFilter(contentUri,
new long[] {rawContact.getId()}, cv);
rawContact.newDataRow(CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
.with(CommonDataKinds.StructuredPostal.DATA1, "100 Sesame Street")
.insert();
rawContact.newDataRow(Phone.CONTENT_ITEM_TYPE)
.with(Phone.DATA, "123456789")
.with(Phone.TYPE, Phone.TYPE_MOBILE)
.insert();
ContentValues cv2 = new ContentValues();
cv.put(Phone.DATA, "123456789");
cv.put(Phone.TYPE, Phone.TYPE_MOBILE);
// Contactables Uri should return only email and phone data items.
DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, contentUri, null,
Data.RAW_CONTACT_ID + "=?", new String[] {String.valueOf(rawContact.getId())},
null, false, cv, cv2);
} finally {
// Clean up
rawContact.delete();
}
}
public void testContactablesFilterByLastName_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri filterUri = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "tamale");
assertCursorStoredValuesWithRawContactsFilter(filterUri, ids,
ContactablesTestHelper.getContentValues(0));
}
public void testContactablesFilterByFirstName_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri filterUri = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "hot");
assertCursorStoredValuesWithRawContactsFilter(filterUri, ids,
ContactablesTestHelper.getContentValues(0));
Uri filterUri2 = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "tam");
assertCursorStoredValuesWithRawContactsFilter(filterUri2, ids,
ContactablesTestHelper.getContentValues(0, 1));
}
public void testContactablesFilterByPhonePrefix_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri filterUri = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "518");
assertCursorStoredValuesWithRawContactsFilter(filterUri, ids,
ContactablesTestHelper.getContentValues(2));
Uri filterUri2 = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "51");
assertCursorStoredValuesWithRawContactsFilter(filterUri2, ids,
ContactablesTestHelper.getContentValues(0, 2));
}
public void testContactablesFilterByEmailPrefix_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri filterUri = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "doeassoc");
assertCursorStoredValuesWithRawContactsFilter(filterUri, ids,
ContactablesTestHelper.getContentValues(2));
}
public void testContactablesFilter_doesNotExist_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri filterUri = Uri.withAppendedPath(Contactables.CONTENT_FILTER_URI, "doesnotexist");
assertCursorStoredValuesWithRawContactsFilter(filterUri, ids, new ContentValues[0]);
}
/**
* Verifies that Callable.CONTENT_URI returns only data items that can be called (i.e.
* phone numbers and sip addresses)
*/
public void testCallableUri_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri uri = Callable.CONTENT_URI;
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1],
sContentValues[5], sContentValues[6]);
}
public void testCallableFilterByNameOrOrganization_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "doe");
// Only callables belonging to John Doe (name) and Cold Tamago (organization) are returned.
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[5],
sContentValues[6]);
}
public void testCallableFilterByNumber_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "510");
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1]);
}
public void testCallableFilterBySipAddress_returnsCorrectDataRows() throws Exception {
long[] ids = setupContactablesTestData();
Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "mysip");
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
}
public void testDataInsert_updatesContactLastUpdatedTimestamp() {
DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
SystemClock.sleep(1);
createData(ids.mRawContactId);
long newTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
assertTrue(newTime > baseTime);
// Clean up
RawContactUtil.delete(mResolver, ids.mRawContactId, true);
}
public void testDataDelete_updatesContactLastUpdatedTimestamp() {
DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
long dataId = createData(ids.mRawContactId);
long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
SystemClock.sleep(1);
DataUtil.delete(mResolver, dataId);
long newTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
assertTrue(newTime > baseTime);
// Clean up
RawContactUtil.delete(mResolver, ids.mRawContactId, true);
}
/**
* Tests that specifying the {@link android.provider.ContactsContract#REMOVE_DUPLICATE_ENTRIES}
* boolean parameter correctly results in deduped phone numbers.
*/
public void testPhoneQuery_removeDuplicateEntries() throws Exception{
long[] ids = setupContactablesTestData();
// Insert duplicate data entry for raw contact 3. (existing phone number 518-354-1111)
mRawContacts[2].newDataRow(Phone.CONTENT_ITEM_TYPE)
.with(Phone.DATA, "518-354-1111")
.with(Phone.TYPE, Phone.TYPE_HOME)
.insert();
ContentValues dupe = new ContentValues();
dupe.put(Contacts.DISPLAY_NAME, "John Doe");
dupe.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
dupe.put(Phone.DATA, "518-354-1111");
dupe.put(Phone.TYPE, Phone.TYPE_HOME);
// Query for all phone numbers in the contacts database (without deduping).
// The phone number above should be listed twice, in its duplicated forms.
assertCursorStoredValuesWithRawContactsFilter(Phone.CONTENT_URI, ids, sContentValues[1],
sContentValues[5], dupe);
// Now query for all phone numbers in the contacts database but request deduping.
// The phone number should now be listed only once.
Uri uri = Phone.CONTENT_URI.buildUpon().
appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1],
sContentValues[5]);
}
/**
* Tests that specifying the {@link android.provider.ContactsContract#REMOVE_DUPLICATE_ENTRIES}
* boolean parameter correctly results in deduped email addresses.
*/
public void testEmailQuery_removeDuplicateEntries() throws Exception{
long[] ids = setupContactablesTestData();
// Insert duplicate data entry for raw contact 3. (existing email doeassociates@deer.com)
mRawContacts[2].newDataRow(Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "doeassociates@deer.com")
.with(Email.TYPE, Email.TYPE_WORK)
.insert();
ContentValues dupe = new ContentValues();
dupe.put(Contacts.DISPLAY_NAME, "John Doe");
dupe.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
dupe.put(Email.DATA, "doeassociates@deer.com");
dupe.put(Email.TYPE, Email.TYPE_WORK);
// Query for all email addresses in the contacts database (without deduping).
// The email address above should be listed twice, in its duplicated forms.
assertCursorStoredValuesWithRawContactsFilter(Email.CONTENT_URI, ids, sContentValues[0],
sContentValues[2], sContentValues[3], sContentValues[4], dupe);
// Now query for all email addresses in the contacts database but request deduping.
// The email address should now be listed only once.
Uri uri = Email.CONTENT_URI.buildUpon().
appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[0],
sContentValues[2], sContentValues[3], sContentValues[4]);
}
public void testDataUpdate_updatesContactLastUpdatedTimestamp() {
DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
long dataId = createData(ids.mRawContactId);
long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
SystemClock.sleep(1);
ContentValues values = new ContentValues();
values.put(CommonDataKinds.Phone.NUMBER, "555-5555");
DataUtil.update(mResolver, dataId, values);
long newTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
assertTrue("Expected contact " + ids.mContactId + " last updated to be greater than " +
baseTime + ". But was " + newTime, newTime > baseTime);
// Clean up
RawContactUtil.delete(mResolver, ids.mRawContactId, true);
}
private long createData(long rawContactId) {
ContentValues values = new ContentValues();
values.put(Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
values.put(CommonDataKinds.Phone.NUMBER, "1-800-GOOG-411");
values.put(CommonDataKinds.Phone.TYPE, CommonDataKinds.Phone.TYPE_CUSTOM);
values.put(CommonDataKinds.Phone.LABEL, "free directory assistance");
return DataUtil.insertData(mResolver, rawContactId, values);
}
private void assertCursorStoredValuesWithRawContactsFilter(Uri uri, long[] rawContactsId,
ContentValues... expected) {
// We need this helper function to add a filter for specific raw contacts because
// otherwise tests will fail if performed on a device with existing contacts data
StringBuilder sb = new StringBuilder();
sb.append(Data.RAW_CONTACT_ID + " in ");
sb.append("(");
for (int i = 0; i < rawContactsId.length; i++) {
if (i != 0) sb.append(",");
sb.append(rawContactsId[i]);
}
sb.append(")");
DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, uri, null, sb.toString(),
null, null, false, expected);
}
private long[] setupContactablesTestData() throws Exception {
TestRawContact rawContact = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_account")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.insert();
rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
.with(StructuredName.DISPLAY_NAME, "Hot Tamale")
.insert();
rawContact.newDataRow(Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "tamale@acme.com")
.with(Email.TYPE, Email.TYPE_HOME)
.insert();
rawContact.newDataRow(Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "hot@google.com")
.with(Email.TYPE, Email.TYPE_WORK)
.insert();
rawContact.newDataRow(Phone.CONTENT_ITEM_TYPE)
.with(Phone.DATA, "510-123-5769")
.with(Email.TYPE, Phone.TYPE_HOME)
.insert();
mRawContacts[0] = rawContact;
TestRawContact rawContact2 = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_account")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.insert();
rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
.with(StructuredName.DISPLAY_NAME, "Cold Tamago")
.insert();
rawContact2.newDataRow(Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "eggs@farmers.org")
.with(Email.TYPE, Email.TYPE_HOME)
.insert();
rawContact2.newDataRow(SipAddress.CONTENT_ITEM_TYPE)
.with(SipAddress.DATA, "mysip@sipaddress.com")
.with(SipAddress.TYPE, SipAddress.TYPE_HOME)
.insert();
rawContact2.newDataRow(Organization.CONTENT_ITEM_TYPE)
.with(Organization.COMPANY, "Doe Corp")
.insert();
mRawContacts[1] = rawContact2;
TestRawContact rawContact3 = mBuilder.newRawContact()
.with(RawContacts.ACCOUNT_TYPE, "test_account")
.with(RawContacts.ACCOUNT_NAME, "test_name")
.insert();
rawContact3.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
.with(StructuredName.DISPLAY_NAME, "John Doe")
.insert();
rawContact3.newDataRow(Email.CONTENT_ITEM_TYPE)
.with(Email.DATA, "doeassociates@deer.com")
.with(Email.TYPE, Email.TYPE_WORK)
.insert();
rawContact3.newDataRow(Phone.CONTENT_ITEM_TYPE)
.with(Phone.DATA, "518-354-1111")
.with(Phone.TYPE, Phone.TYPE_HOME)
.insert();
rawContact3.newDataRow(Organization.CONTENT_ITEM_TYPE)
.with(Organization.DATA, "Doe Industries")
.insert();
mRawContacts[2] = rawContact3;
return new long[] {rawContact.getId(), rawContact2.getId(), rawContact3.getId()};
}
// Provides functionality to set up content values for the Contactables tests
private static class ContactablesTestHelper {
/**
* @return An arraylist of contentValues that correspond to the provided raw contacts
*/
public static ContentValues[] getContentValues(int... rawContacts) {
ArrayList<ContentValues> cv = new ArrayList<ContentValues>();
for (int i = 0; i < rawContacts.length; i++) {
switch (rawContacts[i]) {
case 0:
// rawContact 0 "Hot Tamale" contains ContentValues 0, 1, and 2
cv.add(sContentValues[0]);
cv.add(sContentValues[1]);
cv.add(sContentValues[2]);
break;
case 1:
// rawContact 1 "Cold Tamago" contains ContentValues 3
cv.add(sContentValues[3]);
break;
case 2:
// rawContact 1 "John Doe" contains ContentValues 4, 5
cv.add(sContentValues[4]);
cv.add(sContentValues[5]);
break;
}
}
ContentValues[] toReturn = new ContentValues[cv.size()];
for (int i = 0; i < cv.size(); i++) {
toReturn[i] = cv.get(i);
}
return toReturn;
}
}
}