ContactsProvider2Test.java revision 627152453c692915ac79191acd1d2d2a4dd6fb0d
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 17package com.android.providers.contacts; 18 19import com.android.internal.util.ArrayUtils; 20import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 21 22import android.accounts.Account; 23import android.content.ContentUris; 24import android.content.ContentValues; 25import android.content.Entity; 26import android.content.EntityIterator; 27import android.database.Cursor; 28import android.net.Uri; 29import android.os.RemoteException; 30import android.provider.ContactsContract; 31import android.provider.LiveFolders; 32import android.provider.ContactsContract.AggregationExceptions; 33import android.provider.ContactsContract.Contacts; 34import android.provider.ContactsContract.Data; 35import android.provider.ContactsContract.Groups; 36import android.provider.ContactsContract.PhoneLookup; 37import android.provider.ContactsContract.RawContacts; 38import android.provider.ContactsContract.Settings; 39import android.provider.ContactsContract.StatusUpdates; 40import android.provider.ContactsContract.CommonDataKinds.Email; 41import android.provider.ContactsContract.CommonDataKinds.GroupMembership; 42import android.provider.ContactsContract.CommonDataKinds.Im; 43import android.provider.ContactsContract.CommonDataKinds.Organization; 44import android.provider.ContactsContract.CommonDataKinds.Phone; 45import android.provider.ContactsContract.CommonDataKinds.Photo; 46import android.provider.ContactsContract.CommonDataKinds.StructuredName; 47import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 48import android.test.MoreAsserts; 49import android.test.suitebuilder.annotation.LargeTest; 50 51 52/** 53 * Unit tests for {@link ContactsProvider2}. 54 * 55 * Run the test like this: 56 * <code> 57 * adb shell am instrument -e class com.android.providers.contacts.ContactsProvider2Test -w \ 58 * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner 59 * </code> 60 */ 61@LargeTest 62public class ContactsProvider2Test extends BaseContactsProvider2Test { 63 64 public void testRawContactsInsert() { 65 ContentValues values = new ContentValues(); 66 67 values.put(RawContacts.ACCOUNT_NAME, "a"); 68 values.put(RawContacts.ACCOUNT_TYPE, "b"); 69 values.put(RawContacts.SOURCE_ID, "c"); 70 values.put(RawContacts.VERSION, 42); 71 values.put(RawContacts.DIRTY, 1); 72 values.put(RawContacts.DELETED, 1); 73 values.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 74 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 75 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 76 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 77 values.put(RawContacts.STARRED, 1); 78 values.put(RawContacts.SYNC1, "e"); 79 values.put(RawContacts.SYNC2, "f"); 80 values.put(RawContacts.SYNC3, "g"); 81 values.put(RawContacts.SYNC4, "h"); 82 83 Uri rowUri = mResolver.insert(RawContacts.CONTENT_URI, values); 84 long rawContactId = ContentUris.parseId(rowUri); 85 86 assertStoredValues(rowUri, values); 87 assertSelection(RawContacts.CONTENT_URI, values, RawContacts._ID, rawContactId); 88 assertNetworkNotified(true); 89 } 90 91 public void testDataInsert() { 92 long rawContactId = createRawContactWithName("John", "Doe"); 93 94 ContentValues values = new ContentValues(); 95 putDataValues(values, rawContactId); 96 Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 97 long dataId = ContentUris.parseId(dataUri); 98 99 long contactId = queryContactId(rawContactId); 100 values.put(RawContacts.CONTACT_ID, contactId); 101 assertStoredValues(dataUri, values); 102 103 assertSelection(Data.CONTENT_URI, values, Data._ID, dataId); 104 105 // Access the same data through the directory under RawContacts 106 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 107 Uri rawContactDataUri = 108 Uri.withAppendedPath(rawContactUri, RawContacts.Data.CONTENT_DIRECTORY); 109 assertSelection(rawContactDataUri, values, Data._ID, dataId); 110 111 // Access the same data through the directory under Contacts 112 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 113 Uri contactDataUri = Uri.withAppendedPath(contactUri, Contacts.Data.CONTENT_DIRECTORY); 114 assertSelection(contactDataUri, values, Data._ID, dataId); 115 assertNetworkNotified(true); 116 } 117 118 public void testRawContactDataQuery() { 119 Account account1 = new Account("a", "b"); 120 Account account2 = new Account("c", "d"); 121 long rawContactId1 = createRawContact(account1); 122 Uri dataUri1 = insertStructuredName(rawContactId1, "John", "Doe"); 123 long rawContactId2 = createRawContact(account2); 124 Uri dataUri2 = insertStructuredName(rawContactId2, "Jane", "Doe"); 125 126 Uri uri1 = maybeAddAccountQueryParameters(dataUri1, account1); 127 Uri uri2 = maybeAddAccountQueryParameters(dataUri2, account2); 128 assertStoredValue(uri1, Data._ID, ContentUris.parseId(dataUri1)) ; 129 assertStoredValue(uri2, Data._ID, ContentUris.parseId(dataUri2)) ; 130 } 131 132 public void testPhonesQuery() { 133 134 ContentValues values = new ContentValues(); 135 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 136 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 137 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 138 values.put(RawContacts.TIMES_CONTACTED, 54321); 139 values.put(RawContacts.STARRED, 1); 140 141 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 142 long rawContactId = ContentUris.parseId(rawContactUri); 143 144 insertStructuredName(rawContactId, "Meghan", "Knox"); 145 Uri uri = insertPhoneNumber(rawContactId, "18004664411"); 146 long phoneId = ContentUris.parseId(uri); 147 148 149 long contactId = queryContactId(rawContactId); 150 values.clear(); 151 values.put(Data._ID, phoneId); 152 values.put(Data.RAW_CONTACT_ID, rawContactId); 153 values.put(RawContacts.CONTACT_ID, contactId); 154 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 155 values.put(Phone.NUMBER, "18004664411"); 156 values.put(Phone.TYPE, Phone.TYPE_HOME); 157 values.putNull(Phone.LABEL); 158 values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 159 values.put(Contacts.CUSTOM_RINGTONE, "d"); 160 values.put(Contacts.SEND_TO_VOICEMAIL, 1); 161 values.put(Contacts.LAST_TIME_CONTACTED, 12345); 162 values.put(Contacts.TIMES_CONTACTED, 54321); 163 values.put(Contacts.STARRED, 1); 164 165 assertStoredValues(ContentUris.withAppendedId(Phone.CONTENT_URI, phoneId), values); 166 assertSelection(Phone.CONTENT_URI, values, Data._ID, phoneId); 167 } 168 169 public void testPhonesFilterQuery() { 170 long rawContactId1 = createRawContactWithName("Hot", "Tamale"); 171 insertPhoneNumber(rawContactId1, "18004664411"); 172 insertPhoneNumber(rawContactId1, "1-800-466-4411"); 173 174 long rawContactId2 = createRawContactWithName("Hot", "Tamale"); 175 insertPhoneNumber(rawContactId2, "1-800-466-4411"); 176 177 forceAggregation(); 178 179 Uri filterUri1 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "tamale"); 180 ContentValues values = new ContentValues(); 181 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 182 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 183 values.put(Phone.NUMBER, "1-800-466-4411"); 184 values.put(Phone.TYPE, Phone.TYPE_HOME); 185 values.putNull(Phone.LABEL); 186 assertStoredValuesWithProjection(filterUri1, values); 187 188 Uri filterUri2 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1-800-GOOG-411"); 189 assertStoredValues(filterUri2, values); 190 191 Uri filterUri3 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "18004664"); 192 assertStoredValues(filterUri3, values); 193 194 Uri filterUri4 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "encilada"); 195 assertEquals(0, getCount(filterUri4, null, null)); 196 } 197 198 public void testPhoneLookup() { 199 ContentValues values = new ContentValues(); 200 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 201 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 202 203 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 204 long rawContactId = ContentUris.parseId(rawContactUri); 205 206 insertStructuredName(rawContactId, "Hot", "Tamale"); 207 insertPhoneNumber(rawContactId, "18004664411"); 208 209 Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 210 211 values.clear(); 212 values.put(PhoneLookup._ID, queryContactId(rawContactId)); 213 values.put(PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 214 values.put(PhoneLookup.NUMBER, "18004664411"); 215 values.put(PhoneLookup.TYPE, Phone.TYPE_HOME); 216 values.putNull(PhoneLookup.LABEL); 217 values.put(PhoneLookup.CUSTOM_RINGTONE, "d"); 218 values.put(PhoneLookup.SEND_TO_VOICEMAIL, 1); 219 assertStoredValues(lookupUri1, values); 220 221 // The strict comparation, adopted in Donut, does not allow the behavior like 222 // "8004664411 == 4664411", while the loose comparation, which had been used in Cupcake 223 // and reverted back into the default in Eclair, allows it. Hmm... 224 final boolean useStrictComparation = 225 mContext.getResources().getBoolean( 226 com.android.internal.R.bool.config_use_strict_phone_number_comparation); 227 final int expectedResult = (useStrictComparation ? 0 : 1); 228 229 Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "4664411"); 230 assertEquals(expectedResult, getCount(lookupUri2, null, null)); 231 } 232 233 public void testPhoneUpdate() { 234 ContentValues values = new ContentValues(); 235 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 236 long rawContactId = ContentUris.parseId(rawContactUri); 237 238 insertStructuredName(rawContactId, "Hot", "Tamale"); 239 Uri phoneUri = insertPhoneNumber(rawContactId, "18004664411"); 240 241 Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 242 assertStoredValue(lookupUri1, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 243 244 values.clear(); 245 values.put(Phone.NUMBER, "18004664422"); 246 mResolver.update(phoneUri, values, null, null); 247 248 Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664422"); 249 assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 250 251 // Setting number to null will remove the phone lookup record 252 values.clear(); 253 values.putNull(Phone.NUMBER); 254 mResolver.update(phoneUri, values, null, null); 255 256 assertEquals(0, getCount(lookupUri2, null, null)); 257 258 // Let's restore that phone lookup record 259 values.clear(); 260 values.put(Phone.NUMBER, "18004664422"); 261 mResolver.update(phoneUri, values, null, null); 262 assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 263 assertNetworkNotified(true); 264 } 265 266 public void testEmailsQuery() { 267 ContentValues values = new ContentValues(); 268 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 269 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 270 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 271 values.put(RawContacts.TIMES_CONTACTED, 54321); 272 values.put(RawContacts.STARRED, 1); 273 274 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 275 long rawContactId = ContentUris.parseId(rawContactUri); 276 277 insertStructuredName(rawContactId, "Meghan", "Knox"); 278 Uri uri = insertEmail(rawContactId, "meghan@acme.com"); 279 long emailId = ContentUris.parseId(uri); 280 281 long contactId = queryContactId(rawContactId); 282 values.clear(); 283 values.put(Data._ID, emailId); 284 values.put(Data.RAW_CONTACT_ID, rawContactId); 285 values.put(RawContacts.CONTACT_ID, contactId); 286 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 287 values.put(Email.DATA, "meghan@acme.com"); 288 values.put(Email.TYPE, Email.TYPE_HOME); 289 values.putNull(Email.LABEL); 290 values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 291 values.put(Contacts.CUSTOM_RINGTONE, "d"); 292 values.put(Contacts.SEND_TO_VOICEMAIL, 1); 293 values.put(Contacts.LAST_TIME_CONTACTED, 12345); 294 values.put(Contacts.TIMES_CONTACTED, 54321); 295 values.put(Contacts.STARRED, 1); 296 297 assertStoredValues(ContentUris.withAppendedId(Email.CONTENT_URI, emailId), values); 298 assertSelection(Email.CONTENT_URI, values, Data._ID, emailId); 299 } 300 301 public void testEmailsLookupQuery() { 302 long rawContactId = createRawContactWithName("Hot", "Tamale"); 303 insertEmail(rawContactId, "tamale@acme.com"); 304 305 Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "tamale@acme.com"); 306 ContentValues values = new ContentValues(); 307 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 308 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 309 values.put(Email.DATA, "tamale@acme.com"); 310 values.put(Email.TYPE, Email.TYPE_HOME); 311 values.putNull(Email.LABEL); 312 assertStoredValues(filterUri1, values); 313 314 Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "encilada@acme.com"); 315 assertEquals(0, getCount(filterUri2, null, null)); 316 } 317 318 public void testEmailsFilterQuery() { 319 long rawContactId1 = createRawContactWithName("Hot", "Tamale"); 320 insertEmail(rawContactId1, "tamale@acme.com"); 321 insertEmail(rawContactId1, "tamale@acme.com"); 322 323 long rawContactId2 = createRawContactWithName("Hot", "Tamale"); 324 insertEmail(rawContactId2, "tamale@acme.com"); 325 forceAggregation(); 326 327 Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tam"); 328 ContentValues values = new ContentValues(); 329 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 330 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 331 values.put(Email.DATA, "tamale@acme.com"); 332 values.put(Email.TYPE, Email.TYPE_HOME); 333 values.putNull(Email.LABEL); 334 assertStoredValuesWithProjection(filterUri1, values); 335 336 Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hot"); 337 assertStoredValuesWithProjection(filterUri2, values); 338 339 Uri filterUri3 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hottamale"); 340 assertStoredValuesWithProjection(filterUri3, values); 341 342 Uri filterUri4 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tamale@acme"); 343 assertStoredValuesWithProjection(filterUri4, values); 344 345 Uri filterUri5 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "encilada"); 346 assertEquals(0, getCount(filterUri5, null, null)); 347 } 348 349 public void testPostalsQuery() { 350 long rawContactId = createRawContactWithName("Alice", "Nextore"); 351 Uri dataUri = insertPostalAddress(rawContactId, "1600 Amphiteatre Ave, Mountain View"); 352 long dataId = ContentUris.parseId(dataUri); 353 354 long contactId = queryContactId(rawContactId); 355 ContentValues values = new ContentValues(); 356 values.put(Data._ID, dataId); 357 values.put(Data.RAW_CONTACT_ID, rawContactId); 358 values.put(RawContacts.CONTACT_ID, contactId); 359 values.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); 360 values.put(StructuredPostal.FORMATTED_ADDRESS, "1600 Amphiteatre Ave, Mountain View"); 361 values.put(Contacts.DISPLAY_NAME, "Alice Nextore"); 362 363 assertStoredValues(ContentUris.withAppendedId(StructuredPostal.CONTENT_URI, dataId), 364 values); 365 assertSelection(StructuredPostal.CONTENT_URI, values, Data._ID, dataId); 366 } 367 368 public void testQueryContactData() { 369 ContentValues values = new ContentValues(); 370 long contactId = createContact(values, "John", "Doe", 371 "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0); 372 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 373 374 assertStoredValues(contactUri, values); 375 assertSelection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 376 } 377 378 public void testQueryContactWithStatusUpdate() { 379 ContentValues values = new ContentValues(); 380 long contactId = createContact(values, "John", "Doe", 381 "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0); 382 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 383 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 384 assertStoredValuesWithProjection(contactUri, values); 385 assertSelectionWithProjection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 386 } 387 388 public void testQueryContactFilterData() { 389 ContentValues values = new ContentValues(); 390 createContact(values, "Stu", "Goulash", "18004664411", 391 "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0); 392 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 393 Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goulash"); 394 assertStoredValuesWithProjection(filterUri1, values); 395 396 Uri filterUri2 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goolish"); 397 assertEquals(0, getCount(filterUri2, null, null)); 398 } 399 400 public void testQueryContactStrequent() { 401 ContentValues values1 = new ContentValues(); 402 createContact(values1, "Noah", "Tever", "18004664411", 403 "a@acme.com", StatusUpdates.OFFLINE, 0, 0, 0); 404 ContentValues values2 = new ContentValues(); 405 createContact(values2, "Sam", "Times", "18004664412", 406 "b@acme.com", StatusUpdates.INVISIBLE, 3, 0, 0); 407 ContentValues values3 = new ContentValues(); 408 createContact(values3, "Lotta", "Calling", "18004664413", 409 "c@acme.com", StatusUpdates.AWAY, 5, 0, 0); 410 ContentValues values4 = new ContentValues(); 411 createContact(values4, "Fay", "Veritt", "18004664414", 412 "d@acme.com", StatusUpdates.AVAILABLE, 0, 1, 0); 413 414 Cursor c = mResolver.query(Contacts.CONTENT_STREQUENT_URI, null, null, null, 415 Contacts._ID); 416 assertEquals(3, c.getCount()); 417 c.moveToFirst(); 418 assertCursorValues(c, values4); 419 c.moveToNext(); 420 assertCursorValues(c, values3); 421 c.moveToNext(); 422 assertCursorValues(c, values2); 423 c.close(); 424 425 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_STREQUENT_FILTER_URI, "fay"); 426 c = mResolver.query(filterUri, null, null, null, Contacts._ID); 427 assertEquals(1, c.getCount()); 428 c.moveToFirst(); 429 assertCursorValues(c, values4); 430 c.close(); 431 } 432 433 public void testQueryContactGroup() { 434 long groupId = createGroup(null, "testGroup", "Test Group"); 435 436 ContentValues values1 = new ContentValues(); 437 createContact(values1, "Best", "West", "18004664411", 438 "west@acme.com", StatusUpdates.OFFLINE, 0, 0, groupId); 439 440 ContentValues values2 = new ContentValues(); 441 createContact(values2, "Rest", "East", "18004664422", 442 "east@acme.com", StatusUpdates.AVAILABLE, 0, 0, 0); 443 444 Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 445 Cursor c = mResolver.query(filterUri1, null, null, null, Contacts._ID); 446 assertEquals(1, c.getCount()); 447 c.moveToFirst(); 448 assertCursorValues(c, values1); 449 c.close(); 450 451 Uri filterUri2 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 452 c = mResolver.query(filterUri2, null, Contacts.DISPLAY_NAME + "=?", 453 new String[] { "Best West" }, Contacts._ID); 454 assertEquals(1, c.getCount()); 455 c.close(); 456 457 Uri filterUri3 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Next Group"); 458 c = mResolver.query(filterUri3, null, null, null, Contacts._ID); 459 assertEquals(0, c.getCount()); 460 c.close(); 461 } 462 463 public void testPhonesWithStatusUpdate() { 464 465 ContentValues values = new ContentValues(); 466 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 467 long rawContactId = ContentUris.parseId(rawContactUri); 468 insertStructuredName(rawContactId, "John", "Doe"); 469 Uri photoUri = insertPhoto(rawContactId); 470 long photoId = ContentUris.parseId(photoUri); 471 values.put(Contacts.PHOTO_ID, photoId); 472 insertPhoneNumber(rawContactId, "18004664411"); 473 insertPhoneNumber(rawContactId, "18004664412"); 474 insertEmail(rawContactId, "goog411@acme.com"); 475 insertEmail(rawContactId, "goog412@acme.com"); 476 477 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog411@acme.com", 478 StatusUpdates.INVISIBLE, "Bad"); 479 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog412@acme.com", 480 StatusUpdates.AVAILABLE, "Good"); 481 long contactId = queryContactId(rawContactId); 482 483 Uri uri = Data.CONTENT_URI; 484 485 Cursor c = mResolver.query(uri, null, RawContacts.CONTACT_ID + "=" + contactId + " AND " 486 + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null, Phone.NUMBER); 487 assertEquals(2, c.getCount()); 488 489 c.moveToFirst(); 490 491 values.clear(); 492 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 493 values.put(Contacts.CONTACT_STATUS, "Bad"); 494 values.put(Contacts.DISPLAY_NAME, "John Doe"); 495 values.put(Phone.NUMBER, "18004664411"); 496 values.putNull(Phone.LABEL); 497 values.put(RawContacts.CONTACT_ID, contactId); 498 assertCursorValues(c, values); 499 500 c.moveToNext(); 501 502 values.clear(); 503 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 504 values.put(Contacts.CONTACT_STATUS, "Bad"); 505 values.put(Contacts.DISPLAY_NAME, "John Doe"); 506 values.put(Phone.NUMBER, "18004664412"); 507 values.putNull(Phone.LABEL); 508 values.put(RawContacts.CONTACT_ID, contactId); 509 assertCursorValues(c, values); 510 511 c.close(); 512 } 513 514 public void testGroupQuery() { 515 Account account1 = new Account("a", "b"); 516 Account account2 = new Account("c", "d"); 517 long groupId1 = createGroup(account1, "e", "f"); 518 long groupId2 = createGroup(account2, "g", "h"); 519 Uri uri1 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account1); 520 Uri uri2 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account2); 521 assertEquals(1, getCount(uri1, null, null)); 522 assertEquals(1, getCount(uri2, null, null)); 523 assertStoredValue(uri1, Groups._ID + "=" + groupId1, null, Groups._ID, groupId1) ; 524 assertStoredValue(uri2, Groups._ID + "=" + groupId2, null, Groups._ID, groupId2) ; 525 } 526 527 public void testGroupInsert() { 528 ContentValues values = new ContentValues(); 529 530 values.put(Groups.ACCOUNT_NAME, "a"); 531 values.put(Groups.ACCOUNT_TYPE, "b"); 532 values.put(Groups.SOURCE_ID, "c"); 533 values.put(Groups.VERSION, 42); 534 values.put(Groups.GROUP_VISIBLE, 1); 535 values.put(Groups.TITLE, "d"); 536 values.put(Groups.TITLE_RES, 1234); 537 values.put(Groups.NOTES, "e"); 538 values.put(Groups.RES_PACKAGE, "f"); 539 values.put(Groups.SYSTEM_ID, "g"); 540 values.put(Groups.DELETED, 1); 541 values.put(Groups.SYNC1, "h"); 542 values.put(Groups.SYNC2, "i"); 543 values.put(Groups.SYNC3, "j"); 544 values.put(Groups.SYNC4, "k"); 545 546 Uri rowUri = mResolver.insert(Groups.CONTENT_URI, values); 547 548 values.put(Groups.DIRTY, 1); 549 assertStoredValues(rowUri, values); 550 } 551 552 public void testSettingsQuery() { 553 Account account1 = new Account("a", "b"); 554 Account account2 = new Account("c", "d"); 555 createSettings(account1, "0", "0"); 556 createSettings(account2, "1", "1"); 557 Uri uri1 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account1); 558 Uri uri2 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account2); 559 assertEquals(1, getCount(uri1, null, null)); 560 assertEquals(1, getCount(uri2, null, null)); 561 assertStoredValue(uri1, Settings.SHOULD_SYNC, "0") ; 562 assertStoredValue(uri1, Settings.UNGROUPED_VISIBLE, "0") ; 563 assertStoredValue(uri2, Settings.SHOULD_SYNC, "1") ; 564 assertStoredValue(uri2, Settings.UNGROUPED_VISIBLE, "1") ; 565 } 566 567 public void testDisplayNameParsingWhenPartsUnspecified() { 568 long rawContactId = createRawContact(); 569 ContentValues values = new ContentValues(); 570 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 571 insertStructuredName(rawContactId, values); 572 573 assertStructuredName(rawContactId, "Mr", "John", "Kevin", "von Smith", "Jr"); 574 } 575 576 public void testDisplayNameParsingWhenPartsAreNull() { 577 long rawContactId = createRawContact(); 578 ContentValues values = new ContentValues(); 579 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 580 values.putNull(StructuredName.GIVEN_NAME); 581 values.putNull(StructuredName.FAMILY_NAME); 582 insertStructuredName(rawContactId, values); 583 assertStructuredName(rawContactId, "Mr", "John", "Kevin", "von Smith", "Jr"); 584 } 585 586 public void testDisplayNameParsingWhenPartsSpecified() { 587 long rawContactId = createRawContact(); 588 ContentValues values = new ContentValues(); 589 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 590 values.put(StructuredName.FAMILY_NAME, "Johnson"); 591 insertStructuredName(rawContactId, values); 592 593 assertStructuredName(rawContactId, null, null, null, "Johnson", null); 594 } 595 596 public void testDisplayNameUpdate() { 597 long rawContactId1 = createRawContact(); 598 insertEmail(rawContactId1, "potato@acme.com", true); 599 600 long rawContactId2 = createRawContact(); 601 insertPhoneNumber(rawContactId2, "123456789", true); 602 603 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 604 rawContactId1, rawContactId2); 605 606 assertAggregated(rawContactId1, rawContactId2, "123456789"); 607 608 insertStructuredName(rawContactId2, "Potato", "Head"); 609 610 assertAggregated(rawContactId1, rawContactId2, "Potato Head"); 611 assertNetworkNotified(true); 612 } 613 614 public void testDisplayNameFromData() { 615 long rawContactId = createRawContact(); 616 long contactId = queryContactId(rawContactId); 617 ContentValues values = new ContentValues(); 618 619 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 620 621 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 622 insertEmail(rawContactId, "mike@monstersinc.com"); 623 assertStoredValue(uri, Contacts.DISPLAY_NAME, "mike@monstersinc.com"); 624 625 insertEmail(rawContactId, "james@monstersinc.com", true); 626 assertStoredValue(uri, Contacts.DISPLAY_NAME, "james@monstersinc.com"); 627 628 insertPhoneNumber(rawContactId, "1-800-466-4411"); 629 assertStoredValue(uri, Contacts.DISPLAY_NAME, "1-800-466-4411"); 630 631 // If there is title without company, the title is display name. 632 values.clear(); 633 values.put(Organization.TITLE, "Protagonist"); 634 Uri organizationUri = insertOrganization(rawContactId, values); 635 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Protagonist"); 636 637 // If there are title and company, the company is display name. 638 values.clear(); 639 values.put(Organization.COMPANY, "Monsters Inc"); 640 mResolver.update(organizationUri, values, null, null); 641 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Monsters Inc"); 642 643 // If there is nickname, that is display name. 644 insertNickname(rawContactId, "Sully"); 645 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Sully"); 646 647 // If there is structured name, that is display name. 648 values.clear(); 649 values.put(StructuredName.GIVEN_NAME, "James"); 650 values.put(StructuredName.MIDDLE_NAME, "P."); 651 values.put(StructuredName.FAMILY_NAME, "Sullivan"); 652 insertStructuredName(rawContactId, values); 653 assertStoredValue(uri, Contacts.DISPLAY_NAME, "James Sullivan"); 654 } 655 656 public void testDisplayNameUpdateFromStructuredNameUpdate() { 657 long rawContactId = createRawContact(); 658 Uri nameUri = insertStructuredName(rawContactId, "Slinky", "Dog"); 659 660 long contactId = queryContactId(rawContactId); 661 662 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 663 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky Dog"); 664 665 ContentValues values = new ContentValues(); 666 values.putNull(StructuredName.FAMILY_NAME); 667 668 mResolver.update(nameUri, values, null, null); 669 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky"); 670 671 values.putNull(StructuredName.GIVEN_NAME); 672 673 mResolver.update(nameUri, values, null, null); 674 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 675 676 values.put(StructuredName.FAMILY_NAME, "Dog"); 677 mResolver.update(nameUri, values, null, null); 678 679 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Dog"); 680 } 681 682 public void testSendToVoicemailDefault() { 683 long rawContactId = createRawContactWithName(); 684 long contactId = queryContactId(rawContactId); 685 686 Cursor c = queryContact(contactId); 687 assertTrue(c.moveToNext()); 688 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 689 assertEquals(0, sendToVoicemail); 690 c.close(); 691 } 692 693 public void testSetSendToVoicemailAndRingtone() { 694 long rawContactId = createRawContactWithName(); 695 long contactId = queryContactId(rawContactId); 696 697 updateSendToVoicemailAndRingtone(contactId, true, "foo"); 698 assertSendToVoicemailAndRingtone(contactId, true, "foo"); 699 assertNetworkNotified(false); 700 701 updateSendToVoicemailAndRingtoneWithSelection(contactId, false, "bar"); 702 assertSendToVoicemailAndRingtone(contactId, false, "bar"); 703 assertNetworkNotified(false); 704 } 705 706 public void testSendToVoicemailAndRingtoneAfterAggregation() { 707 long rawContactId1 = createRawContactWithName("a", "b"); 708 long contactId1 = queryContactId(rawContactId1); 709 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 710 711 long rawContactId2 = createRawContactWithName("c", "d"); 712 long contactId2 = queryContactId(rawContactId2); 713 updateSendToVoicemailAndRingtone(contactId2, true, "bar"); 714 715 // Aggregate them 716 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 717 rawContactId1, rawContactId2); 718 719 // Both contacts had "send to VM", the contact now has the same value 720 assertSendToVoicemailAndRingtone(contactId1, true, "foo,bar"); // Either foo or bar 721 } 722 723 public void testDoNotSendToVoicemailAfterAggregation() { 724 long rawContactId1 = createRawContactWithName("e", "f"); 725 long contactId1 = queryContactId(rawContactId1); 726 updateSendToVoicemailAndRingtone(contactId1, true, null); 727 728 long rawContactId2 = createRawContactWithName("g", "h"); 729 long contactId2 = queryContactId(rawContactId2); 730 updateSendToVoicemailAndRingtone(contactId2, false, null); 731 732 // Aggregate them 733 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 734 rawContactId1, rawContactId2); 735 736 // Since one of the contacts had "don't send to VM" that setting wins for the aggregate 737 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), false, null); 738 } 739 740 public void testSetSendToVoicemailAndRingtonePreservedAfterJoinAndSplit() { 741 long rawContactId1 = createRawContactWithName("i", "j"); 742 long contactId1 = queryContactId(rawContactId1); 743 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 744 745 long rawContactId2 = createRawContactWithName("k", "l"); 746 long contactId2 = queryContactId(rawContactId2); 747 updateSendToVoicemailAndRingtone(contactId2, false, "bar"); 748 749 // Aggregate them 750 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 751 rawContactId1, rawContactId2); 752 753 // Split them 754 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 755 rawContactId1, rawContactId2); 756 757 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), true, "foo"); 758 assertSendToVoicemailAndRingtone(queryContactId(rawContactId2), false, "bar"); 759 } 760 761 public void testStatusUpdateInsert() { 762 long rawContactId = createRawContact(); 763 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 764 long dataId = ContentUris.parseId(imUri); 765 766 ContentValues values = new ContentValues(); 767 values.put(StatusUpdates.DATA_ID, dataId); 768 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 769 values.putNull(StatusUpdates.CUSTOM_PROTOCOL); 770 values.put(StatusUpdates.IM_HANDLE, "aim"); 771 values.put(StatusUpdates.PRESENCE, StatusUpdates.INVISIBLE); 772 values.put(StatusUpdates.STATUS, "Hiding"); 773 values.put(StatusUpdates.STATUS_TIMESTAMP, 100); 774 values.put(StatusUpdates.STATUS_RES_PACKAGE, "a.b.c"); 775 values.put(StatusUpdates.STATUS_ICON, 1234); 776 values.put(StatusUpdates.STATUS_LABEL, 2345); 777 778 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 779 780 assertStoredValues(resultUri, values); 781 782 long contactId = queryContactId(rawContactId); 783 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 784 785 values.clear(); 786 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 787 values.put(Contacts.CONTACT_STATUS, "Hiding"); 788 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 789 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "a.b.c"); 790 values.put(Contacts.CONTACT_STATUS_ICON, 1234); 791 values.put(Contacts.CONTACT_STATUS_LABEL, 2345); 792 793 assertStoredValues(contactUri, values); 794 795 values.clear(); 796 values.put(StatusUpdates.DATA_ID, dataId); 797 values.put(StatusUpdates.STATUS, "Cloaked"); 798 values.put(StatusUpdates.STATUS_TIMESTAMP, 200); 799 values.put(StatusUpdates.STATUS_RES_PACKAGE, "d.e.f"); 800 values.put(StatusUpdates.STATUS_ICON, 4321); 801 values.put(StatusUpdates.STATUS_LABEL, 5432); 802 mResolver.insert(StatusUpdates.CONTENT_URI, values); 803 804 values.clear(); 805 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 806 values.put(Contacts.CONTACT_STATUS, "Cloaked"); 807 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 200); 808 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "d.e.f"); 809 values.put(Contacts.CONTACT_STATUS_ICON, 4321); 810 values.put(Contacts.CONTACT_STATUS_LABEL, 5432); 811 assertStoredValues(contactUri, values); 812 } 813 814 public void testStatusUpdateInferAttribution() { 815 long rawContactId = createRawContact(); 816 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 817 long dataId = ContentUris.parseId(imUri); 818 819 ContentValues values = new ContentValues(); 820 values.put(StatusUpdates.DATA_ID, dataId); 821 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 822 values.put(StatusUpdates.IM_HANDLE, "aim"); 823 values.put(StatusUpdates.STATUS, "Hiding"); 824 825 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 826 827 values.clear(); 828 values.put(StatusUpdates.DATA_ID, dataId); 829 values.put(StatusUpdates.STATUS_LABEL, com.android.internal.R.string.imProtocolAim); 830 values.put(StatusUpdates.STATUS, "Hiding"); 831 832 assertStoredValues(resultUri, values); 833 } 834 835 public void testStatusUpdateMatchingImOrEmail() { 836 long rawContactId = createRawContact(); 837 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 838 insertImHandle(rawContactId, Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im"); 839 insertEmail(rawContactId, "m@acme.com"); 840 841 // Match on IM (standard) 842 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available"); 843 844 // Match on IM (custom) 845 insertStatusUpdate(Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im", StatusUpdates.IDLE, "Idle"); 846 847 // Match on Email 848 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "m@acme.com", StatusUpdates.AWAY, "Away"); 849 850 // No match 851 insertStatusUpdate(Im.PROTOCOL_ICQ, null, "12345", StatusUpdates.DO_NOT_DISTURB, "Go away"); 852 853 Cursor c = mResolver.query(StatusUpdates.CONTENT_URI, new String[] { 854 StatusUpdates.DATA_ID, StatusUpdates.PROTOCOL, StatusUpdates.CUSTOM_PROTOCOL, 855 StatusUpdates.PRESENCE, StatusUpdates.STATUS}, 856 PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null, StatusUpdates.DATA_ID); 857 assertTrue(c.moveToNext()); 858 assertStatusUpdate(c, Im.PROTOCOL_AIM, null, StatusUpdates.AVAILABLE, "Available"); 859 assertTrue(c.moveToNext()); 860 assertStatusUpdate(c, Im.PROTOCOL_CUSTOM, "my_im_proto", StatusUpdates.IDLE, "Idle"); 861 assertTrue(c.moveToNext()); 862 assertStatusUpdate(c, Im.PROTOCOL_GOOGLE_TALK, null, StatusUpdates.AWAY, "Away"); 863 assertFalse(c.moveToNext()); 864 c.close(); 865 866 long contactId = queryContactId(rawContactId); 867 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 868 869 ContentValues values = new ContentValues(); 870 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 871 values.put(Contacts.CONTACT_STATUS, "Available"); 872 assertStoredValuesWithProjection(contactUri, values); 873 } 874 875 public void testStatusUpdateUpdateAndDelete() { 876 long rawContactId = createRawContact(); 877 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 878 879 long contactId = queryContactId(rawContactId); 880 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 881 882 ContentValues values = new ContentValues(); 883 values.putNull(Contacts.CONTACT_PRESENCE); 884 values.putNull(Contacts.CONTACT_STATUS); 885 assertStoredValuesWithProjection(contactUri, values); 886 887 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AWAY, "BUSY"); 888 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.DO_NOT_DISTURB, "GO AWAY"); 889 Uri statusUri = 890 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available"); 891 long statusId = ContentUris.parseId(statusUri); 892 893 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 894 values.put(Contacts.CONTACT_STATUS, "Available"); 895 assertStoredValuesWithProjection(contactUri, values); 896 897 mResolver.delete(StatusUpdates.CONTENT_URI, StatusUpdates.DATA_ID + "=" + statusId, null); 898 values.putNull(Contacts.CONTACT_PRESENCE); 899 900 // Latest custom status update stays on the phone 901 values.put(Contacts.CONTACT_STATUS, "Available"); 902 assertStoredValuesWithProjection(contactUri, values); 903 } 904 905 public void testStatusUpdateWithTimestamp() { 906 long rawContactId = createRawContact(); 907 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 908 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 909 910 long contactId = queryContactId(rawContactId); 911 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 912 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Offline", 80); 913 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Available", 100); 914 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", 0, "Busy", 90); 915 916 // Should return the latest status 917 ContentValues values = new ContentValues(); 918 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 919 values.put(Contacts.CONTACT_STATUS, "Available"); 920 assertStoredValuesWithProjection(contactUri, values); 921 } 922 923 private void assertStatusUpdate(Cursor c, int protocol, String customProtocol, int presence, 924 String status) { 925 ContentValues values = new ContentValues(); 926 values.put(StatusUpdates.PROTOCOL, protocol); 927 values.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 928 values.put(StatusUpdates.PRESENCE_STATUS, presence); 929 values.put(StatusUpdates.STATUS, status); 930 assertCursorValues(c, values); 931 } 932 933 public void testSingleStatusUpdateRowPerContact() { 934 int protocol1 = Im.PROTOCOL_GOOGLE_TALK; 935 String handle1 = "test@gmail.com"; 936 937 long rawContactId1 = createRawContact(); 938 insertImHandle(rawContactId1, protocol1, null, handle1); 939 940 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AVAILABLE, "Green"); 941 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AWAY, "Yellow"); 942 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.INVISIBLE, "Red"); 943 944 Cursor c = queryContact(queryContactId(rawContactId1), 945 new String[] {Contacts.CONTACT_PRESENCE, Contacts.CONTACT_STATUS}); 946 assertEquals(1, c.getCount()); 947 948 c.moveToFirst(); 949 assertEquals(StatusUpdates.INVISIBLE, c.getInt(0)); 950 assertEquals("Red", c.getString(1)); 951 } 952 953 private void updateSendToVoicemailAndRingtone(long contactId, boolean sendToVoicemail, 954 String ringtone) { 955 ContentValues values = new ContentValues(); 956 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 957 if (ringtone != null) { 958 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 959 } 960 961 final Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 962 int count = mResolver.update(uri, values, null, null); 963 assertEquals(1, count); 964 } 965 966 private void updateSendToVoicemailAndRingtoneWithSelection(long contactId, 967 boolean sendToVoicemail, String ringtone) { 968 ContentValues values = new ContentValues(); 969 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 970 if (ringtone != null) { 971 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 972 } 973 974 int count = mResolver.update(Contacts.CONTENT_URI, values, Contacts._ID + "=" + contactId, 975 null); 976 assertEquals(1, count); 977 } 978 979 private void assertSendToVoicemailAndRingtone(long contactId, boolean expectedSendToVoicemail, 980 String expectedRingtone) { 981 Cursor c = queryContact(contactId); 982 assertTrue(c.moveToNext()); 983 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 984 assertEquals(expectedSendToVoicemail ? 1 : 0, sendToVoicemail); 985 String ringtone = c.getString(c.getColumnIndex(Contacts.CUSTOM_RINGTONE)); 986 if (expectedRingtone == null) { 987 assertNull(ringtone); 988 } else { 989 assertTrue(ArrayUtils.contains(expectedRingtone.split(","), ringtone)); 990 } 991 c.close(); 992 } 993 994 public void testGroupCreationAfterMembershipInsert() { 995 long rawContactId1 = createRawContact(mAccount); 996 Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 997 998 long groupId = assertSingleGroup(NO_LONG, mAccount, "gsid1", null); 999 assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 1000 rawContactId1, groupId, "gsid1"); 1001 } 1002 1003 public void testGroupReuseAfterMembershipInsert() { 1004 long rawContactId1 = createRawContact(mAccount); 1005 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 1006 Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 1007 1008 assertSingleGroup(groupId1, mAccount, "gsid1", "title1"); 1009 assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 1010 rawContactId1, groupId1, "gsid1"); 1011 } 1012 1013 public void testGroupInsertFailureOnGroupIdConflict() { 1014 long rawContactId1 = createRawContact(mAccount); 1015 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 1016 1017 ContentValues values = new ContentValues(); 1018 values.put(GroupMembership.RAW_CONTACT_ID, rawContactId1); 1019 values.put(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 1020 values.put(GroupMembership.GROUP_SOURCE_ID, "gsid1"); 1021 values.put(GroupMembership.GROUP_ROW_ID, groupId1); 1022 try { 1023 mResolver.insert(Data.CONTENT_URI, values); 1024 fail("the insert was expected to fail, but it succeeded"); 1025 } catch (IllegalArgumentException e) { 1026 // this was expected 1027 } 1028 } 1029 1030 public void testContactVisibilityUpdateOnMembershipChange() { 1031 long rawContactId = createRawContact(mAccount); 1032 assertVisibility(rawContactId, "0"); 1033 1034 long visibleGroupId = createGroup(mAccount, "123", "Visible", 1); 1035 long invisibleGroupId = createGroup(mAccount, "567", "Invisible", 0); 1036 1037 Uri membership1 = insertGroupMembership(rawContactId, visibleGroupId); 1038 assertVisibility(rawContactId, "1"); 1039 1040 Uri membership2 = insertGroupMembership(rawContactId, invisibleGroupId); 1041 assertVisibility(rawContactId, "1"); 1042 1043 mResolver.delete(membership1, null, null); 1044 assertVisibility(rawContactId, "0"); 1045 1046 ContentValues values = new ContentValues(); 1047 values.put(GroupMembership.GROUP_ROW_ID, visibleGroupId); 1048 1049 mResolver.update(membership2, values, null, null); 1050 assertVisibility(rawContactId, "1"); 1051 } 1052 1053 private void assertVisibility(long rawContactId, String expectedValue) { 1054 assertStoredValue(Contacts.CONTENT_URI, Contacts._ID + "=" + queryContactId(rawContactId), 1055 null, Contacts.IN_VISIBLE_GROUP, expectedValue); 1056 } 1057 1058 public void testContentEntityIterator() throws RemoteException { 1059 // create multiple contacts and check that the selected ones are returned 1060 long id; 1061 1062 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 1063 long groupId2 = createGroup(mAccount, "gsid2", "title2"); 1064 1065 id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c0"); 1066 insertGroupMembership(id, "gsid1"); 1067 insertEmail(id, "c0@email.com"); 1068 insertPhoneNumber(id, "5551212c0"); 1069 1070 long c1 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c1"); 1071 Uri id_1_0 = insertGroupMembership(id, "gsid1"); 1072 Uri id_1_1 = insertGroupMembership(id, "gsid2"); 1073 Uri id_1_2 = insertEmail(id, "c1@email.com"); 1074 Uri id_1_3 = insertPhoneNumber(id, "5551212c1"); 1075 1076 long c2 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c2"); 1077 Uri id_2_0 = insertGroupMembership(id, "gsid1"); 1078 Uri id_2_1 = insertEmail(id, "c2@email.com"); 1079 Uri id_2_2 = insertPhoneNumber(id, "5551212c2"); 1080 1081 long c3 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c3"); 1082 Uri id_3_0 = insertGroupMembership(id, groupId2); 1083 Uri id_3_1 = insertEmail(id, "c3@email.com"); 1084 Uri id_3_2 = insertPhoneNumber(id, "5551212c3"); 1085 1086 EntityIterator iterator = mResolver.queryEntities( 1087 maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, mAccount), 1088 RawContacts.SOURCE_ID + " in ('c1', 'c2', 'c3')", null, null); 1089 Entity entity; 1090 ContentValues[] subValues; 1091 entity = iterator.next(); 1092 assertEquals(c1, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 1093 subValues = asSortedContentValuesArray(entity.getSubValues()); 1094 assertEquals(4, subValues.length); 1095 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 1096 Data._ID, id_1_0, 1097 GroupMembership.GROUP_ROW_ID, groupId1, 1098 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 1099 assertDataRow(subValues[1], GroupMembership.CONTENT_ITEM_TYPE, 1100 Data._ID, id_1_1, 1101 GroupMembership.GROUP_ROW_ID, groupId2, 1102 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 1103 assertDataRow(subValues[2], Email.CONTENT_ITEM_TYPE, 1104 Data._ID, id_1_2, 1105 Email.DATA, "c1@email.com"); 1106 assertDataRow(subValues[3], Phone.CONTENT_ITEM_TYPE, 1107 Data._ID, id_1_3, 1108 Email.DATA, "5551212c1"); 1109 1110 entity = iterator.next(); 1111 assertEquals(c2, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 1112 subValues = asSortedContentValuesArray(entity.getSubValues()); 1113 assertEquals(3, subValues.length); 1114 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 1115 Data._ID, id_2_0, 1116 GroupMembership.GROUP_ROW_ID, groupId1, 1117 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 1118 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 1119 Data._ID, id_2_1, 1120 Email.DATA, "c2@email.com"); 1121 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 1122 Data._ID, id_2_2, 1123 Email.DATA, "5551212c2"); 1124 1125 entity = iterator.next(); 1126 assertEquals(c3, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 1127 subValues = asSortedContentValuesArray(entity.getSubValues()); 1128 assertEquals(3, subValues.length); 1129 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 1130 Data._ID, id_3_0, 1131 GroupMembership.GROUP_ROW_ID, groupId2, 1132 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 1133 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 1134 Data._ID, id_3_1, 1135 Email.DATA, "c3@email.com"); 1136 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 1137 Data._ID, id_3_2, 1138 Email.DATA, "5551212c3"); 1139 1140 assertFalse(iterator.hasNext()); 1141 iterator.close(); 1142 } 1143 1144 public void testDataCreateUpdateDeleteByMimeType() throws Exception { 1145 long rawContactId = createRawContact(); 1146 1147 ContentValues values = new ContentValues(); 1148 values.put(Data.RAW_CONTACT_ID, rawContactId); 1149 values.put(Data.MIMETYPE, "testmimetype"); 1150 values.put(Data.RES_PACKAGE, "oldpackage"); 1151 values.put(Data.IS_PRIMARY, 1); 1152 values.put(Data.IS_SUPER_PRIMARY, 1); 1153 values.put(Data.DATA1, "old1"); 1154 values.put(Data.DATA2, "old2"); 1155 values.put(Data.DATA3, "old3"); 1156 values.put(Data.DATA4, "old4"); 1157 values.put(Data.DATA5, "old5"); 1158 values.put(Data.DATA6, "old6"); 1159 values.put(Data.DATA7, "old7"); 1160 values.put(Data.DATA8, "old8"); 1161 values.put(Data.DATA9, "old9"); 1162 values.put(Data.DATA10, "old10"); 1163 values.put(Data.DATA11, "old11"); 1164 values.put(Data.DATA12, "old12"); 1165 values.put(Data.DATA13, "old13"); 1166 values.put(Data.DATA14, "old14"); 1167 values.put(Data.DATA15, "old15"); 1168 Uri uri = mResolver.insert(Data.CONTENT_URI, values); 1169 assertStoredValues(uri, values); 1170 assertNetworkNotified(true); 1171 1172 values.clear(); 1173 values.put(Data.RES_PACKAGE, "newpackage"); 1174 values.put(Data.IS_PRIMARY, 0); 1175 values.put(Data.IS_SUPER_PRIMARY, 0); 1176 values.put(Data.DATA1, "new1"); 1177 values.put(Data.DATA2, "new2"); 1178 values.put(Data.DATA3, "new3"); 1179 values.put(Data.DATA4, "new4"); 1180 values.put(Data.DATA5, "new5"); 1181 values.put(Data.DATA6, "new6"); 1182 values.put(Data.DATA7, "new7"); 1183 values.put(Data.DATA8, "new8"); 1184 values.put(Data.DATA9, "new9"); 1185 values.put(Data.DATA10, "new10"); 1186 values.put(Data.DATA11, "new11"); 1187 values.put(Data.DATA12, "new12"); 1188 values.put(Data.DATA13, "new13"); 1189 values.put(Data.DATA14, "new14"); 1190 values.put(Data.DATA15, "new15"); 1191 mResolver.update(Data.CONTENT_URI, values, Data.RAW_CONTACT_ID + "=" + rawContactId + 1192 " AND " + Data.MIMETYPE + "='testmimetype'", null); 1193 assertNetworkNotified(true); 1194 1195 // Should not be able to change IS_PRIMARY and IS_SUPER_PRIMARY by the above update 1196 values.put(Data.IS_PRIMARY, 1); 1197 values.put(Data.IS_SUPER_PRIMARY, 1); 1198 assertStoredValues(uri, values); 1199 1200 int count = mResolver.delete(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 1201 + " AND " + Data.MIMETYPE + "='testmimetype'", null); 1202 assertEquals(1, count); 1203 assertEquals(0, getCount(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 1204 + " AND " + Data.MIMETYPE + "='testmimetype'", null)); 1205 assertNetworkNotified(true); 1206 } 1207 1208 public void testRawContactQuery() { 1209 Account account1 = new Account("a", "b"); 1210 Account account2 = new Account("c", "d"); 1211 long rawContactId1 = createRawContact(account1); 1212 long rawContactId2 = createRawContact(account2); 1213 1214 Uri uri1 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account1); 1215 Uri uri2 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account2); 1216 assertEquals(1, getCount(uri1, null, null)); 1217 assertEquals(1, getCount(uri2, null, null)); 1218 assertStoredValue(uri1, RawContacts._ID, rawContactId1) ; 1219 assertStoredValue(uri2, RawContacts._ID, rawContactId2) ; 1220 1221 Uri rowUri1 = ContentUris.withAppendedId(uri1, rawContactId1); 1222 Uri rowUri2 = ContentUris.withAppendedId(uri2, rawContactId2); 1223 assertStoredValue(rowUri1, RawContacts._ID, rawContactId1) ; 1224 assertStoredValue(rowUri2, RawContacts._ID, rawContactId2) ; 1225 } 1226 1227 public void testRawContactDeletion() { 1228 long rawContactId = createRawContact(); 1229 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1230 1231 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 1232 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 1233 StatusUpdates.AVAILABLE, null); 1234 long contactId = queryContactId(rawContactId); 1235 1236 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 1237 null, null)); 1238 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 1239 + rawContactId, null)); 1240 1241 mResolver.delete(uri, null, null); 1242 1243 assertStoredValue(uri, RawContacts.DELETED, "1"); 1244 assertNetworkNotified(true); 1245 1246 Uri permanentDeletionUri = uri.buildUpon().appendQueryParameter( 1247 ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(); 1248 mResolver.delete(permanentDeletionUri, null, null); 1249 assertEquals(0, getCount(uri, null, null)); 1250 assertEquals(0, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 1251 null, null)); 1252 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 1253 + rawContactId, null)); 1254 assertEquals(0, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 1255 assertNetworkNotified(false); 1256 } 1257 1258 public void testRawContactDeletionKeepingAggregateContact() { 1259 long rawContactId1 = createRawContactWithName(); 1260 long rawContactId2 = createRawContactWithName(); 1261 1262 // Same name - should be aggregated 1263 assertAggregated(rawContactId1, rawContactId2); 1264 1265 long contactId = queryContactId(rawContactId1); 1266 1267 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 1268 Uri permanentDeletionUri = uri.buildUpon().appendQueryParameter( 1269 ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(); 1270 mResolver.delete(permanentDeletionUri, null, null); 1271 assertEquals(0, getCount(uri, null, null)); 1272 assertEquals(1, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 1273 } 1274 1275 public void testRawContactDeletionWithAccounts() { 1276 long rawContactId = createRawContact(mAccount); 1277 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1278 1279 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 1280 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 1281 StatusUpdates.AVAILABLE, null); 1282 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 1283 null, null)); 1284 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 1285 + rawContactId, null)); 1286 1287 // Do not delete if we are deleting with wrong account. 1288 Uri deleteWithWrongAccountUri = 1289 RawContacts.CONTENT_URI.buildUpon() 1290 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccountTwo.name) 1291 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccountTwo.type) 1292 .build(); 1293 mResolver.delete(deleteWithWrongAccountUri, null, null); 1294 1295 assertStoredValue(uri, RawContacts.DELETED, "0"); 1296 1297 // Delete if we are deleting with correct account. 1298 Uri deleteWithCorrectAccountUri = 1299 RawContacts.CONTENT_URI.buildUpon() 1300 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccount.name) 1301 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccount.type) 1302 .build(); 1303 mResolver.delete(deleteWithCorrectAccountUri, null, null); 1304 1305 assertStoredValue(uri, RawContacts.DELETED, "1"); 1306 } 1307 1308 public void testAccountsUpdated() { 1309 long rawContactId1 = createRawContact(mAccount); 1310 insertEmail(rawContactId1, "account1@email.com"); 1311 long rawContactId2 = createRawContact(mAccountTwo); 1312 insertEmail(rawContactId2, "account2@email.com"); 1313 insertImHandle(rawContactId2, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 1314 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 1315 StatusUpdates.AVAILABLE, null); 1316 1317 // This is to ensure we do not delete contacts with null, null (account name, type) 1318 // accidentally. 1319 long rawContactId3 = createRawContactWithName("James", "Sullivan"); 1320 insertPhoneNumber(rawContactId3, "5234567890"); 1321 Uri rawContact3 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId3); 1322 1323 ContactsProvider2 cp = (ContactsProvider2) getProvider(); 1324 1325 Account accountRemaining = new Account("account1", "account type1"); 1326 cp.onAccountsUpdated(new Account[]{accountRemaining}); 1327 assertEquals(2, getCount(RawContacts.CONTENT_URI, null, null)); 1328 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 1329 + rawContactId2, null)); 1330 assertStoredValue(rawContact3, RawContacts.ACCOUNT_NAME, "account1"); 1331 assertStoredValue(rawContact3, RawContacts.ACCOUNT_TYPE, "account type1"); 1332 } 1333 1334 public void testContactDeletion() { 1335 long rawContactId1 = createRawContactWithName("John", "Doe"); 1336 long rawContactId2 = createRawContactWithName("John", "Doe"); 1337 forceAggregation(); 1338 1339 long contactId = queryContactId(rawContactId1); 1340 1341 mResolver.delete(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), null, null); 1342 1343 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1), 1344 RawContacts.DELETED, "1"); 1345 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2), 1346 RawContacts.DELETED, "1"); 1347 } 1348 1349 public void testMarkAsDirtyParameter() { 1350 long rawContactId = createRawContact(mAccount); 1351 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1352 1353 Uri uri = insertStructuredName(rawContactId, "John", "Doe"); 1354 clearDirty(rawContactUri); 1355 Uri updateUri = uri.buildUpon() 1356 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(); 1357 1358 ContentValues values = new ContentValues(); 1359 values.put(StructuredName.FAMILY_NAME, "Dough"); 1360 mResolver.update(updateUri, values, null, null); 1361 assertStoredValue(uri, StructuredName.FAMILY_NAME, "Dough"); 1362 assertDirty(rawContactUri, false); 1363 assertNetworkNotified(false); 1364 } 1365 1366 public void testRawContactDirtyAndVersion() { 1367 final long rawContactId = createRawContact(mAccount); 1368 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); 1369 assertDirty(uri, false); 1370 long version = getVersion(uri); 1371 1372 ContentValues values = new ContentValues(); 1373 values.put(ContactsContract.RawContacts.DIRTY, 0); 1374 values.put(ContactsContract.RawContacts.SEND_TO_VOICEMAIL, 1); 1375 values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 1376 RawContacts.AGGREGATION_MODE_IMMEDIATE); 1377 values.put(ContactsContract.RawContacts.STARRED, 1); 1378 assertEquals(1, mResolver.update(uri, values, null, null)); 1379 assertEquals(version, getVersion(uri)); 1380 1381 assertDirty(uri, false); 1382 assertNetworkNotified(false); 1383 1384 Uri emailUri = insertEmail(rawContactId, "goo@woo.com"); 1385 assertDirty(uri, true); 1386 assertNetworkNotified(true); 1387 ++version; 1388 assertEquals(version, getVersion(uri)); 1389 clearDirty(uri); 1390 1391 values = new ContentValues(); 1392 values.put(Email.DATA, "goo@hoo.com"); 1393 mResolver.update(emailUri, values, null, null); 1394 assertDirty(uri, true); 1395 assertNetworkNotified(true); 1396 ++version; 1397 assertEquals(version, getVersion(uri)); 1398 clearDirty(uri); 1399 1400 mResolver.delete(emailUri, null, null); 1401 assertDirty(uri, true); 1402 assertNetworkNotified(true); 1403 ++version; 1404 assertEquals(version, getVersion(uri)); 1405 } 1406 1407 public void testRawContactClearDirty() { 1408 final long rawContactId = createRawContact(mAccount); 1409 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 1410 rawContactId); 1411 long version = getVersion(uri); 1412 insertEmail(rawContactId, "goo@woo.com"); 1413 assertDirty(uri, true); 1414 version++; 1415 assertEquals(version, getVersion(uri)); 1416 1417 clearDirty(uri); 1418 assertDirty(uri, false); 1419 assertEquals(version, getVersion(uri)); 1420 } 1421 1422 public void testRawContactDeletionSetsDirty() { 1423 final long rawContactId = createRawContact(mAccount); 1424 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 1425 rawContactId); 1426 long version = getVersion(uri); 1427 clearDirty(uri); 1428 assertDirty(uri, false); 1429 1430 mResolver.delete(uri, null, null); 1431 assertStoredValue(uri, RawContacts.DELETED, "1"); 1432 assertDirty(uri, true); 1433 assertNetworkNotified(true); 1434 version++; 1435 assertEquals(version, getVersion(uri)); 1436 } 1437 1438 public void testGetPhotoUri() { 1439 ContentValues values = new ContentValues(); 1440 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1441 long rawContactId = ContentUris.parseId(rawContactUri); 1442 insertStructuredName(rawContactId, "John", "Doe"); 1443 Uri photoUri = insertPhoto(rawContactId); 1444 1445 Uri twigUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1446 queryContactId(rawContactId)), Contacts.Photo.CONTENT_DIRECTORY); 1447 1448 long twigId = Long.parseLong(getStoredValue(twigUri, Data._ID)); 1449 assertEquals(ContentUris.parseId(photoUri), twigId); 1450 } 1451 1452 public void testSuperPrimaryPhoto() { 1453 long rawContactId1 = createRawContact(new Account("a", "a")); 1454 Uri photoUri1 = insertPhoto(rawContactId1); 1455 long photoId1 = ContentUris.parseId(photoUri1); 1456 1457 long rawContactId2 = createRawContact(new Account("b", "b")); 1458 Uri photoUri2 = insertPhoto(rawContactId2); 1459 long photoId2 = ContentUris.parseId(photoUri2); 1460 1461 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1462 rawContactId1, rawContactId2); 1463 1464 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 1465 queryContactId(rawContactId1)); 1466 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 1467 1468 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 1469 rawContactId1, rawContactId2); 1470 1471 ContentValues values = new ContentValues(); 1472 values.put(Data.IS_SUPER_PRIMARY, 1); 1473 mResolver.update(photoUri2, values, null, null); 1474 1475 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1476 rawContactId1, rawContactId2); 1477 contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 1478 queryContactId(rawContactId1)); 1479 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId2); 1480 1481 mResolver.update(photoUri1, values, null, null); 1482 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 1483 } 1484 1485 public void testUpdatePhoto() { 1486 ContentValues values = new ContentValues(); 1487 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1488 long rawContactId = ContentUris.parseId(rawContactUri); 1489 insertStructuredName(rawContactId, "John", "Doe"); 1490 1491 Uri twigUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1492 queryContactId(rawContactId)), Contacts.Photo.CONTENT_DIRECTORY); 1493 1494 values.clear(); 1495 values.put(Data.RAW_CONTACT_ID, rawContactId); 1496 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 1497 values.putNull(Photo.PHOTO); 1498 Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 1499 long photoId = ContentUris.parseId(dataUri); 1500 1501 assertNull(getStoredValue(twigUri, Data._ID)); 1502 1503 values.clear(); 1504 values.put(Photo.PHOTO, loadTestPhoto()); 1505 mResolver.update(dataUri, values, null, null); 1506 assertNetworkNotified(true); 1507 1508 long twigId = Long.parseLong(getStoredValue(twigUri, Data._ID)); 1509 assertEquals(photoId, twigId); 1510 } 1511 1512 public void testUpdateRawContactDataPhoto() { 1513 // setup a contact with a null photo 1514 ContentValues values = new ContentValues(); 1515 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1516 long rawContactId = ContentUris.parseId(rawContactUri); 1517 1518 // setup a photo 1519 values.put(Data.RAW_CONTACT_ID, rawContactId); 1520 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 1521 values.putNull(Photo.PHOTO); 1522 1523 // try to do an update before insert should return count == 0 1524 Uri dataUri = Uri.withAppendedPath( 1525 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 1526 RawContacts.Data.CONTENT_DIRECTORY); 1527 assertEquals(0, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 1528 new String[] {Photo.CONTENT_ITEM_TYPE})); 1529 1530 mResolver.insert(Data.CONTENT_URI, values); 1531 1532 // save a photo to the db 1533 values.clear(); 1534 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 1535 values.put(Photo.PHOTO, loadTestPhoto()); 1536 assertEquals(1, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 1537 new String[] {Photo.CONTENT_ITEM_TYPE})); 1538 1539 // verify the photo 1540 Cursor storedPhoto = mResolver.query(dataUri, new String[] {Photo.PHOTO}, 1541 Data.MIMETYPE + "=?", new String[] {Photo.CONTENT_ITEM_TYPE}, null); 1542 storedPhoto.moveToFirst(); 1543 MoreAsserts.assertEquals(loadTestPhoto(), storedPhoto.getBlob(0)); 1544 } 1545 1546 public void testUpdateRawContactSetStarred() { 1547 long rawContactId1 = createRawContactWithName(); 1548 Uri rawContactUri1 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 1549 long rawContactId2 = createRawContactWithName(); 1550 Uri rawContactUri2 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2); 1551 1552 assertAggregated(rawContactId1, rawContactId2); 1553 1554 long contactId = queryContactId(rawContactId1); 1555 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1556 assertStoredValue(contactUri, Contacts.STARRED, "0"); 1557 1558 ContentValues values = new ContentValues(); 1559 values.put(RawContacts.STARRED, "1"); 1560 1561 mResolver.update(rawContactUri1, values, null, null); 1562 1563 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 1564 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 1565 assertStoredValue(contactUri, Contacts.STARRED, "1"); 1566 1567 values.put(RawContacts.STARRED, "0"); 1568 mResolver.update(rawContactUri1, values, null, null); 1569 1570 assertStoredValue(rawContactUri1, RawContacts.STARRED, "0"); 1571 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 1572 assertStoredValue(contactUri, Contacts.STARRED, "0"); 1573 1574 values.put(Contacts.STARRED, "1"); 1575 mResolver.update(contactUri, values, null, null); 1576 1577 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 1578 assertStoredValue(rawContactUri2, RawContacts.STARRED, "1"); 1579 assertStoredValue(contactUri, Contacts.STARRED, "1"); 1580 } 1581 1582 public void testLiveFolders() { 1583 long rawContactId1 = createRawContactWithName("James", "Sullivan"); 1584 insertPhoneNumber(rawContactId1, "5234567890"); 1585 long contactId1 = queryContactId(rawContactId1); 1586 1587 long rawContactId2 = createRawContactWithName("Mike", "Wazowski"); 1588 long contactId2 = queryContactId(rawContactId2); 1589 storeValue(Contacts.CONTENT_URI, contactId2, Contacts.STARRED, "1"); 1590 1591 long rawContactId3 = createRawContactWithName("Randall", "Boggs"); 1592 long contactId3 = queryContactId(rawContactId3); 1593 long groupId = createGroup(NO_ACCOUNT, "src1", "VIP"); 1594 insertGroupMembership(rawContactId3, groupId); 1595 1596 assertLiveFolderContents( 1597 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 1598 "live_folders/contacts"), 1599 contactId1, "James Sullivan", 1600 contactId2, "Mike Wazowski", 1601 contactId3, "Randall Boggs"); 1602 1603 assertLiveFolderContents( 1604 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 1605 "live_folders/contacts_with_phones"), 1606 contactId1, "James Sullivan"); 1607 1608 assertLiveFolderContents( 1609 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 1610 "live_folders/favorites"), 1611 contactId2, "Mike Wazowski"); 1612 1613 assertLiveFolderContents( 1614 Uri.withAppendedPath(Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 1615 "live_folders/contacts"), Uri.encode("VIP")), 1616 contactId3, "Randall Boggs"); 1617 } 1618 1619 private void assertLiveFolderContents(Uri uri, Object... expected) { 1620 Cursor c = mResolver.query(uri, new String[]{LiveFolders._ID, LiveFolders.NAME}, 1621 null, null, LiveFolders._ID); 1622 assertEquals(expected.length/2, c.getCount()); 1623 for (int i = 0; i < expected.length/2; i++) { 1624 assertTrue(c.moveToNext()); 1625 assertEquals(((Long)expected[i * 2]).longValue(), c.getLong(0)); 1626 assertEquals(expected[i * 2 + 1], c.getString(1)); 1627 } 1628 c.close(); 1629 } 1630 1631 private long createContact(ContentValues values, String firstName, String givenName, 1632 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 1633 long groupId) { 1634 values.put(RawContacts.STARRED, starred); 1635 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 1636 values.put(RawContacts.CUSTOM_RINGTONE, "beethoven5"); 1637 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 1638 values.put(RawContacts.TIMES_CONTACTED, timesContacted); 1639 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1640 long rawContactId = ContentUris.parseId(rawContactUri); 1641 insertStructuredName(rawContactId, firstName, givenName); 1642 Uri photoUri = insertPhoto(rawContactId); 1643 long photoId = ContentUris.parseId(photoUri); 1644 values.put(Contacts.PHOTO_ID, photoId); 1645 insertPhoneNumber(rawContactId, phoneNumber); 1646 insertEmail(rawContactId, email); 1647 1648 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, email, presenceStatus, "hacking"); 1649 1650 if (groupId != 0) { 1651 insertGroupMembership(rawContactId, groupId); 1652 } 1653 1654 return queryContactId(rawContactId); 1655 } 1656 1657 private void putDataValues(ContentValues values, long rawContactId) { 1658 values.put(Data.RAW_CONTACT_ID, rawContactId); 1659 values.put(Data.MIMETYPE, "testmimetype"); 1660 values.put(Data.RES_PACKAGE, "oldpackage"); 1661 values.put(Data.IS_PRIMARY, 1); 1662 values.put(Data.IS_SUPER_PRIMARY, 1); 1663 values.put(Data.DATA1, "one"); 1664 values.put(Data.DATA2, "two"); 1665 values.put(Data.DATA3, "three"); 1666 values.put(Data.DATA4, "four"); 1667 values.put(Data.DATA5, "five"); 1668 values.put(Data.DATA6, "six"); 1669 values.put(Data.DATA7, "seven"); 1670 values.put(Data.DATA8, "eight"); 1671 values.put(Data.DATA9, "nine"); 1672 values.put(Data.DATA10, "ten"); 1673 values.put(Data.DATA11, "eleven"); 1674 values.put(Data.DATA12, "twelve"); 1675 values.put(Data.DATA13, "thirteen"); 1676 values.put(Data.DATA14, "fourteen"); 1677 values.put(Data.DATA15, "fifteen"); 1678 values.put(Data.SYNC1, "sync1"); 1679 values.put(Data.SYNC2, "sync2"); 1680 values.put(Data.SYNC3, "sync3"); 1681 values.put(Data.SYNC4, "sync4"); 1682 } 1683} 1684 1685