Home | History | Annotate | Download | only in aggregation
      1 /*
      2  * Copyright (C) 2009 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.providers.contacts.aggregation;
     18 
     19 import android.accounts.Account;
     20 import android.content.ContentProviderOperation;
     21 import android.content.ContentProviderResult;
     22 import android.content.ContentUris;
     23 import android.content.ContentValues;
     24 import android.database.Cursor;
     25 import android.net.Uri;
     26 import android.provider.ContactsContract;
     27 import android.provider.ContactsContract.AggregationExceptions;
     28 import android.provider.ContactsContract.CommonDataKinds.Organization;
     29 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     30 import android.provider.ContactsContract.Contacts;
     31 import android.provider.ContactsContract.Contacts.AggregationSuggestions;
     32 import android.provider.ContactsContract.Contacts.Photo;
     33 import android.provider.ContactsContract.Data;
     34 import android.provider.ContactsContract.RawContacts;
     35 import android.provider.ContactsContract.StatusUpdates;
     36 import android.test.MoreAsserts;
     37 import android.test.suitebuilder.annotation.MediumTest;
     38 
     39 import com.android.providers.contacts.BaseContactsProvider2Test;
     40 import com.android.providers.contacts.TestUtils;
     41 import com.android.providers.contacts.tests.R;
     42 import com.google.android.collect.Lists;
     43 
     44 /**
     45  * Unit tests for {@link ContactAggregator}.
     46  *
     47  * Run the test like this:
     48  * <code>
     49  * adb shell am instrument -e class com.android.providers.contacts.ContactAggregatorTest -w \
     50  *         com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
     51  * </code>
     52  */
     53 @MediumTest
     54 public class ContactAggregatorTest extends BaseContactsProvider2Test {
     55 
     56     private static final Account ACCOUNT_1 = new Account("account_name_1", "account_type_1");
     57     private static final Account ACCOUNT_2 = new Account("account_name_2", "account_type_2");
     58     private static final Account ACCOUNT_3 = new Account("account_name_3", "account_type_3");
     59 
     60     private static final String[] AGGREGATION_EXCEPTION_PROJECTION = new String[] {
     61             AggregationExceptions.TYPE,
     62             AggregationExceptions.RAW_CONTACT_ID1,
     63             AggregationExceptions.RAW_CONTACT_ID2
     64     };
     65 
     66     public void testCrudAggregationExceptions() throws Exception {
     67         long rawContactId1 = createRawContactWithName("zz", "top");
     68         long rawContactId2 = createRawContactWithName("aa", "bottom");
     69 
     70         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
     71                 rawContactId1, rawContactId2);
     72 
     73         String selection = "(" + AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1
     74                 + " AND " + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2
     75                 + ") OR (" + AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId2
     76                 + " AND " + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId1 + ")";
     77 
     78         // Refetch the row we have just inserted
     79         Cursor c = mResolver.query(AggregationExceptions.CONTENT_URI,
     80                 AGGREGATION_EXCEPTION_PROJECTION, selection, null, null);
     81 
     82         assertTrue(c.moveToFirst());
     83         assertEquals(AggregationExceptions.TYPE_KEEP_TOGETHER, c.getInt(0));
     84         assertTrue((rawContactId1 == c.getLong(1) && rawContactId2 == c.getLong(2))
     85                 || (rawContactId2 == c.getLong(1) && rawContactId1 == c.getLong(2)));
     86         assertFalse(c.moveToNext());
     87         c.close();
     88 
     89         // Change from TYPE_KEEP_IN to TYPE_KEEP_OUT
     90         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
     91                 rawContactId1, rawContactId2);
     92 
     93         c = mResolver.query(AggregationExceptions.CONTENT_URI, AGGREGATION_EXCEPTION_PROJECTION,
     94                 selection, null, null);
     95 
     96         assertTrue(c.moveToFirst());
     97         assertEquals(AggregationExceptions.TYPE_KEEP_SEPARATE, c.getInt(0));
     98         assertTrue((rawContactId1 == c.getLong(1) && rawContactId2 == c.getLong(2))
     99                 || (rawContactId2 == c.getLong(1) && rawContactId1 == c.getLong(2)));
    100         assertFalse(c.moveToNext());
    101         c.close();
    102 
    103         // Delete the rule
    104         setAggregationException(AggregationExceptions.TYPE_AUTOMATIC,
    105                 rawContactId1, rawContactId2);
    106 
    107         // Verify that the row is gone
    108         c = mResolver.query(AggregationExceptions.CONTENT_URI, AGGREGATION_EXCEPTION_PROJECTION,
    109                 selection, null, null);
    110         assertFalse(c.moveToFirst());
    111         c.close();
    112     }
    113 
    114     public void testAggregationCreatesNewAggregate() {
    115         long rawContactId = createRawContact();
    116 
    117         Uri resultUri = insertStructuredName(rawContactId, "Johna", "Smitha");
    118 
    119         // Parse the URI and confirm that it contains an ID
    120         assertTrue(ContentUris.parseId(resultUri) != 0);
    121 
    122         long contactId = queryContactId(rawContactId);
    123         assertTrue(contactId != 0);
    124 
    125         String displayName = queryDisplayName(contactId);
    126         assertEquals("Johna Smitha", displayName);
    127     }
    128 
    129     public void testAggregationOfExactFullNameMatch() {
    130         long rawContactId1 = createRawContact(ACCOUNT_1);
    131         insertStructuredName(rawContactId1, "Johnb", "Smithb");
    132 
    133         long rawContactId2 = createRawContact(ACCOUNT_2);
    134         insertStructuredName(rawContactId2, "Johnb", "Smithb");
    135 
    136         assertAggregated(rawContactId1, rawContactId2, "Johnb Smithb");
    137     }
    138 
    139     public void testAggregationIgnoresInvisibleContact() {
    140         Account account = new Account("accountName", "accountType");
    141         createAutoAddGroup(account);
    142 
    143         long rawContactId1 = createRawContact(account);
    144         insertStructuredName(rawContactId1, "Flynn", "Ryder");
    145 
    146         // Hide by removing from all groups
    147         removeGroupMemberships(rawContactId1);
    148 
    149         long rawContactId2 = createRawContact(account);
    150         insertStructuredName(rawContactId2, "Flynn", "Ryder");
    151 
    152         long rawContactId3 = createRawContact(ACCOUNT_2);
    153         insertStructuredName(rawContactId3, "Flynn", "Ryder");
    154 
    155         assertNotAggregated(rawContactId1, rawContactId2);
    156         assertNotAggregated(rawContactId1, rawContactId3);
    157         assertAggregated(rawContactId2, rawContactId3, "Flynn Ryder");
    158     }
    159 
    160     public void testAggregationOfCaseInsensitiveFullNameMatch() {
    161         long rawContactId1 = createRawContact(ACCOUNT_1);
    162         insertStructuredName(rawContactId1, "Johnc", "Smithc");
    163 
    164         long rawContactId2 = createRawContact(ACCOUNT_2);
    165         insertStructuredName(rawContactId2, "Johnc", "smithc");
    166 
    167         assertAggregated(rawContactId1, rawContactId2, "Johnc Smithc");
    168     }
    169 
    170     public void testAggregationOfLastNameMatch() {
    171         long rawContactId1 = createRawContact(ACCOUNT_1);
    172         insertStructuredName(rawContactId1, null, "Johnd");
    173 
    174         long rawContactId2 = createRawContact(ACCOUNT_2);
    175         insertStructuredName(rawContactId2, null, "johnd");
    176 
    177         assertAggregated(rawContactId1, rawContactId2, "Johnd");
    178     }
    179 
    180     public void testNonAggregationOfFirstNameMatch() {
    181         long rawContactId1 = createRawContact(ACCOUNT_1);
    182         insertStructuredName(rawContactId1, "Johne", "Smithe");
    183 
    184         long rawContactId2 = createRawContact(ACCOUNT_2);
    185         insertStructuredName(rawContactId2, "Johne", null);
    186 
    187         assertNotAggregated(rawContactId1, rawContactId2);
    188     }
    189 
    190     public void testNonAggregationOfLastNameMatch() {
    191         long rawContactId1 = createRawContact(ACCOUNT_1);
    192         insertStructuredName(rawContactId1, "Johnf", "Smithf");
    193 
    194         long rawContactId2 = createRawContact(ACCOUNT_2);
    195         insertStructuredName(rawContactId2, null, "Smithf");
    196 
    197         assertNotAggregated(rawContactId1, rawContactId2);
    198     }
    199 
    200     public void testAggregationOfConcatenatedFullNameMatch() {
    201         long rawContactId1 = createRawContact(ACCOUNT_1);
    202         insertStructuredName(rawContactId1, "Johng", "Smithg");
    203 
    204         long rawContactId2 = createRawContact(ACCOUNT_2);
    205         insertStructuredName(rawContactId2, "johngsmithg", null);
    206 
    207         assertAggregated(rawContactId1, rawContactId2, "Johng Smithg");
    208     }
    209 
    210     public void testAggregationOfNormalizedFullNameMatch() {
    211         long rawContactId1 = createRawContact(ACCOUNT_1);
    212         insertStructuredName(rawContactId1, "H\u00e9l\u00e8ne", "Bj\u00f8rn");
    213 
    214         long rawContactId2 = createRawContact(ACCOUNT_2);
    215         insertStructuredName(rawContactId2, "helene bjorn", null);
    216 
    217         assertAggregated(rawContactId1, rawContactId2, "H\u00e9l\u00e8ne Bj\u00f8rn");
    218     }
    219 
    220     public void testAggregationOfNormalizedFullNameMatchWithReadOnlyAccount() {
    221         long rawContactId1 = createRawContact(new Account("acct", READ_ONLY_ACCOUNT_TYPE));
    222         insertStructuredName(rawContactId1, "H\u00e9l\u00e8ne", "Bj\u00f8rn");
    223 
    224         long rawContactId2 = createRawContact();
    225         insertStructuredName(rawContactId2, "helene bjorn", null);
    226 
    227         assertAggregated(rawContactId1, rawContactId2, "helene bjorn");
    228     }
    229 
    230     public void testAggregationOfNumericNames() {
    231         long rawContactId1 = createRawContact(ACCOUNT_1);
    232         insertStructuredName(rawContactId1, "123", null);
    233 
    234         long rawContactId2 = createRawContact(ACCOUNT_2);
    235         insertStructuredName(rawContactId2, "1-2-3", null);
    236 
    237         assertAggregated(rawContactId1, rawContactId2, "1-2-3");
    238     }
    239 
    240     public void testAggregationOfInconsistentlyParsedNames() {
    241         long rawContactId1 = createRawContact(ACCOUNT_1);
    242 
    243         ContentValues values = new ContentValues();
    244         values.put(StructuredName.DISPLAY_NAME, "604 Arizona Ave");
    245         values.put(StructuredName.GIVEN_NAME, "604");
    246         values.put(StructuredName.MIDDLE_NAME, "Arizona");
    247         values.put(StructuredName.FAMILY_NAME, "Ave");
    248         insertStructuredName(rawContactId1, values);
    249 
    250         long rawContactId2 = createRawContact(ACCOUNT_2);
    251         values.clear();
    252         values.put(StructuredName.DISPLAY_NAME, "604 Arizona Ave");
    253         values.put(StructuredName.GIVEN_NAME, "604");
    254         values.put(StructuredName.FAMILY_NAME, "Arizona Ave");
    255         insertStructuredName(rawContactId2, values);
    256 
    257         assertAggregated(rawContactId1, rawContactId2, "604 Arizona Ave");
    258     }
    259 
    260     public void testAggregationBasedOnMiddleName() {
    261         ContentValues values = new ContentValues();
    262         long rawContactId1 = createRawContact(ACCOUNT_1);
    263         values.put(StructuredName.GIVEN_NAME, "John");
    264         values.put(StructuredName.GIVEN_NAME, "Abigale");
    265         values.put(StructuredName.FAMILY_NAME, "James");
    266 
    267         insertStructuredName(rawContactId1, values);
    268 
    269         long rawContactId2 = createRawContact(ACCOUNT_2);
    270         values.clear();
    271         values.put(StructuredName.GIVEN_NAME, "John");
    272         values.put(StructuredName.GIVEN_NAME, "Marie");
    273         values.put(StructuredName.FAMILY_NAME, "James");
    274         insertStructuredName(rawContactId2, values);
    275 
    276         assertNotAggregated(rawContactId1, rawContactId2);
    277     }
    278 
    279     public void testAggregationBasedOnPhoneNumberNoNameData() {
    280         long rawContactId1 = createRawContact(ACCOUNT_1);
    281         insertPhoneNumber(rawContactId1, "(888)555-1231");
    282 
    283         long rawContactId2 = createRawContact(ACCOUNT_2);
    284         insertPhoneNumber(rawContactId2, "1(888)555-1231");
    285 
    286         assertAggregated(rawContactId1, rawContactId2);
    287     }
    288 
    289     public void testAggregationBasedOnPhoneNumberWhenTargetAggregateHasNoName() {
    290         long rawContactId1 = createRawContact(ACCOUNT_1);
    291         insertPhoneNumber(rawContactId1, "(888)555-1232");
    292 
    293         long rawContactId2 = createRawContact(ACCOUNT_2);
    294         insertStructuredName(rawContactId2, "Johnl", "Smithl");
    295         insertPhoneNumber(rawContactId2, "1(888)555-1232");
    296 
    297         assertAggregated(rawContactId1, rawContactId2);
    298     }
    299 
    300     public void testAggregationBasedOnPhoneNumberWhenNewContactHasNoName() {
    301         long rawContactId1 = createRawContact(ACCOUNT_1);
    302         insertStructuredName(rawContactId1, "Johnm", "Smithm");
    303         insertPhoneNumber(rawContactId1, "(888)555-1233");
    304 
    305         long rawContactId2 = createRawContact(ACCOUNT_2);
    306         insertPhoneNumber(rawContactId2, "1(888)555-1233");
    307 
    308         assertAggregated(rawContactId1, rawContactId2);
    309     }
    310 
    311     public void testAggregationBasedOnPhoneNumberWithDifferentNames() {
    312         long rawContactId1 = createRawContact(ACCOUNT_1);
    313         insertStructuredName(rawContactId1, "Baby", "Bear");
    314         insertPhoneNumber(rawContactId1, "(888)555-1235");
    315 
    316         long rawContactId2 = createRawContact(ACCOUNT_2);
    317         insertStructuredName(rawContactId2, "Blind", "Mouse");
    318         insertPhoneNumber(rawContactId2, "1(888)555-1235");
    319 
    320         assertNotAggregated(rawContactId1, rawContactId2);
    321     }
    322 
    323     public void testAggregationBasedOnPhoneNumberWithJustFirstName() {
    324         long rawContactId1 = createRawContact(ACCOUNT_1);
    325         insertStructuredName(rawContactId1, "Chick", "Notnull");
    326         insertPhoneNumber(rawContactId1, "(888)555-1236");
    327 
    328         long rawContactId2 = createRawContact(ACCOUNT_2);
    329         insertStructuredName(rawContactId2, "Chick", null);
    330         insertPhoneNumber(rawContactId2, "1(888)555-1236");
    331 
    332         assertAggregated(rawContactId1, rawContactId2);
    333     }
    334 
    335     public void testAggregationBasedOnEmailNoNameData() {
    336         long rawContactId1 = createRawContact(ACCOUNT_1);
    337         insertEmail(rawContactId1, "lightning (at) android.com");
    338 
    339         long rawContactId2 = createRawContact(ACCOUNT_2);
    340         insertEmail(rawContactId2, "lightning (at) android.com");
    341 
    342         assertAggregated(rawContactId1, rawContactId2);
    343     }
    344 
    345     public void testAggregationBasedOnEmailWhenTargetAggregateHasNoName() {
    346         long rawContactId1 = createRawContact(ACCOUNT_1);
    347         insertEmail(rawContactId1, "mcqueen (at) android.com");
    348 
    349         long rawContactId2 = createRawContact(ACCOUNT_2);
    350         insertStructuredName(rawContactId2, "Lightning", "McQueen");
    351         insertEmail(rawContactId2, "mcqueen (at) android.com");
    352 
    353         assertAggregated(rawContactId1, rawContactId2, "Lightning McQueen");
    354     }
    355 
    356     public void testAggregationBasedOnEmailWhenNewContactHasNoName() {
    357         long rawContactId1 = createRawContact(ACCOUNT_1);
    358         insertStructuredName(rawContactId1, "Doc", "Hudson");
    359         insertEmail(rawContactId1, "doc (at) android.com");
    360 
    361         long rawContactId2 = createRawContact(ACCOUNT_2);
    362         insertEmail(rawContactId2, "doc (at) android.com");
    363 
    364         assertAggregated(rawContactId1, rawContactId2);
    365     }
    366 
    367     public void testAggregationBasedOnEmailWithDifferentNames() {
    368         long rawContactId1 = createRawContact(ACCOUNT_1);
    369         insertStructuredName(rawContactId1, "Chick", "Hicks");
    370         insertEmail(rawContactId1, "hicky (at) android.com");
    371 
    372         long rawContactId2 = createRawContact(ACCOUNT_2);
    373         insertStructuredName(rawContactId2, "Luigi", "Guido");
    374         insertEmail(rawContactId2, "hicky (at) android.com");
    375 
    376         assertNotAggregated(rawContactId1, rawContactId2);
    377     }
    378 
    379     public void testAggregationByCommonNicknameWithLastName() {
    380         long rawContactId1 = createRawContact(ACCOUNT_1);
    381         insertStructuredName(rawContactId1, "Bill", "Gore");
    382 
    383         long rawContactId2 = createRawContact(ACCOUNT_2);
    384         insertStructuredName(rawContactId2, "William", "Gore");
    385 
    386         assertAggregated(rawContactId1, rawContactId2, "William Gore");
    387     }
    388 
    389     public void testAggregationByCommonNicknameOnly() {
    390         long rawContactId1 = createRawContact(ACCOUNT_1);
    391         insertStructuredName(rawContactId1, "Lawrence", null);
    392 
    393         long rawContactId2 = createRawContact(ACCOUNT_2);
    394         insertStructuredName(rawContactId2, "Larry", null);
    395 
    396         assertAggregated(rawContactId1, rawContactId2, "Lawrence");
    397     }
    398 
    399     public void testAggregationByNicknameNoStructuredName() {
    400         long rawContactId1 = createRawContact(ACCOUNT_1);
    401         insertNickname(rawContactId1, "Frozone");
    402 
    403         long rawContactId2 = createRawContact(ACCOUNT_2);
    404         insertNickname(rawContactId2, "Frozone");
    405 
    406         assertAggregated(rawContactId1, rawContactId2);
    407     }
    408 
    409     public void testAggregationByNicknameWithDifferentNames() {
    410         long rawContactId1 = createRawContact(ACCOUNT_1);
    411         insertStructuredName(rawContactId1, "Helen", "Parr");
    412         insertNickname(rawContactId1, "Elastigirl");
    413 
    414         long rawContactId2 = createRawContact(ACCOUNT_2);
    415         insertStructuredName(rawContactId2, "Shawn", "Johnson");
    416         insertNickname(rawContactId2, "Elastigirl");
    417 
    418         assertNotAggregated(rawContactId1, rawContactId2);
    419     }
    420 
    421     public void testNonAggregationOnOrganization() {
    422         ContentValues values = new ContentValues();
    423         values.put(Organization.TITLE, "Monsters, Inc");
    424         long rawContactId1 = createRawContact(ACCOUNT_1);
    425         insertOrganization(rawContactId1, values);
    426         insertNickname(rawContactId1, "Boo");
    427 
    428         long rawContactId2 = createRawContact(ACCOUNT_2);
    429         insertOrganization(rawContactId2, values);
    430         insertNickname(rawContactId2, "Rendall");   // To force reaggregation
    431 
    432         assertNotAggregated(rawContactId1, rawContactId2);
    433     }
    434 
    435     public void testAggregationByIdentity() {
    436         long rawContactId1 = createRawContact(ACCOUNT_1);
    437         insertIdentity(rawContactId1, "iden1", "namespace1");
    438 
    439         long rawContactId2 = createRawContact(ACCOUNT_2);
    440         insertIdentity(rawContactId2, "iden1", "namespace1");
    441 
    442         assertAggregated(rawContactId1, rawContactId2);
    443     }
    444 
    445     public void testAggregationExceptionKeepIn() {
    446         long rawContactId1 = createRawContact(ACCOUNT_1);
    447         insertStructuredName(rawContactId1, "Johnk", "Smithk");
    448 
    449         long rawContactId2 = createRawContact(ACCOUNT_2);
    450         insertStructuredName(rawContactId2, "Johnkx", "Smithkx");
    451 
    452         long contactId1 = queryContactId(rawContactId1);
    453         long contactId2 = queryContactId(rawContactId2);
    454 
    455         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    456                 rawContactId1, rawContactId2);
    457 
    458         assertAggregated(rawContactId1, rawContactId2, "Johnkx Smithkx");
    459 
    460         // Assert that the empty aggregate got removed
    461         long newContactId1 = queryContactId(rawContactId1);
    462         if (contactId1 != newContactId1) {
    463             Cursor cursor = queryContact(contactId1);
    464             assertFalse(cursor.moveToFirst());
    465             cursor.close();
    466         } else {
    467             Cursor cursor = queryContact(contactId2);
    468             assertFalse(cursor.moveToFirst());
    469             cursor.close();
    470         }
    471     }
    472 
    473     public void testAggregationExceptionKeepOut() {
    474         long rawContactId1 = createRawContact(ACCOUNT_1);
    475         insertStructuredName(rawContactId1, "Johnh", "Smithh");
    476 
    477         long rawContactId2 = createRawContact(ACCOUNT_2);
    478         insertStructuredName(rawContactId2, "Johnh", "Smithh");
    479 
    480         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    481                 rawContactId1, rawContactId2);
    482 
    483         assertNotAggregated(rawContactId1, rawContactId2);
    484     }
    485 
    486     public void testAggregationExceptionKeepOutCheckUpdatesDisplayName() {
    487         long rawContactId1 = createRawContact(ACCOUNT_1);
    488         insertStructuredName(rawContactId1, "Johni", "Smithi");
    489 
    490         long rawContactId2 = createRawContact(ACCOUNT_2);
    491         insertStructuredName(rawContactId2, "Johnj", "Smithj");
    492 
    493         long rawContactId3 = createRawContact(ACCOUNT_3);
    494         insertStructuredName(rawContactId3, "Johnm", "Smithm");
    495 
    496         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    497                 rawContactId1, rawContactId2);
    498         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    499                 rawContactId1, rawContactId3);
    500         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    501                 rawContactId2, rawContactId3);
    502 
    503         assertAggregated(rawContactId1, rawContactId2, "Johnm Smithm");
    504         assertAggregated(rawContactId1, rawContactId3);
    505 
    506         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    507                 rawContactId1, rawContactId2);
    508         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    509                 rawContactId1, rawContactId3);
    510 
    511         assertNotAggregated(rawContactId1, rawContactId2);
    512         assertNotAggregated(rawContactId1, rawContactId3);
    513 
    514         String displayName1 = queryDisplayName(queryContactId(rawContactId1));
    515         assertEquals("Johni Smithi", displayName1);
    516 
    517         assertAggregated(rawContactId2, rawContactId3, "Johnm Smithm");
    518 
    519         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    520                 rawContactId2, rawContactId3);
    521         assertNotAggregated(rawContactId1, rawContactId2);
    522         assertNotAggregated(rawContactId1, rawContactId3);
    523         assertNotAggregated(rawContactId2, rawContactId3);
    524 
    525         String displayName2 = queryDisplayName(queryContactId(rawContactId1));
    526         assertEquals("Johni Smithi", displayName2);
    527 
    528         String displayName3 = queryDisplayName(queryContactId(rawContactId2));
    529         assertEquals("Johnj Smithj", displayName3);
    530 
    531         String displayName4 = queryDisplayName(queryContactId(rawContactId3));
    532         assertEquals("Johnm Smithm", displayName4);
    533     }
    534 
    535     public void testAggregationExceptionKeepOutCheckResultDisplayNames() {
    536         long rawContactId1 = createRawContactWithName("c", "c", ACCOUNT_1);
    537         long rawContactId2 = createRawContactWithName("b", "b", ACCOUNT_2);
    538         long rawContactId3 = createRawContactWithName("a", "a", ACCOUNT_3);
    539 
    540         // Join all contacts
    541         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    542                 rawContactId1, rawContactId2);
    543         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    544                 rawContactId1, rawContactId3);
    545         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    546                 rawContactId2, rawContactId3);
    547 
    548         // Separate all contacts. The order (2-3 , 1-2, 1-3) is important
    549         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    550                 rawContactId2, rawContactId3);
    551         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    552                 rawContactId1, rawContactId2);
    553         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    554                 rawContactId1, rawContactId3);
    555 
    556         // Verify that we have three different contacts
    557         long contactId1 = queryContactId(rawContactId1);
    558         long contactId2 = queryContactId(rawContactId2);
    559         long contactId3 = queryContactId(rawContactId3);
    560 
    561         assertTrue(contactId1 != contactId2);
    562         assertTrue(contactId1 != contactId3);
    563         assertTrue(contactId2 != contactId3);
    564 
    565         // Verify that each raw contact contribute to the contact display name
    566         assertDisplayNameEquals(contactId1, rawContactId1);
    567         assertDisplayNameEquals(contactId2, rawContactId2);
    568         assertDisplayNameEquals(contactId3, rawContactId3);
    569     }
    570 
    571     public void testNonAggregationWithMultipleAffinities() {
    572         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    573         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    574         assertNotAggregated(rawContactId1, rawContactId2);
    575 
    576         // There are two aggregates this raw contact could join, so it should join neither
    577         long rawContactId3 = createRawContactWithName("John", "Doe", ACCOUNT_2);
    578         assertNotAggregated(rawContactId1, rawContactId3);
    579         assertNotAggregated(rawContactId2, rawContactId3);
    580 
    581         // Just in case - let's make sure the original two did not get aggregated in the process
    582         assertNotAggregated(rawContactId1, rawContactId2);
    583     }
    584 
    585     public void testSplitBecauseOfMultipleAffinities() {
    586         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    587         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_2);
    588         assertAggregated(rawContactId1, rawContactId2);
    589 
    590         // The aggregate this raw contact could join has a raw contact from the same account,
    591         // let's not aggregate and break up the existing aggregate because of the ambiguity
    592         long rawContactId3 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    593         assertNotAggregated(rawContactId1, rawContactId3);
    594         assertNotAggregated(rawContactId2, rawContactId3);
    595         assertNotAggregated(rawContactId1, rawContactId2);
    596     }
    597 
    598     public void testReaggregationWhenBecomesInvisible() {
    599         Account account = new Account("accountName", "accountType");
    600         createAutoAddGroup(account);
    601 
    602         long rawContactId1 = createRawContact(account);
    603         insertStructuredName(rawContactId1, "Flynn", "Ryder");
    604 
    605         long rawContactId2 = createRawContact(ACCOUNT_2);
    606         insertStructuredName(rawContactId2, "Flynn", "Ryder");
    607 
    608         long rawContactId3 = createRawContact(account);
    609         insertStructuredName(rawContactId3, "Flynn", "Ryder");
    610 
    611         assertNotAggregated(rawContactId1, rawContactId3);
    612         assertNotAggregated(rawContactId2, rawContactId3);
    613         assertNotAggregated(rawContactId1, rawContactId2);
    614 
    615         // Hide by removing from all groups
    616         removeGroupMemberships(rawContactId3);
    617 
    618         assertAggregated(rawContactId1, rawContactId2, "Flynn Ryder");
    619         assertNotAggregated(rawContactId1, rawContactId3);
    620         assertNotAggregated(rawContactId2, rawContactId3);
    621     }
    622 
    623     public void testReaggregationWhenBecomesInvisibleSecondaryDataMatch() {
    624         Account account = new Account("accountName", "accountType");
    625         createAutoAddGroup(account);
    626 
    627         long rawContactId1 = createRawContact(account);
    628         insertStructuredName(rawContactId1, "Flynn", "Ryder");
    629         insertPhoneNumber(rawContactId1, "1234567890");
    630 
    631         long rawContactId2 = createRawContact(ACCOUNT_2);
    632         insertPhoneNumber(rawContactId2, "1234567890");
    633 
    634         long rawContactId3 = createRawContact(account);
    635         insertStructuredName(rawContactId3, "Flynn", "Ryder");
    636 
    637         assertNotAggregated(rawContactId1, rawContactId3);
    638         assertNotAggregated(rawContactId2, rawContactId3);
    639         assertNotAggregated(rawContactId1, rawContactId2);
    640 
    641         // Hide by removing from all groups
    642         removeGroupMemberships(rawContactId3);
    643 
    644         assertAggregated(rawContactId1, rawContactId2, "Flynn Ryder");
    645         assertNotAggregated(rawContactId1, rawContactId3);
    646         assertNotAggregated(rawContactId2, rawContactId3);
    647     }
    648 
    649     public void testReaggregationWhenBecomesVisible() {
    650         Account account = new Account("accountName", "accountType");
    651         long groupId = createAutoAddGroup(account);
    652 
    653         long rawContactId1 = createRawContact(account);
    654         insertStructuredName(rawContactId1, "Flynn", "Ryder");
    655 
    656         long rawContactId2 = createRawContact(ACCOUNT_2);
    657         insertStructuredName(rawContactId2, "Flynn", "Ryder");
    658 
    659         long rawContactId3 = createRawContact(account);
    660         removeGroupMemberships(rawContactId3);
    661         insertStructuredName(rawContactId3, "Flynn", "Ryder");
    662 
    663         assertAggregated(rawContactId1, rawContactId2, "Flynn Ryder");
    664         assertNotAggregated(rawContactId1, rawContactId3);
    665         assertNotAggregated(rawContactId2, rawContactId3);
    666 
    667         insertGroupMembership(rawContactId3, groupId);
    668 
    669         assertNotAggregated(rawContactId1, rawContactId3);
    670         assertNotAggregated(rawContactId2, rawContactId3);
    671         assertNotAggregated(rawContactId1, rawContactId2);
    672     }
    673 
    674     public void testNonSplitBecauseOfMultipleAffinitiesWhenOverridden() {
    675         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    676         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_2);
    677         long rawContactId3 = createRawContactWithName("John", "Doe", ACCOUNT_3);
    678         assertAggregated(rawContactId1, rawContactId2);
    679         assertAggregated(rawContactId1, rawContactId3);
    680         setAggregationException(
    681                 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2);
    682         assertAggregated(rawContactId1, rawContactId2);
    683         assertAggregated(rawContactId1, rawContactId3);
    684 
    685         // The aggregate this raw contact could join has a raw contact from the same account,
    686         // let's not aggregate and break up the existing aggregate because of the ambiguity
    687         long rawContactId4 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    688         assertAggregated(rawContactId1, rawContactId2);     // Aggregation exception
    689         assertNotAggregated(rawContactId1, rawContactId3);
    690         assertNotAggregated(rawContactId1, rawContactId4);
    691         assertNotAggregated(rawContactId3, rawContactId4);
    692     }
    693 
    694     public void testNonAggregationFromSameAccount() {
    695         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    696         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    697         assertNotAggregated(rawContactId1, rawContactId2);
    698     }
    699 
    700     public void testNonAggregationFromSameAccountNoCommonData() {
    701         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    702         insertEmail(rawContactId1, "lightning1 (at) android.com");
    703         insertPhoneNumber(rawContactId1, "111-222-3333");
    704         insertIdentity(rawContactId1, "iden1", "namespace");
    705 
    706         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    707         insertEmail(rawContactId2, "lightning2 (at) android.com");
    708         insertPhoneNumber(rawContactId2, "555-666-7777");
    709         insertIdentity(rawContactId1, "iden2", "namespace");
    710 
    711         assertNotAggregated(rawContactId1, rawContactId2);
    712     }
    713 
    714     public void testAggregationFromSameAccountEmailSame() {
    715         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    716         insertEmail(rawContactId1, "lightning (at) android.com");
    717 
    718         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    719         insertEmail(rawContactId2, "lightning (at) android.com");
    720 
    721         assertAggregated(rawContactId1, rawContactId2);
    722     }
    723 
    724     public void testNonAggregationFromSameAccountEmailDifferent() {
    725         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    726         insertEmail(rawContactId1, "lightning1 (at) android.com");
    727 
    728         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    729         insertEmail(rawContactId2, "lightning2 (at) android.com");
    730         insertEmail(rawContactId2, "lightning3 (at) android.com");
    731 
    732         assertNotAggregated(rawContactId1, rawContactId2);
    733     }
    734 
    735     public void testAggregationFromSameAccountIdentitySame() {
    736         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    737         insertIdentity(rawContactId1, "iden", "namespace");
    738 
    739         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    740         insertIdentity(rawContactId2, "iden", "namespace");
    741 
    742         assertAggregated(rawContactId1, rawContactId2);
    743     }
    744 
    745     public void testNonAggregationFromSameAccountIdentityDifferent() {
    746         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    747         insertIdentity(rawContactId1, "iden1", "namespace1");
    748         insertIdentity(rawContactId1, "iden2", "namespace2");
    749 
    750         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    751         insertIdentity(rawContactId2, "iden2", "namespace1");
    752         insertIdentity(rawContactId2, "iden1", "namespace2");
    753 
    754         assertNotAggregated(rawContactId1, rawContactId2);
    755     }
    756 
    757     public void testAggregationFromSameAccountPhoneNumberSame() {
    758         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    759         insertPhoneNumber(rawContactId1, "111-222-3333");
    760 
    761         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    762         insertPhoneNumber(rawContactId2, "111-222-3333");
    763 
    764         assertAggregated(rawContactId1, rawContactId2);
    765     }
    766 
    767     public void testAggregationFromSameAccountPhoneNumberNormalizedSame() {
    768         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    769         insertPhoneNumber(rawContactId1, "111-222-3333");
    770 
    771         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    772         insertPhoneNumber(rawContactId2, "+1-111-222-3333");
    773 
    774         assertAggregated(rawContactId1, rawContactId2);
    775     }
    776 
    777     public void testNonAggregationFromSameAccountPhoneNumberDifferent() {
    778         long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    779         insertPhoneNumber(rawContactId1, "111-222-3333");
    780 
    781         long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_1);
    782         insertPhoneNumber(rawContactId2, "111-222-3334");
    783 
    784         assertNotAggregated(rawContactId1, rawContactId2);
    785     }
    786 
    787     public void testAggregationSuggestionsBasedOnName() {
    788         long rawContactId1 = createRawContact();
    789         insertStructuredName(rawContactId1, "Duane", null);
    790 
    791         // Exact name match
    792         long rawContactId2 = createRawContact();
    793         insertStructuredName(rawContactId2, "Duane", null);
    794         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    795                 rawContactId1, rawContactId2);
    796 
    797         // Edit distance == 0.84
    798         long rawContactId3 = createRawContact();
    799         insertStructuredName(rawContactId3, "Dwayne", null);
    800 
    801         // Edit distance == 0.6
    802         long rawContactId4 = createRawContact();
    803         insertStructuredName(rawContactId4, "Donny", null);
    804 
    805         long contactId1 = queryContactId(rawContactId1);
    806         long contactId2 = queryContactId(rawContactId2);
    807         long contactId3 = queryContactId(rawContactId3);
    808 
    809         assertSuggestions(contactId1, contactId2, contactId3);
    810     }
    811 
    812     public void testAggregationSuggestionsBasedOnPhoneNumber() {
    813 
    814         // Create two contacts that would not be aggregated because of name mismatch
    815         long rawContactId1 = createRawContact();
    816         insertStructuredName(rawContactId1, "Lord", "Farquaad");
    817         insertPhoneNumber(rawContactId1, "(888)555-1236");
    818 
    819         long rawContactId2 = createRawContact();
    820         insertStructuredName(rawContactId2, "Talking", "Donkey");
    821         insertPhoneNumber(rawContactId2, "1(888)555-1236");
    822 
    823         long contactId1 = queryContactId(rawContactId1);
    824         long contactId2 = queryContactId(rawContactId2);
    825         assertTrue(contactId1 != contactId2);
    826 
    827         assertSuggestions(contactId1, contactId2);
    828     }
    829 
    830     public void testAggregationSuggestionsBasedOnEmailAddress() {
    831 
    832         // Create two contacts that would not be aggregated because of name mismatch
    833         long rawContactId1 = createRawContact();
    834         insertStructuredName(rawContactId1, "Carl", "Fredricksen");
    835         insertEmail(rawContactId1, "up (at) android.com");
    836 
    837         long rawContactId2 = createRawContact();
    838         insertStructuredName(rawContactId2, "Charles", "Muntz");
    839         insertEmail(rawContactId2, "up (at) android.com");
    840 
    841         long contactId1 = queryContactId(rawContactId1);
    842         long contactId2 = queryContactId(rawContactId2);
    843         assertTrue(contactId1 != contactId2);
    844 
    845         assertSuggestions(contactId1, contactId2);
    846     }
    847 
    848     public void testAggregationSuggestionsBasedOnEmailAddressApproximateMatch() {
    849 
    850         // Create two contacts that would not be aggregated because of name mismatch
    851         long rawContactId1 = createRawContact();
    852         insertStructuredName(rawContactId1, "Bob", null);
    853         insertEmail(rawContactId1, "incredible (at) android.com");
    854 
    855         long rawContactId2 = createRawContact();
    856         insertStructuredName(rawContactId2, "Lucius", "Best");
    857         insertEmail(rawContactId2, "incrediball (at) android.com");
    858 
    859         long contactId1 = queryContactId(rawContactId1);
    860         long contactId2 = queryContactId(rawContactId2);
    861         assertTrue(contactId1 != contactId2);
    862 
    863         assertSuggestions(contactId1, contactId2);
    864     }
    865 
    866     public void testAggregationSuggestionsBasedOnNickname() {
    867         long rawContactId1 = createRawContact();
    868         insertStructuredName(rawContactId1, "Peter", "Parker");
    869         insertNickname(rawContactId1, "Spider-Man");
    870 
    871         long rawContactId2 = createRawContact();
    872         insertStructuredName(rawContactId2, "Manny", "Spider");
    873 
    874         long contactId1 = queryContactId(rawContactId1);
    875         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    876                 rawContactId1, rawContactId2);
    877 
    878         long contactId2 = queryContactId(rawContactId2);
    879         assertSuggestions(contactId1, contactId2);
    880     }
    881 
    882     public void testAggregationSuggestionsBasedOnNicknameMatchingName() {
    883         long rawContactId1 = createRawContact();
    884         insertStructuredName(rawContactId1, "Clark", "Kent");
    885         insertNickname(rawContactId1, "Superman");
    886 
    887         long rawContactId2 = createRawContact();
    888         insertStructuredName(rawContactId2, "Roy", "Williams");
    889         insertNickname(rawContactId2, "superman");
    890 
    891         long contactId1 = queryContactId(rawContactId1);
    892         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    893                 rawContactId1, rawContactId2);
    894 
    895         long contactId2 = queryContactId(rawContactId2);
    896         assertSuggestions(contactId1, contactId2);
    897     }
    898 
    899     public void testAggregationSuggestionsBasedOnCommonNickname() {
    900         long rawContactId1 = createRawContact();
    901         insertStructuredName(rawContactId1, "Dick", "Cherry");
    902 
    903         long rawContactId2 = createRawContact();
    904         insertStructuredName(rawContactId2, "Richard", "Cherry");
    905 
    906         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    907                 rawContactId1, rawContactId2);
    908 
    909         long contactId1 = queryContactId(rawContactId1);
    910         long contactId2 = queryContactId(rawContactId2);
    911         assertSuggestions(contactId1, contactId2);
    912     }
    913 
    914     public void testAggregationSuggestionsBasedOnPhoneNumberWithFilter() {
    915 
    916         // Create two contacts that would not be aggregated because of name mismatch
    917         long rawContactId1 = createRawContact();
    918         insertStructuredName(rawContactId1, "Lord", "Farquaad");
    919         insertPhoneNumber(rawContactId1, "(888)555-1236");
    920 
    921         long rawContactId2 = createRawContact();
    922         insertStructuredName(rawContactId2, "Talking", "Donkey");
    923         insertPhoneNumber(rawContactId2, "1(888)555-1236");
    924 
    925         long contactId1 = queryContactId(rawContactId1);
    926         long contactId2 = queryContactId(rawContactId2);
    927         assertTrue(contactId1 != contactId2);
    928 
    929         assertSuggestions(contactId1, "talk", contactId2);
    930         assertSuggestions(contactId1, "don", contactId2);
    931         assertSuggestions(contactId1, "", contactId2);
    932         assertSuggestions(contactId1, "eddie");
    933     }
    934 
    935     public void testAggregationSuggestionsDontSuggestInvisible() {
    936         long rawContactId1 = createRawContactWithName("first", "last", ACCOUNT_1);
    937         insertPhoneNumber(rawContactId1, "111-222-3333");
    938         insertNickname(rawContactId1, "Superman");
    939         insertEmail(rawContactId1, "incredible (at) android.com");
    940 
    941         // Create another with the exact same name, phone number, nickname and email.
    942         long rawContactId2 = createRawContactWithName("first", "last", ACCOUNT_2);
    943         insertPhoneNumber(rawContactId2, "111-222-3333");
    944         insertNickname(rawContactId2, "Superman");
    945         insertEmail(rawContactId2, "incredible (at) android.com");
    946 
    947         // The aggregator should have joined them.  Split them up.
    948         setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE,
    949                 rawContactId1, rawContactId2);
    950 
    951         long contactId1 = queryContactId(rawContactId1);
    952         long contactId2 = queryContactId(rawContactId2);
    953 
    954         // Make sure they're different contacts.
    955         MoreAsserts.assertNotEqual(contactId1, contactId2);
    956 
    957         // Contact 2 should be suggested.
    958         assertSuggestions(contactId1, contactId2);
    959 
    960         // Make contact 2 invisible.
    961         markInvisible(contactId2);
    962 
    963         // Now contact 2 shuldn't be suggested.
    964         assertSuggestions(contactId1, new long[0]);
    965     }
    966 
    967     public void testChoosePhotoSetBeforeAggregation() {
    968         long rawContactId1 = createRawContact();
    969         setContactAccount(rawContactId1, "donut", "donut_act");
    970         insertPhoto(rawContactId1);
    971 
    972         long rawContactId2 = createRawContact();
    973         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
    974         long cupcakeId = ContentUris.parseId(insertPhoto(rawContactId2));
    975 
    976         long rawContactId3 = createRawContact();
    977         setContactAccount(rawContactId3, "froyo", "froyo_act");
    978         insertPhoto(rawContactId3);
    979 
    980         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    981                 rawContactId1, rawContactId2);
    982         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    983                 rawContactId1, rawContactId3);
    984         assertEquals(cupcakeId, queryPhotoId(queryContactId(rawContactId2)));
    985     }
    986 
    987     public void testChoosePhotoSetAfterAggregation() {
    988         long rawContactId1 = createRawContact();
    989         setContactAccount(rawContactId1, "donut", "donut_act");
    990         insertPhoto(rawContactId1);
    991 
    992         long rawContactId2 = createRawContact();
    993         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
    994                 rawContactId1, rawContactId2);
    995         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
    996         long cupcakeId = ContentUris.parseId(insertPhoto(rawContactId2));
    997 
    998         long rawContactId3 = createRawContact();
    999         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1000                 rawContactId1, rawContactId3);
   1001         setContactAccount(rawContactId3, "froyo", "froyo_act");
   1002         insertPhoto(rawContactId3);
   1003 
   1004         assertEquals(cupcakeId, queryPhotoId(queryContactId(rawContactId2)));
   1005     }
   1006 
   1007     // Note that for the following tests of photo aggregation, the accounts are being used to
   1008     // set the typical photo priority that each raw contact would have, based on
   1009     // SynchronousContactsProvider2.createPhotoPriorityResolver.  The relative priorities
   1010     // specified there are:
   1011     // cupcake: 3
   1012     // donut: 2
   1013     // froyo: 1
   1014     // <other>: 0
   1015 
   1016     public void testChooseLargerPhotoByDimensions() {
   1017         // Donut photo is 256x256.
   1018         long rawContactId1 = createRawContact();
   1019         setContactAccount(rawContactId1, "donut", "donut_act");
   1020         long normalEarthDataId = ContentUris.parseId(
   1021                 insertPhoto(rawContactId1, R.drawable.earth_normal));
   1022         long normalEarthPhotoFileId = getStoredLongValue(
   1023                 ContentUris.withAppendedId(Data.CONTENT_URI, normalEarthDataId),
   1024                 Photo.PHOTO_FILE_ID);
   1025 
   1026         // Cupcake would normally have priority, but its photo is 200x200.
   1027         long rawContactId2 = createRawContact();
   1028         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
   1029         insertPhoto(rawContactId2, R.drawable.earth_200);
   1030 
   1031         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1032                 rawContactId1, rawContactId2);
   1033 
   1034         // Larger photo (by dimensions) wins.
   1035         assertEquals(normalEarthPhotoFileId, queryPhotoFileId(queryContactId(rawContactId1)));
   1036     }
   1037 
   1038     public void testChooseLargerPhotoByFileSize() {
   1039         // Donut photo is a 256x256 photo of a nebula.
   1040         long rawContactId1 = createRawContact();
   1041         setContactAccount(rawContactId1, "donut", "donut_act");
   1042         long nebulaDataId = ContentUris.parseId(
   1043                 insertPhoto(rawContactId1, R.drawable.nebula));
   1044         long nebulaPhotoFileId = getStoredLongValue(
   1045                 ContentUris.withAppendedId(Data.CONTENT_URI, nebulaDataId),
   1046                 Photo.PHOTO_FILE_ID);
   1047 
   1048         // Cupcake would normally have priority, but its photo (of a galaxy) has the same dimensions
   1049         // as Donut's, but a smaller filesize.
   1050         long rawContactId2 = createRawContact();
   1051         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
   1052         insertPhoto(rawContactId2, R.drawable.galaxy);
   1053 
   1054         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1055                 rawContactId1, rawContactId2);
   1056 
   1057         // Larger photo (by filesize) wins.
   1058         assertEquals(nebulaPhotoFileId, queryPhotoFileId(queryContactId(rawContactId1)));
   1059     }
   1060 
   1061     public void testChooseFilePhotoOverThumbnail() {
   1062         // Donut photo is a 256x256 photo of Earth.
   1063         long rawContactId1 = createRawContact();
   1064         setContactAccount(rawContactId1, "donut", "donut_act");
   1065         long normalEarthDataId = ContentUris.parseId(
   1066                 insertPhoto(rawContactId1, R.drawable.earth_normal));
   1067         long normalEarthPhotoFileId = getStoredLongValue(
   1068                 ContentUris.withAppendedId(Data.CONTENT_URI, normalEarthDataId),
   1069                 Photo.PHOTO_FILE_ID);
   1070 
   1071         // Cupcake would normally have priority, but its photo of Earth is thumbnail-sized.
   1072         long rawContactId2 = createRawContact();
   1073         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
   1074         insertPhoto(rawContactId2, R.drawable.earth_small);
   1075 
   1076         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1077                 rawContactId1, rawContactId2);
   1078 
   1079         // Larger photo (by filesize) wins.
   1080         assertEquals(normalEarthPhotoFileId, queryPhotoFileId(queryContactId(rawContactId1)));
   1081     }
   1082 
   1083     public void testFallbackToAccountPriorityForSamePhoto() {
   1084         // Donut photo is a 256x256 photo of Earth.
   1085         long rawContactId1 = createRawContact();
   1086         setContactAccount(rawContactId1, "donut", "donut_act");
   1087         insertPhoto(rawContactId1, R.drawable.earth_normal);
   1088 
   1089         // Cupcake has the same 256x256 photo of Earth.
   1090         long rawContactId2 = createRawContact();
   1091         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
   1092         long cupcakeEarthDataId = ContentUris.parseId(
   1093                 insertPhoto(rawContactId2, R.drawable.earth_normal));
   1094         long cupcakeEarthPhotoFileId = getStoredLongValue(
   1095                 ContentUris.withAppendedId(Data.CONTENT_URI, cupcakeEarthDataId),
   1096                 Photo.PHOTO_FILE_ID);
   1097 
   1098         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1099                 rawContactId1, rawContactId2);
   1100 
   1101         // Cupcake's version of the photo wins, falling back to account priority.
   1102         assertEquals(cupcakeEarthPhotoFileId, queryPhotoFileId(queryContactId(rawContactId1)));
   1103     }
   1104 
   1105     public void testFallbackToAccountPriorityForDifferingThumbnails() {
   1106         // Donut photo is a 96x96 thumbnail of Earth.
   1107         long rawContactId1 = createRawContact();
   1108         setContactAccount(rawContactId1, "donut", "donut_act");
   1109         insertPhoto(rawContactId1, R.drawable.earth_small);
   1110 
   1111         // Cupcake photo is the 96x96 "no contact" placeholder (smaller filesize than the Earth
   1112         // picture, but thumbnail filesizes are ignored in the aggregator).
   1113         long rawContactId2 = createRawContact();
   1114         setContactAccount(rawContactId2, "cupcake", "cupcake_act");
   1115         long cupcakeDataId = ContentUris.parseId(
   1116                 insertPhoto(rawContactId2, R.drawable.ic_contact_picture));
   1117 
   1118         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER,
   1119                 rawContactId1, rawContactId2);
   1120 
   1121         // The Cupcake thumbnail wins, by account priority..
   1122         assertEquals(cupcakeDataId, queryPhotoId(queryContactId(rawContactId1)));
   1123     }
   1124 
   1125     public void testDisplayNameSources() {
   1126         long rawContactId = createRawContact();
   1127         long contactId = queryContactId(rawContactId);
   1128 
   1129         assertNull(queryDisplayName(contactId));
   1130 
   1131         insertEmail(rawContactId, "eclair (at) android.com");
   1132         assertEquals("eclair (at) android.com", queryDisplayName(contactId));
   1133 
   1134         insertPhoneNumber(rawContactId, "800-555-5555");
   1135         assertEquals("800-555-5555", queryDisplayName(contactId));
   1136 
   1137         ContentValues values = new ContentValues();
   1138         values.put(Organization.COMPANY, "Android");
   1139         insertOrganization(rawContactId, values);
   1140         assertEquals("Android", queryDisplayName(contactId));
   1141 
   1142         insertNickname(rawContactId, "Dro");
   1143         assertEquals("Dro", queryDisplayName(contactId));
   1144 
   1145         values.clear();
   1146         values.put(StructuredName.GIVEN_NAME, "Eclair");
   1147         values.put(StructuredName.FAMILY_NAME, "Android");
   1148         insertStructuredName(rawContactId, values);
   1149         assertEquals("Eclair Android", queryDisplayName(contactId));
   1150     }
   1151 
   1152     public void testVerifiedName() {
   1153         long rawContactId1 = createRawContactWithName("test1", "TEST1", ACCOUNT_1);
   1154         storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.NAME_VERIFIED, "1");
   1155         long rawContactId2 = createRawContactWithName("test2", "TEST2", ACCOUNT_2);
   1156         long rawContactId3 = createRawContactWithName("test3", "TEST3 LONG", ACCOUNT_3);
   1157 
   1158         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1,
   1159                 rawContactId2);
   1160         setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1,
   1161                 rawContactId3);
   1162 
   1163         long contactId = queryContactId(rawContactId1);
   1164 
   1165         // Should be the verified name
   1166         assertEquals("test1 TEST1", queryDisplayName(contactId));
   1167 
   1168         // Mark a different name as verified - this should reset the NAME_VERIFIED field
   1169         // for the other rawContacts
   1170         storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.NAME_VERIFIED, "1");
   1171         assertStoredValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.NAME_VERIFIED, 0);
   1172         assertEquals("test2 TEST2", queryDisplayName(contactId));
   1173 
   1174         // Reset the NAME_VERIFIED flag - now the most complex of the three names should win
   1175         storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.NAME_VERIFIED, "0");
   1176         assertEquals("test3 TEST3 LONG", queryDisplayName(contactId));
   1177     }
   1178 
   1179     public void testAggregationModeSuspendedSeparateTransactions() {
   1180 
   1181         // Setting aggregation mode to SUSPENDED should prevent aggregation from happening
   1182         long rawContactId1 = createRawContact(ACCOUNT_1);
   1183         storeValue(RawContacts.CONTENT_URI, rawContactId1,
   1184                 RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
   1185         Uri name1 = insertStructuredName(rawContactId1, "THE", "SAME");
   1186 
   1187         long rawContactId2 = createRawContact(ACCOUNT_2);
   1188         storeValue(RawContacts.CONTENT_URI, rawContactId2,
   1189                 RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
   1190         insertStructuredName(rawContactId2, "THE", "SAME");
   1191 
   1192         assertNotAggregated(rawContactId1, rawContactId2);
   1193 
   1194         // Changing aggregation mode to DEFAULT should change nothing
   1195         storeValue(RawContacts.CONTENT_URI, rawContactId1,
   1196                 RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT);
   1197         storeValue(RawContacts.CONTENT_URI, rawContactId2,
   1198                 RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT);
   1199         assertNotAggregated(rawContactId1, rawContactId2);
   1200 
   1201         // Changing the name should trigger aggregation
   1202         storeValue(name1, StructuredName.GIVEN_NAME, "the");
   1203         assertAggregated(rawContactId1, rawContactId2);
   1204     }
   1205 
   1206     public void testAggregationModeInitializedAsSuspended() throws Exception {
   1207 
   1208         // Setting aggregation mode to SUSPENDED should prevent aggregation from happening
   1209         ContentProviderOperation cpo1 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1210                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1211                 .build();
   1212         ContentProviderOperation cpo2 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1213                 .withValueBackReference(Data.RAW_CONTACT_ID, 0)
   1214                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1215                 .withValue(StructuredName.GIVEN_NAME, "John")
   1216                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1217                 .build();
   1218         ContentProviderOperation cpo3 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1219                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1220                 .build();
   1221         ContentProviderOperation cpo4 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1222                 .withValueBackReference(Data.RAW_CONTACT_ID, 2)
   1223                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1224                 .withValue(StructuredName.GIVEN_NAME, "John")
   1225                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1226                 .build();
   1227         ContentProviderOperation cpo5 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1228                 .withSelection(RawContacts._ID + "=?", new String[1])
   1229                 .withSelectionBackReference(0, 0)
   1230                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT)
   1231                 .build();
   1232         ContentProviderOperation cpo6 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1233                 .withSelection(RawContacts._ID + "=?", new String[1])
   1234                 .withSelectionBackReference(0, 2)
   1235                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT)
   1236                 .build();
   1237 
   1238         ContentProviderResult[] results =
   1239                 mResolver.applyBatch(ContactsContract.AUTHORITY,
   1240                         Lists.newArrayList(cpo1, cpo2, cpo3, cpo4, cpo5, cpo6));
   1241 
   1242         long rawContactId1 = ContentUris.parseId(results[0].uri);
   1243         long rawContactId2 = ContentUris.parseId(results[2].uri);
   1244 
   1245         assertNotAggregated(rawContactId1, rawContactId2);
   1246     }
   1247 
   1248     public void testAggregationModeUpdatedToSuspended() throws Exception {
   1249 
   1250         // Setting aggregation mode to SUSPENDED should prevent aggregation from happening
   1251         ContentProviderOperation cpo1 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1252                 .withValues(new ContentValues())
   1253                 .build();
   1254         ContentProviderOperation cpo2 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1255                 .withValueBackReference(Data.RAW_CONTACT_ID, 0)
   1256                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1257                 .withValue(StructuredName.GIVEN_NAME, "John")
   1258                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1259                 .build();
   1260         ContentProviderOperation cpo3 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1261                 .withValues(new ContentValues())
   1262                 .build();
   1263         ContentProviderOperation cpo4 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1264                 .withValueBackReference(Data.RAW_CONTACT_ID, 2)
   1265                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1266                 .withValue(StructuredName.GIVEN_NAME, "John")
   1267                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1268                 .build();
   1269         ContentProviderOperation cpo5 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1270                 .withSelection(RawContacts._ID + "=?", new String[1])
   1271                 .withSelectionBackReference(0, 0)
   1272                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1273                 .build();
   1274         ContentProviderOperation cpo6 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1275                 .withSelection(RawContacts._ID + "=?", new String[1])
   1276                 .withSelectionBackReference(0, 2)
   1277                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1278                 .build();
   1279 
   1280         ContentProviderResult[] results =
   1281                 mResolver.applyBatch(ContactsContract.AUTHORITY,
   1282                         Lists.newArrayList(cpo1, cpo2, cpo3, cpo4, cpo5, cpo6));
   1283 
   1284         long rawContactId1 = ContentUris.parseId(results[0].uri);
   1285         long rawContactId2 = ContentUris.parseId(results[2].uri);
   1286 
   1287         assertNotAggregated(rawContactId1, rawContactId2);
   1288     }
   1289 
   1290     public void testAggregationModeSuspendedOverriddenByAggException() throws Exception {
   1291         ContentProviderOperation cpo1 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1292                 .withValue(RawContacts.ACCOUNT_NAME, "a")
   1293                 .withValue(RawContacts.ACCOUNT_TYPE, "b")
   1294                 .build();
   1295         ContentProviderOperation cpo2 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1296                 .withValueBackReference(Data.RAW_CONTACT_ID, 0)
   1297                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1298                 .withValue(StructuredName.GIVEN_NAME, "John")
   1299                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1300                 .build();
   1301         ContentProviderOperation cpo3 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   1302                 .withValue(RawContacts.ACCOUNT_NAME, "c")
   1303                 .withValue(RawContacts.ACCOUNT_TYPE, "d")
   1304                 .build();
   1305         ContentProviderOperation cpo4 = ContentProviderOperation.newInsert(Data.CONTENT_URI)
   1306                 .withValueBackReference(Data.RAW_CONTACT_ID, 2)
   1307                 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
   1308                 .withValue(StructuredName.GIVEN_NAME, "John")
   1309                 .withValue(StructuredName.FAMILY_NAME, "Doe")
   1310                 .build();
   1311         ContentProviderOperation cpo5 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1312                 .withSelection(RawContacts._ID + "=?", new String[1])
   1313                 .withSelectionBackReference(0, 0)
   1314                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1315                 .build();
   1316         ContentProviderOperation cpo6 = ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
   1317                 .withSelection(RawContacts._ID + "=?", new String[1])
   1318                 .withSelectionBackReference(0, 2)
   1319                 .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED)
   1320                 .build();
   1321 
   1322         // Checking that aggregation mode SUSPENDED should be overridden by inserting
   1323         // an explicit aggregation exception
   1324         ContentProviderOperation cpo7 =
   1325                 ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI)
   1326                 .withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1, 0)
   1327                 .withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, 2)
   1328                 .withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER)
   1329                 .build();
   1330 
   1331         ContentProviderResult[] results =
   1332                 mResolver.applyBatch(ContactsContract.AUTHORITY,
   1333                         Lists.newArrayList(cpo1, cpo2, cpo3, cpo4, cpo5, cpo6, cpo7));
   1334 
   1335         long rawContactId1 = ContentUris.parseId(results[0].uri);
   1336         long rawContactId2 = ContentUris.parseId(results[2].uri);
   1337 
   1338         assertAggregated(rawContactId1, rawContactId2);
   1339     }
   1340 
   1341     public void testAggregationSuggestionsQueryBuilderWithContactId() throws Exception {
   1342         Uri uri = AggregationSuggestions.builder().setContactId(12).setLimit(7).build();
   1343         assertEquals("content://com.android.contacts/contacts/12/suggestions?limit=7",
   1344                 uri.toString());
   1345     }
   1346 
   1347     public void testAggregationSuggestionsQueryBuilderWithValues() throws Exception {
   1348         Uri uri = AggregationSuggestions.builder()
   1349                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_NAME, "name1")
   1350                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_NAME, "name2")
   1351                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_EMAIL, "email1")
   1352                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_EMAIL, "email2")
   1353                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_PHONE, "phone1")
   1354                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_NICKNAME, "nickname1")
   1355                 .setLimit(7)
   1356                 .build();
   1357         assertEquals("content://com.android.contacts/contacts/0/suggestions?"
   1358                 + "limit=7"
   1359                 + "&query=name%3Aname1"
   1360                 + "&query=name%3Aname2"
   1361                 + "&query=email%3Aemail1"
   1362                 + "&query=email%3Aemail2"
   1363                 + "&query=phone%3Aphone1"
   1364                 + "&query=nickname%3Anickname1", uri.toString());
   1365     }
   1366 
   1367     public void testAggregatedStatusUpdate() {
   1368         long rawContactId1 = createRawContact();
   1369         Uri dataUri1 = insertStructuredName(rawContactId1, "john", "doe");
   1370         insertStatusUpdate(ContentUris.parseId(dataUri1), StatusUpdates.AWAY, "Green", 100,
   1371                 StatusUpdates.CAPABILITY_HAS_CAMERA);
   1372         long rawContactId2 = createRawContact();
   1373         Uri dataUri2 = insertStructuredName(rawContactId2, "john", "doe");
   1374         insertStatusUpdate(ContentUris.parseId(dataUri2), StatusUpdates.AVAILABLE, "Red", 50,
   1375                 StatusUpdates.CAPABILITY_HAS_CAMERA);
   1376         setAggregationException(
   1377                 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2);
   1378 
   1379         assertStoredValue(getContactUriForRawContact(rawContactId1),
   1380                 Contacts.CONTACT_STATUS, "Green");
   1381 
   1382         // When we split these two raw contacts, their respective statuses should be restored
   1383         setAggregationException(
   1384                 AggregationExceptions.TYPE_KEEP_SEPARATE, rawContactId1, rawContactId2);
   1385 
   1386         assertStoredValue(getContactUriForRawContact(rawContactId1),
   1387                 Contacts.CONTACT_STATUS, "Green");
   1388 
   1389         assertStoredValue(getContactUriForRawContact(rawContactId2),
   1390                 Contacts.CONTACT_STATUS, "Red");
   1391     }
   1392 
   1393     public void testAggregationSuggestionsByName() throws Exception {
   1394         long rawContactId1 = createRawContactWithName("first1", "last1");
   1395         long rawContactId2 = createRawContactWithName("first2", "last2");
   1396 
   1397         Uri uri = AggregationSuggestions.builder()
   1398                 .addParameter(AggregationSuggestions.PARAMETER_MATCH_NAME, "last1 first1")
   1399                 .build();
   1400 
   1401         Cursor cursor = mResolver.query(
   1402                 uri, new String[] { Contacts._ID, Contacts.DISPLAY_NAME }, null, null, null);
   1403 
   1404         assertEquals(1, cursor.getCount());
   1405 
   1406         cursor.moveToFirst();
   1407 
   1408         ContentValues values = new ContentValues();
   1409         values.put(Contacts._ID, queryContactId(rawContactId1));
   1410         values.put(Contacts.DISPLAY_NAME, "first1 last1");
   1411         assertCursorValues(cursor, values);
   1412         cursor.close();
   1413     }
   1414 
   1415     private void assertSuggestions(long contactId, long... suggestions) {
   1416         final Uri aggregateUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
   1417         Uri uri = Uri.withAppendedPath(aggregateUri,
   1418                 Contacts.AggregationSuggestions.CONTENT_DIRECTORY);
   1419         assertSuggestions(uri, suggestions);
   1420     }
   1421 
   1422     private void assertSuggestions(long contactId, String filter, long... suggestions) {
   1423         final Uri aggregateUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
   1424         Uri uri = Uri.withAppendedPath(Uri.withAppendedPath(aggregateUri,
   1425                 Contacts.AggregationSuggestions.CONTENT_DIRECTORY), Uri.encode(filter));
   1426         assertSuggestions(uri, suggestions);
   1427     }
   1428 
   1429     private void assertSuggestions(Uri uri, long... suggestions) {
   1430         final Cursor cursor = mResolver.query(uri,
   1431                 new String[] { Contacts._ID, Contacts.CONTACT_PRESENCE },
   1432                 null, null, null);
   1433 
   1434         try {
   1435             assertEquals(suggestions.length, cursor.getCount());
   1436 
   1437             for (int i = 0; i < suggestions.length; i++) {
   1438                 cursor.moveToNext();
   1439                 assertEquals(suggestions[i], cursor.getLong(0));
   1440             }
   1441         } finally {
   1442             TestUtils.dumpCursor(cursor);
   1443         }
   1444 
   1445         cursor.close();
   1446     }
   1447 
   1448     private void assertDisplayNameEquals(long contactId, long rawContactId) {
   1449 
   1450         String contactDisplayName = queryDisplayName(contactId);
   1451 
   1452         Cursor c = queryRawContact(rawContactId);
   1453         assertTrue(c.moveToFirst());
   1454         String rawDisplayName = c.getString(c.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY));
   1455         c.close();
   1456 
   1457         assertTrue(contactDisplayName != null);
   1458         assertTrue(rawDisplayName != null);
   1459         assertEquals(rawDisplayName, contactDisplayName);
   1460     }
   1461 }
   1462