ContactsProvider2Test.java revision 6dd371aea88e09cbe56b8c483021f3bf61527331
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.AggregationExceptionColumns; 21import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 22import com.google.android.collect.Lists; 23 24import android.accounts.Account; 25import android.content.ContentProviderOperation; 26import android.content.ContentProviderResult; 27import android.content.ContentUris; 28import android.content.ContentValues; 29import android.content.Entity; 30import android.content.EntityIterator; 31import android.content.res.AssetFileDescriptor; 32import android.database.Cursor; 33import android.net.Uri; 34import android.provider.ContactsContract; 35import android.provider.ContactsContract.AggregationExceptions; 36import android.provider.ContactsContract.CommonDataKinds.Email; 37import android.provider.ContactsContract.CommonDataKinds.GroupMembership; 38import android.provider.ContactsContract.CommonDataKinds.Im; 39import android.provider.ContactsContract.CommonDataKinds.Nickname; 40import android.provider.ContactsContract.CommonDataKinds.Organization; 41import android.provider.ContactsContract.CommonDataKinds.Phone; 42import android.provider.ContactsContract.CommonDataKinds.Photo; 43import android.provider.ContactsContract.CommonDataKinds.StructuredName; 44import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 45import android.provider.ContactsContract.ContactCounts; 46import android.provider.ContactsContract.Contacts; 47import android.provider.ContactsContract.Data; 48import android.provider.ContactsContract.Directory; 49import android.provider.ContactsContract.DisplayNameSources; 50import android.provider.ContactsContract.FullNameStyle; 51import android.provider.ContactsContract.Groups; 52import android.provider.ContactsContract.PhoneLookup; 53import android.provider.ContactsContract.PhoneticNameStyle; 54import android.provider.ContactsContract.ProviderStatus; 55import android.provider.ContactsContract.RawContacts; 56import android.provider.ContactsContract.RawContactsEntity; 57import android.provider.ContactsContract.SearchSnippetColumns; 58import android.provider.ContactsContract.Settings; 59import android.provider.ContactsContract.StatusUpdates; 60import android.provider.LiveFolders; 61import android.provider.OpenableColumns; 62import android.test.MoreAsserts; 63import android.test.suitebuilder.annotation.LargeTest; 64 65import java.io.FileInputStream; 66import java.io.IOException; 67import java.io.InputStream; 68import java.text.Collator; 69import java.util.Arrays; 70import java.util.Locale; 71 72/** 73 * Unit tests for {@link ContactsProvider2}. 74 * 75 * Run the test like this: 76 * <code> 77 * adb shell am instrument -e class com.android.providers.contacts.ContactsProvider2Test -w \ 78 * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner 79 * </code> 80 */ 81@LargeTest 82public class ContactsProvider2Test extends BaseContactsProvider2Test { 83 84 private static final Account ACCOUNT_1 = new Account("account_name_1", "account_type_1"); 85 private static final Account ACCOUNT_2 = new Account("account_name_2", "account_type_2"); 86 87 public void testContactsProjection() { 88 assertProjection(Contacts.CONTENT_URI, new String[]{ 89 Contacts._ID, 90 Contacts.DISPLAY_NAME_PRIMARY, 91 Contacts.DISPLAY_NAME_ALTERNATIVE, 92 Contacts.DISPLAY_NAME_SOURCE, 93 Contacts.PHONETIC_NAME, 94 Contacts.PHONETIC_NAME_STYLE, 95 Contacts.SORT_KEY_PRIMARY, 96 Contacts.SORT_KEY_ALTERNATIVE, 97 Contacts.LAST_TIME_CONTACTED, 98 Contacts.TIMES_CONTACTED, 99 Contacts.STARRED, 100 Contacts.IN_VISIBLE_GROUP, 101 Contacts.PHOTO_ID, 102 Contacts.PHOTO_URI, 103 Contacts.PHOTO_THUMBNAIL_URI, 104 Contacts.CUSTOM_RINGTONE, 105 Contacts.HAS_PHONE_NUMBER, 106 Contacts.SEND_TO_VOICEMAIL, 107 Contacts.LOOKUP_KEY, 108 Contacts.NAME_RAW_CONTACT_ID, 109 Contacts.CONTACT_PRESENCE, 110 Contacts.CONTACT_CHAT_CAPABILITY, 111 Contacts.CONTACT_STATUS, 112 Contacts.CONTACT_STATUS_TIMESTAMP, 113 Contacts.CONTACT_STATUS_RES_PACKAGE, 114 Contacts.CONTACT_STATUS_LABEL, 115 Contacts.CONTACT_STATUS_ICON, 116 }); 117 } 118 119 public void testContactsWithSnippetProjection() { 120 assertProjection(Contacts.CONTENT_FILTER_URI.buildUpon().appendPath("nothing").build(), 121 new String[]{ 122 Contacts._ID, 123 Contacts.DISPLAY_NAME_PRIMARY, 124 Contacts.DISPLAY_NAME_ALTERNATIVE, 125 Contacts.DISPLAY_NAME_SOURCE, 126 Contacts.PHONETIC_NAME, 127 Contacts.PHONETIC_NAME_STYLE, 128 Contacts.SORT_KEY_PRIMARY, 129 Contacts.SORT_KEY_ALTERNATIVE, 130 Contacts.LAST_TIME_CONTACTED, 131 Contacts.TIMES_CONTACTED, 132 Contacts.STARRED, 133 Contacts.IN_VISIBLE_GROUP, 134 Contacts.PHOTO_ID, 135 Contacts.PHOTO_URI, 136 Contacts.PHOTO_THUMBNAIL_URI, 137 Contacts.CUSTOM_RINGTONE, 138 Contacts.HAS_PHONE_NUMBER, 139 Contacts.SEND_TO_VOICEMAIL, 140 Contacts.LOOKUP_KEY, 141 Contacts.NAME_RAW_CONTACT_ID, 142 Contacts.CONTACT_PRESENCE, 143 Contacts.CONTACT_CHAT_CAPABILITY, 144 Contacts.CONTACT_STATUS, 145 Contacts.CONTACT_STATUS_TIMESTAMP, 146 Contacts.CONTACT_STATUS_RES_PACKAGE, 147 Contacts.CONTACT_STATUS_LABEL, 148 Contacts.CONTACT_STATUS_ICON, 149 150 SearchSnippetColumns.SNIPPET_MIMETYPE, 151 SearchSnippetColumns.SNIPPET_DATA_ID, 152 SearchSnippetColumns.SNIPPET_DATA1, 153 SearchSnippetColumns.SNIPPET_DATA2, 154 SearchSnippetColumns.SNIPPET_DATA3, 155 SearchSnippetColumns.SNIPPET_DATA4, 156 }); 157 } 158 159 public void testRawContactsProjection() { 160 assertProjection(RawContacts.CONTENT_URI, new String[]{ 161 RawContacts._ID, 162 RawContacts.CONTACT_ID, 163 RawContacts.ACCOUNT_NAME, 164 RawContacts.ACCOUNT_TYPE, 165 RawContacts.SOURCE_ID, 166 RawContacts.VERSION, 167 RawContacts.DIRTY, 168 RawContacts.DELETED, 169 RawContacts.DISPLAY_NAME_PRIMARY, 170 RawContacts.DISPLAY_NAME_ALTERNATIVE, 171 RawContacts.DISPLAY_NAME_SOURCE, 172 RawContacts.PHONETIC_NAME, 173 RawContacts.PHONETIC_NAME_STYLE, 174 RawContacts.NAME_VERIFIED, 175 RawContacts.SORT_KEY_PRIMARY, 176 RawContacts.SORT_KEY_ALTERNATIVE, 177 RawContacts.TIMES_CONTACTED, 178 RawContacts.LAST_TIME_CONTACTED, 179 RawContacts.CUSTOM_RINGTONE, 180 RawContacts.SEND_TO_VOICEMAIL, 181 RawContacts.STARRED, 182 RawContacts.AGGREGATION_MODE, 183 RawContacts.SYNC1, 184 RawContacts.SYNC2, 185 RawContacts.SYNC3, 186 RawContacts.SYNC4, 187 }); 188 } 189 190 public void testDataProjection() { 191 assertProjection(Data.CONTENT_URI, new String[]{ 192 Data._ID, 193 Data.RAW_CONTACT_ID, 194 Data.DATA_VERSION, 195 Data.IS_PRIMARY, 196 Data.IS_SUPER_PRIMARY, 197 Data.RES_PACKAGE, 198 Data.MIMETYPE, 199 Data.DATA1, 200 Data.DATA2, 201 Data.DATA3, 202 Data.DATA4, 203 Data.DATA5, 204 Data.DATA6, 205 Data.DATA7, 206 Data.DATA8, 207 Data.DATA9, 208 Data.DATA10, 209 Data.DATA11, 210 Data.DATA12, 211 Data.DATA13, 212 Data.DATA14, 213 Data.DATA15, 214 Data.SYNC1, 215 Data.SYNC2, 216 Data.SYNC3, 217 Data.SYNC4, 218 Data.CONTACT_ID, 219 Data.PRESENCE, 220 Data.CHAT_CAPABILITY, 221 Data.STATUS, 222 Data.STATUS_TIMESTAMP, 223 Data.STATUS_RES_PACKAGE, 224 Data.STATUS_LABEL, 225 Data.STATUS_ICON, 226 RawContacts.ACCOUNT_NAME, 227 RawContacts.ACCOUNT_TYPE, 228 RawContacts.SOURCE_ID, 229 RawContacts.VERSION, 230 RawContacts.DIRTY, 231 RawContacts.NAME_VERIFIED, 232 Contacts._ID, 233 Contacts.DISPLAY_NAME_PRIMARY, 234 Contacts.DISPLAY_NAME_ALTERNATIVE, 235 Contacts.DISPLAY_NAME_SOURCE, 236 Contacts.PHONETIC_NAME, 237 Contacts.PHONETIC_NAME_STYLE, 238 Contacts.SORT_KEY_PRIMARY, 239 Contacts.SORT_KEY_ALTERNATIVE, 240 Contacts.LAST_TIME_CONTACTED, 241 Contacts.TIMES_CONTACTED, 242 Contacts.STARRED, 243 Contacts.IN_VISIBLE_GROUP, 244 Contacts.PHOTO_ID, 245 Contacts.PHOTO_URI, 246 Contacts.PHOTO_THUMBNAIL_URI, 247 Contacts.CUSTOM_RINGTONE, 248 Contacts.SEND_TO_VOICEMAIL, 249 Contacts.LOOKUP_KEY, 250 Contacts.NAME_RAW_CONTACT_ID, 251 Contacts.HAS_PHONE_NUMBER, 252 Contacts.CONTACT_PRESENCE, 253 Contacts.CONTACT_CHAT_CAPABILITY, 254 Contacts.CONTACT_STATUS, 255 Contacts.CONTACT_STATUS_TIMESTAMP, 256 Contacts.CONTACT_STATUS_RES_PACKAGE, 257 Contacts.CONTACT_STATUS_LABEL, 258 Contacts.CONTACT_STATUS_ICON, 259 GroupMembership.GROUP_SOURCE_ID, 260 }); 261 } 262 263 public void testDistinctDataProjection() { 264 assertProjection(Phone.CONTENT_FILTER_URI.buildUpon().appendPath("123").build(), 265 new String[]{ 266 Data._ID, 267 Data.DATA_VERSION, 268 Data.IS_PRIMARY, 269 Data.IS_SUPER_PRIMARY, 270 Data.RES_PACKAGE, 271 Data.MIMETYPE, 272 Data.DATA1, 273 Data.DATA2, 274 Data.DATA3, 275 Data.DATA4, 276 Data.DATA5, 277 Data.DATA6, 278 Data.DATA7, 279 Data.DATA8, 280 Data.DATA9, 281 Data.DATA10, 282 Data.DATA11, 283 Data.DATA12, 284 Data.DATA13, 285 Data.DATA14, 286 Data.DATA15, 287 Data.SYNC1, 288 Data.SYNC2, 289 Data.SYNC3, 290 Data.SYNC4, 291 Data.CONTACT_ID, 292 Data.PRESENCE, 293 Data.CHAT_CAPABILITY, 294 Data.STATUS, 295 Data.STATUS_TIMESTAMP, 296 Data.STATUS_RES_PACKAGE, 297 Data.STATUS_LABEL, 298 Data.STATUS_ICON, 299 Contacts._ID, 300 Contacts.DISPLAY_NAME_PRIMARY, 301 Contacts.DISPLAY_NAME_ALTERNATIVE, 302 Contacts.DISPLAY_NAME_SOURCE, 303 Contacts.PHONETIC_NAME, 304 Contacts.PHONETIC_NAME_STYLE, 305 Contacts.SORT_KEY_PRIMARY, 306 Contacts.SORT_KEY_ALTERNATIVE, 307 Contacts.LAST_TIME_CONTACTED, 308 Contacts.TIMES_CONTACTED, 309 Contacts.STARRED, 310 Contacts.IN_VISIBLE_GROUP, 311 Contacts.PHOTO_ID, 312 Contacts.PHOTO_URI, 313 Contacts.PHOTO_THUMBNAIL_URI, 314 Contacts.HAS_PHONE_NUMBER, 315 Contacts.CUSTOM_RINGTONE, 316 Contacts.SEND_TO_VOICEMAIL, 317 Contacts.LOOKUP_KEY, 318 Contacts.CONTACT_PRESENCE, 319 Contacts.CONTACT_CHAT_CAPABILITY, 320 Contacts.CONTACT_STATUS, 321 Contacts.CONTACT_STATUS_TIMESTAMP, 322 Contacts.CONTACT_STATUS_RES_PACKAGE, 323 Contacts.CONTACT_STATUS_LABEL, 324 Contacts.CONTACT_STATUS_ICON, 325 GroupMembership.GROUP_SOURCE_ID, 326 }); 327 } 328 329 public void testEntityProjection() { 330 assertProjection( 331 Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 0), 332 Contacts.Entity.CONTENT_DIRECTORY), 333 new String[]{ 334 Contacts.Entity._ID, 335 Contacts.Entity.DATA_ID, 336 Contacts.Entity.RAW_CONTACT_ID, 337 Data.DATA_VERSION, 338 Data.IS_PRIMARY, 339 Data.IS_SUPER_PRIMARY, 340 Data.RES_PACKAGE, 341 Data.MIMETYPE, 342 Data.DATA1, 343 Data.DATA2, 344 Data.DATA3, 345 Data.DATA4, 346 Data.DATA5, 347 Data.DATA6, 348 Data.DATA7, 349 Data.DATA8, 350 Data.DATA9, 351 Data.DATA10, 352 Data.DATA11, 353 Data.DATA12, 354 Data.DATA13, 355 Data.DATA14, 356 Data.DATA15, 357 Data.SYNC1, 358 Data.SYNC2, 359 Data.SYNC3, 360 Data.SYNC4, 361 Data.CONTACT_ID, 362 Data.PRESENCE, 363 Data.CHAT_CAPABILITY, 364 Data.STATUS, 365 Data.STATUS_TIMESTAMP, 366 Data.STATUS_RES_PACKAGE, 367 Data.STATUS_LABEL, 368 Data.STATUS_ICON, 369 RawContacts.ACCOUNT_NAME, 370 RawContacts.ACCOUNT_TYPE, 371 RawContacts.SOURCE_ID, 372 RawContacts.VERSION, 373 RawContacts.DELETED, 374 RawContacts.DIRTY, 375 RawContacts.NAME_VERIFIED, 376 RawContacts.SYNC1, 377 RawContacts.SYNC2, 378 RawContacts.SYNC3, 379 RawContacts.SYNC4, 380 RawContacts.IS_RESTRICTED, 381 Contacts._ID, 382 Contacts.DISPLAY_NAME_PRIMARY, 383 Contacts.DISPLAY_NAME_ALTERNATIVE, 384 Contacts.DISPLAY_NAME_SOURCE, 385 Contacts.PHONETIC_NAME, 386 Contacts.PHONETIC_NAME_STYLE, 387 Contacts.SORT_KEY_PRIMARY, 388 Contacts.SORT_KEY_ALTERNATIVE, 389 Contacts.LAST_TIME_CONTACTED, 390 Contacts.TIMES_CONTACTED, 391 Contacts.STARRED, 392 Contacts.IN_VISIBLE_GROUP, 393 Contacts.PHOTO_ID, 394 Contacts.PHOTO_URI, 395 Contacts.PHOTO_THUMBNAIL_URI, 396 Contacts.CUSTOM_RINGTONE, 397 Contacts.SEND_TO_VOICEMAIL, 398 Contacts.LOOKUP_KEY, 399 Contacts.NAME_RAW_CONTACT_ID, 400 Contacts.HAS_PHONE_NUMBER, 401 Contacts.CONTACT_PRESENCE, 402 Contacts.CONTACT_CHAT_CAPABILITY, 403 Contacts.CONTACT_STATUS, 404 Contacts.CONTACT_STATUS_TIMESTAMP, 405 Contacts.CONTACT_STATUS_RES_PACKAGE, 406 Contacts.CONTACT_STATUS_LABEL, 407 Contacts.CONTACT_STATUS_ICON, 408 GroupMembership.GROUP_SOURCE_ID, 409 }); 410 } 411 412 public void testRawEntityProjection() { 413 assertProjection(RawContactsEntity.CONTENT_URI, new String[]{ 414 RawContacts.Entity.DATA_ID, 415 RawContacts._ID, 416 RawContacts.CONTACT_ID, 417 RawContacts.ACCOUNT_NAME, 418 RawContacts.ACCOUNT_TYPE, 419 RawContacts.SOURCE_ID, 420 RawContacts.VERSION, 421 RawContacts.DIRTY, 422 RawContacts.NAME_VERIFIED, 423 RawContacts.DELETED, 424 RawContacts.IS_RESTRICTED, 425 RawContacts.SYNC1, 426 RawContacts.SYNC2, 427 RawContacts.SYNC3, 428 RawContacts.SYNC4, 429 RawContacts.STARRED, 430 Data.DATA_VERSION, 431 Data.IS_PRIMARY, 432 Data.IS_SUPER_PRIMARY, 433 Data.RES_PACKAGE, 434 Data.MIMETYPE, 435 Data.DATA1, 436 Data.DATA2, 437 Data.DATA3, 438 Data.DATA4, 439 Data.DATA5, 440 Data.DATA6, 441 Data.DATA7, 442 Data.DATA8, 443 Data.DATA9, 444 Data.DATA10, 445 Data.DATA11, 446 Data.DATA12, 447 Data.DATA13, 448 Data.DATA14, 449 Data.DATA15, 450 Data.SYNC1, 451 Data.SYNC2, 452 Data.SYNC3, 453 Data.SYNC4, 454 GroupMembership.GROUP_SOURCE_ID, 455 }); 456 } 457 458 public void testPhoneLookupProjection() { 459 assertProjection(PhoneLookup.CONTENT_FILTER_URI.buildUpon().appendPath("123").build(), 460 new String[]{ 461 PhoneLookup._ID, 462 PhoneLookup.LOOKUP_KEY, 463 PhoneLookup.DISPLAY_NAME, 464 PhoneLookup.LAST_TIME_CONTACTED, 465 PhoneLookup.TIMES_CONTACTED, 466 PhoneLookup.STARRED, 467 PhoneLookup.IN_VISIBLE_GROUP, 468 PhoneLookup.PHOTO_ID, 469 PhoneLookup.PHOTO_URI, 470 PhoneLookup.PHOTO_THUMBNAIL_URI, 471 PhoneLookup.CUSTOM_RINGTONE, 472 PhoneLookup.HAS_PHONE_NUMBER, 473 PhoneLookup.SEND_TO_VOICEMAIL, 474 PhoneLookup.NUMBER, 475 PhoneLookup.TYPE, 476 PhoneLookup.LABEL, 477 PhoneLookup.NORMALIZED_NUMBER, 478 }); 479 } 480 481 public void testGroupsProjection() { 482 assertProjection(Groups.CONTENT_URI, new String[]{ 483 Groups._ID, 484 Groups.ACCOUNT_NAME, 485 Groups.ACCOUNT_TYPE, 486 Groups.SOURCE_ID, 487 Groups.DIRTY, 488 Groups.VERSION, 489 Groups.RES_PACKAGE, 490 Groups.TITLE, 491 Groups.TITLE_RES, 492 Groups.GROUP_VISIBLE, 493 Groups.SYSTEM_ID, 494 Groups.DELETED, 495 Groups.NOTES, 496 Groups.SHOULD_SYNC, 497 Groups.FAVORITES, 498 Groups.AUTO_ADD, 499 Groups.GROUP_IS_READ_ONLY, 500 Groups.SYNC1, 501 Groups.SYNC2, 502 Groups.SYNC3, 503 Groups.SYNC4, 504 }); 505 } 506 507 public void testGroupsSummaryProjection() { 508 assertProjection(Groups.CONTENT_SUMMARY_URI, new String[]{ 509 Groups._ID, 510 Groups.ACCOUNT_NAME, 511 Groups.ACCOUNT_TYPE, 512 Groups.SOURCE_ID, 513 Groups.DIRTY, 514 Groups.VERSION, 515 Groups.RES_PACKAGE, 516 Groups.TITLE, 517 Groups.TITLE_RES, 518 Groups.GROUP_VISIBLE, 519 Groups.SYSTEM_ID, 520 Groups.DELETED, 521 Groups.NOTES, 522 Groups.SHOULD_SYNC, 523 Groups.FAVORITES, 524 Groups.AUTO_ADD, 525 Groups.GROUP_IS_READ_ONLY, 526 Groups.SYNC1, 527 Groups.SYNC2, 528 Groups.SYNC3, 529 Groups.SYNC4, 530 Groups.SUMMARY_COUNT, 531 Groups.SUMMARY_WITH_PHONES, 532 }); 533 } 534 535 public void testAggregateExceptionProjection() { 536 assertProjection(AggregationExceptions.CONTENT_URI, new String[]{ 537 AggregationExceptionColumns._ID, 538 AggregationExceptions.TYPE, 539 AggregationExceptions.RAW_CONTACT_ID1, 540 AggregationExceptions.RAW_CONTACT_ID2, 541 }); 542 } 543 544 public void testSettingsProjection() { 545 assertProjection(Settings.CONTENT_URI, new String[]{ 546 Settings.ACCOUNT_NAME, 547 Settings.ACCOUNT_TYPE, 548 Settings.UNGROUPED_VISIBLE, 549 Settings.SHOULD_SYNC, 550 Settings.ANY_UNSYNCED, 551 Settings.UNGROUPED_COUNT, 552 Settings.UNGROUPED_WITH_PHONES, 553 }); 554 } 555 556 public void testStatusUpdatesProjection() { 557 assertProjection(StatusUpdates.CONTENT_URI, new String[]{ 558 PresenceColumns.RAW_CONTACT_ID, 559 StatusUpdates.DATA_ID, 560 StatusUpdates.IM_ACCOUNT, 561 StatusUpdates.IM_HANDLE, 562 StatusUpdates.PROTOCOL, 563 StatusUpdates.CUSTOM_PROTOCOL, 564 StatusUpdates.PRESENCE, 565 StatusUpdates.CHAT_CAPABILITY, 566 StatusUpdates.STATUS, 567 StatusUpdates.STATUS_TIMESTAMP, 568 StatusUpdates.STATUS_RES_PACKAGE, 569 StatusUpdates.STATUS_ICON, 570 StatusUpdates.STATUS_LABEL, 571 }); 572 } 573 574 public void testLiveFoldersProjection() { 575 assertProjection( 576 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "live_folders/contacts"), 577 new String[]{ 578 LiveFolders._ID, 579 LiveFolders.NAME, 580 }); 581 } 582 583 public void testDirectoryProjection() { 584 assertProjection(Directory.CONTENT_URI, new String[]{ 585 Directory._ID, 586 Directory.PACKAGE_NAME, 587 Directory.TYPE_RESOURCE_ID, 588 Directory.DISPLAY_NAME, 589 Directory.DIRECTORY_AUTHORITY, 590 Directory.ACCOUNT_TYPE, 591 Directory.ACCOUNT_NAME, 592 Directory.EXPORT_SUPPORT, 593 Directory.SHORTCUT_SUPPORT, 594 Directory.PHOTO_SUPPORT, 595 }); 596 } 597 598 public void testRawContactsInsert() { 599 ContentValues values = new ContentValues(); 600 601 values.put(RawContacts.ACCOUNT_NAME, "a"); 602 values.put(RawContacts.ACCOUNT_TYPE, "b"); 603 values.put(RawContacts.SOURCE_ID, "c"); 604 values.put(RawContacts.VERSION, 42); 605 values.put(RawContacts.DIRTY, 1); 606 values.put(RawContacts.DELETED, 1); 607 values.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 608 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 609 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 610 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 611 values.put(RawContacts.STARRED, 1); 612 values.put(RawContacts.SYNC1, "e"); 613 values.put(RawContacts.SYNC2, "f"); 614 values.put(RawContacts.SYNC3, "g"); 615 values.put(RawContacts.SYNC4, "h"); 616 617 Uri rowUri = mResolver.insert(RawContacts.CONTENT_URI, values); 618 long rawContactId = ContentUris.parseId(rowUri); 619 620 assertStoredValues(rowUri, values); 621 assertSelection(RawContacts.CONTENT_URI, values, RawContacts._ID, rawContactId); 622 assertNetworkNotified(true); 623 } 624 625 public void testDataDirectoryWithLookupUri() { 626 ContentValues values = new ContentValues(); 627 628 long rawContactId = createRawContactWithName(); 629 insertPhoneNumber(rawContactId, "555-GOOG-411"); 630 insertEmail(rawContactId, "google@android.com"); 631 632 long contactId = queryContactId(rawContactId); 633 String lookupKey = queryLookupKey(contactId); 634 635 // Complete and valid lookup URI 636 Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); 637 Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY); 638 639 assertDataRows(dataUri, values); 640 641 // Complete but stale lookup URI 642 lookupUri = ContactsContract.Contacts.getLookupUri(contactId + 1, lookupKey); 643 dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY); 644 assertDataRows(dataUri, values); 645 646 // Incomplete lookup URI (lookup key only, no contact ID) 647 dataUri = Uri.withAppendedPath(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, 648 lookupKey), Contacts.Data.CONTENT_DIRECTORY); 649 assertDataRows(dataUri, values); 650 } 651 652 private void assertDataRows(Uri dataUri, ContentValues values) { 653 Cursor cursor = mResolver.query(dataUri, new String[]{ Data.DATA1 }, null, null, Data._ID); 654 assertEquals(3, cursor.getCount()); 655 cursor.moveToFirst(); 656 values.put(Data.DATA1, "John Doe"); 657 assertCursorValues(cursor, values); 658 659 cursor.moveToNext(); 660 values.put(Data.DATA1, "555-GOOG-411"); 661 assertCursorValues(cursor, values); 662 663 cursor.moveToNext(); 664 values.put(Data.DATA1, "google@android.com"); 665 assertCursorValues(cursor, values); 666 667 cursor.close(); 668 } 669 670 public void testContactEntitiesWithIdBasedUri() { 671 ContentValues values = new ContentValues(); 672 Account account1 = new Account("act1", "actype1"); 673 Account account2 = new Account("act2", "actype2"); 674 675 long rawContactId1 = createRawContactWithName(account1); 676 insertImHandle(rawContactId1, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 677 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", StatusUpdates.IDLE, "Busy", 90, 678 StatusUpdates.CAPABILITY_HAS_CAMERA); 679 680 long rawContactId2 = createRawContact(account2); 681 setAggregationException( 682 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 683 684 long contactId = queryContactId(rawContactId1); 685 686 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 687 Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY); 688 689 assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 690 } 691 692 public void testContactEntitiesWithLookupUri() { 693 ContentValues values = new ContentValues(); 694 Account account1 = new Account("act1", "actype1"); 695 Account account2 = new Account("act2", "actype2"); 696 697 long rawContactId1 = createRawContactWithName(account1); 698 insertImHandle(rawContactId1, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 699 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", StatusUpdates.IDLE, "Busy", 90, 700 StatusUpdates.CAPABILITY_HAS_CAMERA); 701 702 long rawContactId2 = createRawContact(account2); 703 setAggregationException( 704 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 705 706 long contactId = queryContactId(rawContactId1); 707 String lookupKey = queryLookupKey(contactId); 708 709 // First try with a matching contact ID 710 Uri contactLookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); 711 Uri entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 712 assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 713 714 // Now try with a contact ID mismatch 715 contactLookupUri = ContactsContract.Contacts.getLookupUri(contactId + 1, lookupKey); 716 entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 717 assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 718 719 // Now try without an ID altogether 720 contactLookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey); 721 entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 722 assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 723 } 724 725 private void assertEntityRows(Uri entityUri, long contactId, long rawContactId1, 726 long rawContactId2) { 727 ContentValues values = new ContentValues(); 728 729 Cursor cursor = mResolver.query(entityUri, null, null, null, 730 Contacts.Entity.RAW_CONTACT_ID + "," + Contacts.Entity.DATA_ID); 731 assertEquals(3, cursor.getCount()); 732 733 // First row - name 734 cursor.moveToFirst(); 735 values.put(Contacts.Entity.CONTACT_ID, contactId); 736 values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId1); 737 values.put(Contacts.Entity.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 738 values.put(Contacts.Entity.DATA1, "John Doe"); 739 values.put(Contacts.Entity.ACCOUNT_NAME, "act1"); 740 values.put(Contacts.Entity.ACCOUNT_TYPE, "actype1"); 741 values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 742 values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 743 values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 744 values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 745 values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 746 values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 747 values.putNull(Contacts.Entity.PRESENCE); 748 assertCursorValues(cursor, values); 749 750 // Second row - IM 751 cursor.moveToNext(); 752 values.put(Contacts.Entity.CONTACT_ID, contactId); 753 values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId1); 754 values.put(Contacts.Entity.MIMETYPE, Im.CONTENT_ITEM_TYPE); 755 values.put(Contacts.Entity.DATA1, "gtalk"); 756 values.put(Contacts.Entity.ACCOUNT_NAME, "act1"); 757 values.put(Contacts.Entity.ACCOUNT_TYPE, "actype1"); 758 values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 759 values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 760 values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 761 values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 762 values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 763 values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 764 values.put(Contacts.Entity.PRESENCE, StatusUpdates.IDLE); 765 assertCursorValues(cursor, values); 766 767 // Third row - second raw contact, not data 768 cursor.moveToNext(); 769 values.put(Contacts.Entity.CONTACT_ID, contactId); 770 values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId2); 771 values.putNull(Contacts.Entity.MIMETYPE); 772 values.putNull(Contacts.Entity.DATA_ID); 773 values.putNull(Contacts.Entity.DATA1); 774 values.put(Contacts.Entity.ACCOUNT_NAME, "act2"); 775 values.put(Contacts.Entity.ACCOUNT_TYPE, "actype2"); 776 values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 777 values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 778 values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 779 values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 780 values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 781 values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 782 values.putNull(Contacts.Entity.PRESENCE); 783 assertCursorValues(cursor, values); 784 785 cursor.close(); 786 } 787 788 public void testDataInsert() { 789 long rawContactId = createRawContactWithName("John", "Doe"); 790 791 ContentValues values = new ContentValues(); 792 putDataValues(values, rawContactId); 793 Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 794 long dataId = ContentUris.parseId(dataUri); 795 796 long contactId = queryContactId(rawContactId); 797 values.put(RawContacts.CONTACT_ID, contactId); 798 assertStoredValues(dataUri, values); 799 800 assertSelection(Data.CONTENT_URI, values, Data._ID, dataId); 801 802 // Access the same data through the directory under RawContacts 803 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 804 Uri rawContactDataUri = 805 Uri.withAppendedPath(rawContactUri, RawContacts.Data.CONTENT_DIRECTORY); 806 assertSelection(rawContactDataUri, values, Data._ID, dataId); 807 808 // Access the same data through the directory under Contacts 809 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 810 Uri contactDataUri = Uri.withAppendedPath(contactUri, Contacts.Data.CONTENT_DIRECTORY); 811 assertSelection(contactDataUri, values, Data._ID, dataId); 812 assertNetworkNotified(true); 813 } 814 815 public void testRawContactDataQuery() { 816 Account account1 = new Account("a", "b"); 817 Account account2 = new Account("c", "d"); 818 long rawContactId1 = createRawContact(account1); 819 Uri dataUri1 = insertStructuredName(rawContactId1, "John", "Doe"); 820 long rawContactId2 = createRawContact(account2); 821 Uri dataUri2 = insertStructuredName(rawContactId2, "Jane", "Doe"); 822 823 Uri uri1 = maybeAddAccountQueryParameters(dataUri1, account1); 824 Uri uri2 = maybeAddAccountQueryParameters(dataUri2, account2); 825 assertStoredValue(uri1, Data._ID, ContentUris.parseId(dataUri1)) ; 826 assertStoredValue(uri2, Data._ID, ContentUris.parseId(dataUri2)) ; 827 } 828 829 public void testPhonesQuery() { 830 831 ContentValues values = new ContentValues(); 832 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 833 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 834 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 835 values.put(RawContacts.TIMES_CONTACTED, 54321); 836 values.put(RawContacts.STARRED, 1); 837 838 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 839 long rawContactId = ContentUris.parseId(rawContactUri); 840 841 insertStructuredName(rawContactId, "Meghan", "Knox"); 842 Uri uri = insertPhoneNumber(rawContactId, "18004664411"); 843 long phoneId = ContentUris.parseId(uri); 844 845 846 long contactId = queryContactId(rawContactId); 847 values.clear(); 848 values.put(Data._ID, phoneId); 849 values.put(Data.RAW_CONTACT_ID, rawContactId); 850 values.put(RawContacts.CONTACT_ID, contactId); 851 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 852 values.put(Phone.NUMBER, "18004664411"); 853 values.put(Phone.TYPE, Phone.TYPE_HOME); 854 values.putNull(Phone.LABEL); 855 values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 856 values.put(Contacts.CUSTOM_RINGTONE, "d"); 857 values.put(Contacts.SEND_TO_VOICEMAIL, 1); 858 values.put(Contacts.LAST_TIME_CONTACTED, 12345); 859 values.put(Contacts.TIMES_CONTACTED, 54321); 860 values.put(Contacts.STARRED, 1); 861 862 assertStoredValues(ContentUris.withAppendedId(Phone.CONTENT_URI, phoneId), values); 863 assertSelection(Phone.CONTENT_URI, values, Data._ID, phoneId); 864 } 865 866 public void testPhonesFilterQuery() { 867 long rawContactId1 = createRawContactWithName("Hot", "Tamale", ACCOUNT_1); 868 insertPhoneNumber(rawContactId1, "18004664411"); 869 insertPhoneNumber(rawContactId1, "1-800-466-4411"); 870 871 long rawContactId2 = createRawContactWithName("Hot", "Tamale", ACCOUNT_2); 872 insertPhoneNumber(rawContactId2, "1-800-466-4411"); 873 874 Uri filterUri1 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "tamale"); 875 ContentValues values = new ContentValues(); 876 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 877 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 878 values.put(Phone.NUMBER, "1-800-466-4411"); 879 values.put(Phone.TYPE, Phone.TYPE_HOME); 880 values.putNull(Phone.LABEL); 881 assertStoredValuesWithProjection(filterUri1, values); 882 883 Uri filterUri2 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1-800-GOOG-411"); 884 assertStoredValues(filterUri2, values); 885 886 Uri filterUri3 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "18004664"); 887 assertStoredValues(filterUri3, values); 888 889 Uri filterUri4 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "encilada"); 890 assertEquals(0, getCount(filterUri4, null, null)); 891 892 Uri filterUri5 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "*"); 893 assertEquals(0, getCount(filterUri5, null, null)); 894 } 895 896 public void testPhoneLookup() { 897 ContentValues values = new ContentValues(); 898 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 899 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 900 901 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 902 long rawContactId = ContentUris.parseId(rawContactUri); 903 904 insertStructuredName(rawContactId, "Hot", "Tamale"); 905 insertPhoneNumber(rawContactId, "18004664411"); 906 907 Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 908 909 values.clear(); 910 values.put(PhoneLookup._ID, queryContactId(rawContactId)); 911 values.put(PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 912 values.put(PhoneLookup.NUMBER, "18004664411"); 913 values.put(PhoneLookup.TYPE, Phone.TYPE_HOME); 914 values.putNull(PhoneLookup.LABEL); 915 values.put(PhoneLookup.CUSTOM_RINGTONE, "d"); 916 values.put(PhoneLookup.SEND_TO_VOICEMAIL, 1); 917 assertStoredValues(lookupUri1, values); 918 919 // In the context that 8004664411 is a valid number, "4664411" as a 920 // call id should not match to "8004664411" 921 Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "4664411"); 922 assertEquals(0, getCount(lookupUri2, null, null)); 923 } 924 925 public void testPhoneLookupUseCases() { 926 ContentValues values = new ContentValues(); 927 Uri rawContactUri; 928 long rawContactId; 929 Uri lookupUri2; 930 931 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 932 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 933 934 // International format in contacts 935 rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 936 rawContactId = ContentUris.parseId(rawContactUri); 937 938 insertStructuredName(rawContactId, "Hot", "Tamale"); 939 insertPhoneNumber(rawContactId, "+1-650-861-0000"); 940 941 values.clear(); 942 943 // match with international format 944 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0000"); 945 assertEquals(1, getCount(lookupUri2, null, null)); 946 947 // match with national format 948 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0000"); 949 assertEquals(1, getCount(lookupUri2, null, null)); 950 951 // National format in contacts 952 values.clear(); 953 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 954 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 955 rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 956 rawContactId = ContentUris.parseId(rawContactUri); 957 958 insertStructuredName(rawContactId, "Hot1", "Tamale"); 959 insertPhoneNumber(rawContactId, "650-861-0001"); 960 961 values.clear(); 962 963 // match with international format 964 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0001"); 965 assertEquals(2, getCount(lookupUri2, null, null)); 966 967 // match with national format 968 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0001"); 969 assertEquals(2, getCount(lookupUri2, null, null)); 970 971 // Local format in contacts 972 values.clear(); 973 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 974 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 975 rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 976 rawContactId = ContentUris.parseId(rawContactUri); 977 978 insertStructuredName(rawContactId, "Hot2", "Tamale"); 979 insertPhoneNumber(rawContactId, "861-0002"); 980 981 values.clear(); 982 983 // match with international format 984 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0002"); 985 assertEquals(1, getCount(lookupUri2, null, null)); 986 987 // match with national format 988 lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0002"); 989 assertEquals(1, getCount(lookupUri2, null, null)); 990 } 991 992 public void testPhoneUpdate() { 993 ContentValues values = new ContentValues(); 994 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 995 long rawContactId = ContentUris.parseId(rawContactUri); 996 997 insertStructuredName(rawContactId, "Hot", "Tamale"); 998 Uri phoneUri = insertPhoneNumber(rawContactId, "18004664411"); 999 1000 Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 1001 assertStoredValue(lookupUri1, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1002 1003 values.clear(); 1004 values.put(Phone.NUMBER, "18004664422"); 1005 mResolver.update(phoneUri, values, null, null); 1006 1007 Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664422"); 1008 assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1009 1010 // Setting number to null will remove the phone lookup record 1011 values.clear(); 1012 values.putNull(Phone.NUMBER); 1013 mResolver.update(phoneUri, values, null, null); 1014 1015 assertEquals(0, getCount(lookupUri2, null, null)); 1016 1017 // Let's restore that phone lookup record 1018 values.clear(); 1019 values.put(Phone.NUMBER, "18004664422"); 1020 mResolver.update(phoneUri, values, null, null); 1021 assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1022 assertNetworkNotified(true); 1023 } 1024 1025 public void testEmailsQuery() { 1026 ContentValues values = new ContentValues(); 1027 values.put(RawContacts.CUSTOM_RINGTONE, "d"); 1028 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 1029 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 1030 values.put(RawContacts.TIMES_CONTACTED, 54321); 1031 values.put(RawContacts.STARRED, 1); 1032 1033 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1034 long rawContactId = ContentUris.parseId(rawContactUri); 1035 1036 insertStructuredName(rawContactId, "Meghan", "Knox"); 1037 Uri uri = insertEmail(rawContactId, "meghan@acme.com"); 1038 long emailId = ContentUris.parseId(uri); 1039 1040 long contactId = queryContactId(rawContactId); 1041 values.clear(); 1042 values.put(Data._ID, emailId); 1043 values.put(Data.RAW_CONTACT_ID, rawContactId); 1044 values.put(RawContacts.CONTACT_ID, contactId); 1045 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1046 values.put(Email.DATA, "meghan@acme.com"); 1047 values.put(Email.TYPE, Email.TYPE_HOME); 1048 values.putNull(Email.LABEL); 1049 values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 1050 values.put(Contacts.CUSTOM_RINGTONE, "d"); 1051 values.put(Contacts.SEND_TO_VOICEMAIL, 1); 1052 values.put(Contacts.LAST_TIME_CONTACTED, 12345); 1053 values.put(Contacts.TIMES_CONTACTED, 54321); 1054 values.put(Contacts.STARRED, 1); 1055 1056 assertStoredValues(ContentUris.withAppendedId(Email.CONTENT_URI, emailId), values); 1057 assertSelection(Email.CONTENT_URI, values, Data._ID, emailId); 1058 } 1059 1060 public void testEmailsLookupQuery() { 1061 long rawContactId = createRawContactWithName("Hot", "Tamale"); 1062 insertEmail(rawContactId, "tamale@acme.com"); 1063 1064 Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "tamale@acme.com"); 1065 ContentValues values = new ContentValues(); 1066 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 1067 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1068 values.put(Email.DATA, "tamale@acme.com"); 1069 values.put(Email.TYPE, Email.TYPE_HOME); 1070 values.putNull(Email.LABEL); 1071 assertStoredValues(filterUri1, values); 1072 1073 Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "Ta<TaMale@acme.com>"); 1074 assertStoredValues(filterUri2, values); 1075 1076 Uri filterUri3 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "encilada@acme.com"); 1077 assertEquals(0, getCount(filterUri3, null, null)); 1078 } 1079 1080 public void testEmailsFilterQuery() { 1081 long rawContactId1 = createRawContactWithName("Hot", "Tamale", ACCOUNT_1); 1082 insertEmail(rawContactId1, "tamale@acme.com"); 1083 insertEmail(rawContactId1, "tamale@acme.com"); 1084 1085 long rawContactId2 = createRawContactWithName("Hot", "Tamale", ACCOUNT_2); 1086 insertEmail(rawContactId2, "tamale@acme.com"); 1087 1088 Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tam"); 1089 ContentValues values = new ContentValues(); 1090 values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 1091 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1092 values.put(Email.DATA, "tamale@acme.com"); 1093 values.put(Email.TYPE, Email.TYPE_HOME); 1094 values.putNull(Email.LABEL); 1095 assertStoredValuesWithProjection(filterUri1, values); 1096 1097 Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hot"); 1098 assertStoredValuesWithProjection(filterUri2, values); 1099 1100 Uri filterUri3 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hottamale"); 1101 assertStoredValuesWithProjection(filterUri3, values); 1102 1103 Uri filterUri4 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tamale@acme"); 1104 assertStoredValuesWithProjection(filterUri4, values); 1105 1106 Uri filterUri5 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "encilada"); 1107 assertEquals(0, getCount(filterUri5, null, null)); 1108 } 1109 1110 public void testEmailFilterSortOrder() { 1111 1112 // Adding contacts from the end to beginning of the expected order. 1113 1114 // Never contacted 1115 insertContactWithEmail("never", false); 1116 insertContactWithEmail("starred-never", true); 1117 1118 // Contacted a long time ago 1119 insertContactWithEmail("a-longago", 10, 1800, false); 1120 insertContactWithEmail("b-longago", 20, 1000, false); 1121 insertContactWithEmail("c-longago", 30, 2000, false); 1122 1123 // Contacted fairly recently 1124 insertContactWithEmail("a-recent", 10, 18, false); 1125 insertContactWithEmail("b-recent", 20, 10, false); 1126 insertContactWithEmail("c-recent", 30, 20, false); 1127 1128 // Contacted very recently 1129 insertContactWithEmail("a-current", 10, 1, false); 1130 insertContactWithEmail("b-current", 20, 0, false); 1131 insertContactWithEmail("c-current", 30, 2, false); 1132 1133 // Starred 1134 insertContactWithEmail("starred-longago", 10, 100, true); 1135 insertContactWithEmail("starred-current", 10, 10, true); 1136 insertContactWithEmail("starred-recent", 10, 1, true); 1137 1138 Uri filterUri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "findme"); 1139 Cursor cursor = mResolver.query(filterUri, new String[]{Contacts.DISPLAY_NAME}, 1140 null, null, null); 1141 cursor.moveToNext(); 1142 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "starred-recent"); 1143 cursor.moveToNext(); 1144 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "starred-current"); 1145 cursor.moveToNext(); 1146 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "starred-longago"); 1147 cursor.moveToNext(); 1148 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "starred-never"); 1149 cursor.moveToNext(); 1150 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "c-current"); 1151 cursor.moveToNext(); 1152 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "b-current"); 1153 cursor.moveToNext(); 1154 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "a-current"); 1155 cursor.moveToNext(); 1156 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "c-recent"); 1157 cursor.moveToNext(); 1158 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "b-recent"); 1159 cursor.moveToNext(); 1160 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "a-recent"); 1161 cursor.moveToNext(); 1162 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "c-longago"); 1163 cursor.moveToNext(); 1164 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "b-longago"); 1165 cursor.moveToNext(); 1166 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "a-longago"); 1167 cursor.moveToNext(); 1168 assertCursorValue(cursor, Contacts.DISPLAY_NAME, "never"); 1169 cursor.close(); 1170 } 1171 1172 private void insertContactWithEmail(String name, boolean starred) { 1173 long rawContactId = createRawContactWithName(name, null); 1174 long contactId = queryContactId(rawContactId); 1175 if (starred) { 1176 storeValue(Contacts.CONTENT_URI, contactId, Contacts.STARRED, 1); 1177 } 1178 insertEmail(rawContactId, "findme" + name + "@acme.com"); 1179 } 1180 1181 private void insertContactWithEmail( 1182 String name, int timesContacted, int lastTimeContactedDays, boolean starred) { 1183 long rawContactId = createRawContactWithName(name, null); 1184 long contactId = queryContactId(rawContactId); 1185 ContentValues values = new ContentValues(); 1186 values.put(Contacts.TIMES_CONTACTED, timesContacted); 1187 values.put(Contacts.LAST_TIME_CONTACTED, 1188 System.currentTimeMillis() - (lastTimeContactedDays * 24 * 60 * 60 * 1000l)); 1189 if (starred) { 1190 values.put(Contacts.STARRED, 1); 1191 } 1192 mResolver.update( 1193 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), values, null, null); 1194 insertEmail(rawContactId, "findme" + name + "@acme.com"); 1195 } 1196 1197 public void testPostalsQuery() { 1198 long rawContactId = createRawContactWithName("Alice", "Nextore"); 1199 Uri dataUri = insertPostalAddress(rawContactId, "1600 Amphiteatre Ave, Mountain View"); 1200 long dataId = ContentUris.parseId(dataUri); 1201 1202 long contactId = queryContactId(rawContactId); 1203 ContentValues values = new ContentValues(); 1204 values.put(Data._ID, dataId); 1205 values.put(Data.RAW_CONTACT_ID, rawContactId); 1206 values.put(RawContacts.CONTACT_ID, contactId); 1207 values.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); 1208 values.put(StructuredPostal.FORMATTED_ADDRESS, "1600 Amphiteatre Ave, Mountain View"); 1209 values.put(Contacts.DISPLAY_NAME, "Alice Nextore"); 1210 1211 assertStoredValues(ContentUris.withAppendedId(StructuredPostal.CONTENT_URI, dataId), 1212 values); 1213 assertSelection(StructuredPostal.CONTENT_URI, values, Data._ID, dataId); 1214 } 1215 1216 public void testQueryContactData() { 1217 ContentValues values = new ContentValues(); 1218 long contactId = createContact(values, "John", "Doe", 1219 "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 1220 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 1221 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1222 1223 assertStoredValues(contactUri, values); 1224 assertSelection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 1225 } 1226 1227 public void testQueryContactWithStatusUpdate() { 1228 ContentValues values = new ContentValues(); 1229 long contactId = createContact(values, "John", "Doe", 1230 "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 1231 StatusUpdates.CAPABILITY_HAS_CAMERA); 1232 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 1233 values.put(Contacts.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 1234 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1235 assertStoredValuesWithProjection(contactUri, values); 1236 assertSelectionWithProjection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 1237 } 1238 1239 public void testQueryContactFilter() { 1240 ContentValues values = new ContentValues(); 1241 long rawContactId = createRawContact(values, "18004664411", 1242 "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 1243 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 1244 StatusUpdates.CAPABILITY_HAS_VOICE); 1245 1246 ContentValues nameValues = new ContentValues(); 1247 nameValues.put(StructuredName.GIVEN_NAME, "Stu"); 1248 nameValues.put(StructuredName.FAMILY_NAME, "Goulash"); 1249 nameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "goo"); 1250 nameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "LASH"); 1251 Uri nameUri = insertStructuredName(rawContactId, nameValues); 1252 1253 long contactId = queryContactId(rawContactId); 1254 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 1255 1256 Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goulash"); 1257 assertStoredValuesWithProjection(filterUri1, values); 1258 1259 assertContactFilter(contactId, "goolash"); 1260 assertContactFilter(contactId, "lash"); 1261 1262 Uri filterUri2 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goolish"); 1263 assertEquals(0, getCount(filterUri2, null, null)); 1264 1265 // Phonetic name with given/family reversed should not match 1266 Uri filterUri3 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "lashgoo"); 1267 assertEquals(0, getCount(filterUri3, null, null)); 1268 1269 nameValues.clear(); 1270 nameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "ga"); 1271 nameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "losh"); 1272 1273 mResolver.update(nameUri, nameValues, null, null); 1274 1275 assertContactFilter(contactId, "galosh"); 1276 1277 Uri filterUri4 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goolish"); 1278 assertEquals(0, getCount(filterUri4, null, null)); 1279 } 1280 1281 public void testQueryContactStrequent() { 1282 ContentValues values1 = new ContentValues(); 1283 createContact(values1, "Noah", "Tever", "18004664411", 1284 "a@acme.com", StatusUpdates.OFFLINE, 0, 0, 0, 1285 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 1286 ContentValues values2 = new ContentValues(); 1287 createContact(values2, "Sam", "Times", "18004664412", 1288 "b@acme.com", StatusUpdates.INVISIBLE, 3, 0, 0, 1289 StatusUpdates.CAPABILITY_HAS_CAMERA); 1290 ContentValues values3 = new ContentValues(); 1291 createContact(values3, "Lotta", "Calling", "18004664413", 1292 "c@acme.com", StatusUpdates.AWAY, 5, 0, 0, 1293 StatusUpdates.CAPABILITY_HAS_VIDEO); 1294 ContentValues values4 = new ContentValues(); 1295 createContact(values4, "Fay", "Veritt", "18004664414", 1296 "d@acme.com", StatusUpdates.AVAILABLE, 0, 1, 0, 1297 StatusUpdates.CAPABILITY_HAS_VIDEO | StatusUpdates.CAPABILITY_HAS_VOICE); 1298 1299 Cursor c = mResolver.query(Contacts.CONTENT_STREQUENT_URI, null, null, null, 1300 Contacts._ID); 1301 assertEquals(3, c.getCount()); 1302 c.moveToFirst(); 1303 assertCursorValues(c, values4); 1304 c.moveToNext(); 1305 assertCursorValues(c, values3); 1306 c.moveToNext(); 1307 assertCursorValues(c, values2); 1308 c.close(); 1309 1310 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_STREQUENT_FILTER_URI, "fay"); 1311 c = mResolver.query(filterUri, null, null, null, Contacts._ID); 1312 assertEquals(1, c.getCount()); 1313 c.moveToFirst(); 1314 assertCursorValues(c, values4); 1315 c.close(); 1316 } 1317 1318 public void testQueryContactGroup() { 1319 long groupId = createGroup(null, "testGroup", "Test Group"); 1320 1321 ContentValues values1 = new ContentValues(); 1322 createContact(values1, "Best", "West", "18004664411", 1323 "west@acme.com", StatusUpdates.OFFLINE, 0, 0, groupId, 1324 StatusUpdates.CAPABILITY_HAS_CAMERA); 1325 1326 ContentValues values2 = new ContentValues(); 1327 createContact(values2, "Rest", "East", "18004664422", 1328 "east@acme.com", StatusUpdates.AVAILABLE, 0, 0, 0, 1329 StatusUpdates.CAPABILITY_HAS_VOICE); 1330 1331 Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 1332 Cursor c = mResolver.query(filterUri1, null, null, null, Contacts._ID); 1333 assertEquals(1, c.getCount()); 1334 c.moveToFirst(); 1335 assertCursorValues(c, values1); 1336 c.close(); 1337 1338 Uri filterUri2 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 1339 c = mResolver.query(filterUri2, null, Contacts.DISPLAY_NAME + "=?", 1340 new String[] { "Best West" }, Contacts._ID); 1341 assertEquals(1, c.getCount()); 1342 c.close(); 1343 1344 Uri filterUri3 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Next Group"); 1345 c = mResolver.query(filterUri3, null, null, null, Contacts._ID); 1346 assertEquals(0, c.getCount()); 1347 c.close(); 1348 } 1349 1350 public void testPhonesWithStatusUpdate() { 1351 1352 ContentValues values = new ContentValues(); 1353 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1354 long rawContactId = ContentUris.parseId(rawContactUri); 1355 insertStructuredName(rawContactId, "John", "Doe"); 1356 Uri photoUri = insertPhoto(rawContactId); 1357 long photoId = ContentUris.parseId(photoUri); 1358 insertPhoneNumber(rawContactId, "18004664411"); 1359 insertPhoneNumber(rawContactId, "18004664412"); 1360 insertEmail(rawContactId, "goog411@acme.com"); 1361 insertEmail(rawContactId, "goog412@acme.com"); 1362 1363 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog411@acme.com", 1364 StatusUpdates.INVISIBLE, "Bad", 1365 StatusUpdates.CAPABILITY_HAS_CAMERA); 1366 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog412@acme.com", 1367 StatusUpdates.AVAILABLE, "Good", 1368 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VOICE); 1369 long contactId = queryContactId(rawContactId); 1370 1371 Uri uri = Data.CONTENT_URI; 1372 1373 Cursor c = mResolver.query(uri, null, RawContacts.CONTACT_ID + "=" + contactId + " AND " 1374 + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null, Phone.NUMBER); 1375 assertEquals(2, c.getCount()); 1376 1377 c.moveToFirst(); 1378 1379 values.clear(); 1380 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 1381 values.put(Contacts.CONTACT_STATUS, "Bad"); 1382 values.put(Contacts.DISPLAY_NAME, "John Doe"); 1383 values.put(Phone.NUMBER, "18004664411"); 1384 values.putNull(Phone.LABEL); 1385 values.put(RawContacts.CONTACT_ID, contactId); 1386 assertCursorValues(c, values); 1387 1388 c.moveToNext(); 1389 1390 values.clear(); 1391 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 1392 values.put(Contacts.CONTACT_STATUS, "Bad"); 1393 values.put(Contacts.DISPLAY_NAME, "John Doe"); 1394 values.put(Phone.NUMBER, "18004664412"); 1395 values.putNull(Phone.LABEL); 1396 values.put(RawContacts.CONTACT_ID, contactId); 1397 assertCursorValues(c, values); 1398 1399 c.close(); 1400 } 1401 1402 public void testGroupQuery() { 1403 Account account1 = new Account("a", "b"); 1404 Account account2 = new Account("c", "d"); 1405 long groupId1 = createGroup(account1, "e", "f"); 1406 long groupId2 = createGroup(account2, "g", "h"); 1407 Uri uri1 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account1); 1408 Uri uri2 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account2); 1409 assertEquals(1, getCount(uri1, null, null)); 1410 assertEquals(1, getCount(uri2, null, null)); 1411 assertStoredValue(uri1, Groups._ID + "=" + groupId1, null, Groups._ID, groupId1) ; 1412 assertStoredValue(uri2, Groups._ID + "=" + groupId2, null, Groups._ID, groupId2) ; 1413 } 1414 1415 public void testGroupInsert() { 1416 ContentValues values = new ContentValues(); 1417 1418 values.put(Groups.ACCOUNT_NAME, "a"); 1419 values.put(Groups.ACCOUNT_TYPE, "b"); 1420 values.put(Groups.SOURCE_ID, "c"); 1421 values.put(Groups.VERSION, 42); 1422 values.put(Groups.GROUP_VISIBLE, 1); 1423 values.put(Groups.TITLE, "d"); 1424 values.put(Groups.TITLE_RES, 1234); 1425 values.put(Groups.NOTES, "e"); 1426 values.put(Groups.RES_PACKAGE, "f"); 1427 values.put(Groups.SYSTEM_ID, "g"); 1428 values.put(Groups.DELETED, 1); 1429 values.put(Groups.SYNC1, "h"); 1430 values.put(Groups.SYNC2, "i"); 1431 values.put(Groups.SYNC3, "j"); 1432 values.put(Groups.SYNC4, "k"); 1433 1434 Uri rowUri = mResolver.insert(Groups.CONTENT_URI, values); 1435 1436 values.put(Groups.DIRTY, 1); 1437 assertStoredValues(rowUri, values); 1438 } 1439 1440 public void testSettingsQuery() { 1441 Account account1 = new Account("a", "b"); 1442 Account account2 = new Account("c", "d"); 1443 createSettings(account1, "0", "0"); 1444 createSettings(account2, "1", "1"); 1445 Uri uri1 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account1); 1446 Uri uri2 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account2); 1447 assertEquals(1, getCount(uri1, null, null)); 1448 assertEquals(1, getCount(uri2, null, null)); 1449 assertStoredValue(uri1, Settings.SHOULD_SYNC, "0") ; 1450 assertStoredValue(uri1, Settings.UNGROUPED_VISIBLE, "0") ; 1451 assertStoredValue(uri2, Settings.SHOULD_SYNC, "1") ; 1452 assertStoredValue(uri2, Settings.UNGROUPED_VISIBLE, "1") ; 1453 } 1454 1455 public void testDisplayNameParsingWhenPartsUnspecified() { 1456 long rawContactId = createRawContact(); 1457 ContentValues values = new ContentValues(); 1458 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 1459 insertStructuredName(rawContactId, values); 1460 1461 assertStructuredName(rawContactId, "Mr", "John", "Kevin", "von Smith", "Jr."); 1462 } 1463 1464 public void testDisplayNameParsingWhenPartsAreNull() { 1465 long rawContactId = createRawContact(); 1466 ContentValues values = new ContentValues(); 1467 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 1468 values.putNull(StructuredName.GIVEN_NAME); 1469 values.putNull(StructuredName.FAMILY_NAME); 1470 insertStructuredName(rawContactId, values); 1471 assertStructuredName(rawContactId, "Mr", "John", "Kevin", "von Smith", "Jr."); 1472 } 1473 1474 public void testDisplayNameParsingWhenPartsSpecified() { 1475 long rawContactId = createRawContact(); 1476 ContentValues values = new ContentValues(); 1477 values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 1478 values.put(StructuredName.FAMILY_NAME, "Johnson"); 1479 insertStructuredName(rawContactId, values); 1480 1481 assertStructuredName(rawContactId, null, null, null, "Johnson", null); 1482 } 1483 1484 public void testContactWithoutPhoneticName() { 1485 final long rawContactId = createRawContact(null); 1486 1487 ContentValues values = new ContentValues(); 1488 values.put(StructuredName.PREFIX, "Mr"); 1489 values.put(StructuredName.GIVEN_NAME, "John"); 1490 values.put(StructuredName.MIDDLE_NAME, "K."); 1491 values.put(StructuredName.FAMILY_NAME, "Doe"); 1492 values.put(StructuredName.SUFFIX, "Jr."); 1493 Uri dataUri = insertStructuredName(rawContactId, values); 1494 1495 values.clear(); 1496 values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1497 values.put(RawContacts.DISPLAY_NAME_PRIMARY, "John K. Doe, Jr."); 1498 values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "Doe, John K., Jr."); 1499 values.putNull(RawContacts.PHONETIC_NAME); 1500 values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1501 values.put(RawContacts.SORT_KEY_PRIMARY, "John K. Doe, Jr."); 1502 values.put(RawContacts.SORT_KEY_ALTERNATIVE, "Doe, John K., Jr."); 1503 1504 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1505 assertStoredValues(rawContactUri, values); 1506 1507 values.clear(); 1508 values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1509 values.put(Contacts.DISPLAY_NAME_PRIMARY, "John K. Doe, Jr."); 1510 values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "Doe, John K., Jr."); 1511 values.putNull(Contacts.PHONETIC_NAME); 1512 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1513 values.put(Contacts.SORT_KEY_PRIMARY, "John K. Doe, Jr."); 1514 values.put(Contacts.SORT_KEY_ALTERNATIVE, "Doe, John K., Jr."); 1515 1516 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 1517 queryContactId(rawContactId)); 1518 assertStoredValues(contactUri, values); 1519 1520 // The same values should be available through a join with Data 1521 assertStoredValues(dataUri, values); 1522 } 1523 1524 public void testContactWithChineseName() { 1525 1526 // Only run this test when Chinese collation is supported 1527 if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) { 1528 return; 1529 } 1530 1531 long rawContactId = createRawContact(null); 1532 1533 ContentValues values = new ContentValues(); 1534 values.put(StructuredName.DISPLAY_NAME, "\u6BB5\u5C0F\u6D9B"); 1535 Uri dataUri = insertStructuredName(rawContactId, values); 1536 1537 values.clear(); 1538 values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1539 values.put(RawContacts.DISPLAY_NAME_PRIMARY, "\u6BB5\u5C0F\u6D9B"); 1540 values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "\u6BB5\u5C0F\u6D9B"); 1541 values.putNull(RawContacts.PHONETIC_NAME); 1542 values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1543 values.put(RawContacts.SORT_KEY_PRIMARY, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 1544 values.put(RawContacts.SORT_KEY_ALTERNATIVE, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 1545 1546 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1547 assertStoredValues(rawContactUri, values); 1548 1549 values.clear(); 1550 values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1551 values.put(Contacts.DISPLAY_NAME_PRIMARY, "\u6BB5\u5C0F\u6D9B"); 1552 values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "\u6BB5\u5C0F\u6D9B"); 1553 values.putNull(Contacts.PHONETIC_NAME); 1554 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1555 values.put(Contacts.SORT_KEY_PRIMARY, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 1556 values.put(Contacts.SORT_KEY_ALTERNATIVE, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 1557 1558 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 1559 queryContactId(rawContactId)); 1560 assertStoredValues(contactUri, values); 1561 1562 // The same values should be available through a join with Data 1563 assertStoredValues(dataUri, values); 1564 } 1565 1566 public void testContactWithJapaneseName() { 1567 long rawContactId = createRawContact(null); 1568 1569 ContentValues values = new ContentValues(); 1570 values.put(StructuredName.GIVEN_NAME, "\u7A7A\u6D77"); 1571 values.put(StructuredName.PHONETIC_GIVEN_NAME, "\u304B\u3044\u304F\u3046"); 1572 Uri dataUri = insertStructuredName(rawContactId, values); 1573 1574 values.clear(); 1575 values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1576 values.put(RawContacts.DISPLAY_NAME_PRIMARY, "\u7A7A\u6D77"); 1577 values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "\u7A7A\u6D77"); 1578 values.put(RawContacts.PHONETIC_NAME, "\u304B\u3044\u304F\u3046"); 1579 values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 1580 values.put(RawContacts.SORT_KEY_PRIMARY, "\u304B\u3044\u304F\u3046"); 1581 values.put(RawContacts.SORT_KEY_ALTERNATIVE, "\u304B\u3044\u304F\u3046"); 1582 1583 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 1584 assertStoredValues(rawContactUri, values); 1585 1586 values.clear(); 1587 values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 1588 values.put(Contacts.DISPLAY_NAME_PRIMARY, "\u7A7A\u6D77"); 1589 values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "\u7A7A\u6D77"); 1590 values.put(Contacts.PHONETIC_NAME, "\u304B\u3044\u304F\u3046"); 1591 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 1592 values.put(Contacts.SORT_KEY_PRIMARY, "\u304B\u3044\u304F\u3046"); 1593 values.put(Contacts.SORT_KEY_ALTERNATIVE, "\u304B\u3044\u304F\u3046"); 1594 1595 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 1596 queryContactId(rawContactId)); 1597 assertStoredValues(contactUri, values); 1598 1599 // The same values should be available through a join with Data 1600 assertStoredValues(dataUri, values); 1601 } 1602 1603 public void testDisplayNameUpdate() { 1604 long rawContactId1 = createRawContact(); 1605 insertEmail(rawContactId1, "potato@acme.com", true); 1606 1607 long rawContactId2 = createRawContact(); 1608 insertPhoneNumber(rawContactId2, "123456789", true); 1609 1610 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1611 rawContactId1, rawContactId2); 1612 1613 assertAggregated(rawContactId1, rawContactId2, "123456789"); 1614 1615 insertStructuredName(rawContactId2, "Potato", "Head"); 1616 1617 assertAggregated(rawContactId1, rawContactId2, "Potato Head"); 1618 assertNetworkNotified(true); 1619 } 1620 1621 public void testDisplayNameFromData() { 1622 long rawContactId = createRawContact(); 1623 long contactId = queryContactId(rawContactId); 1624 ContentValues values = new ContentValues(); 1625 1626 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1627 1628 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 1629 insertEmail(rawContactId, "mike@monstersinc.com"); 1630 assertStoredValue(uri, Contacts.DISPLAY_NAME, "mike@monstersinc.com"); 1631 1632 insertEmail(rawContactId, "james@monstersinc.com", true); 1633 assertStoredValue(uri, Contacts.DISPLAY_NAME, "james@monstersinc.com"); 1634 1635 insertPhoneNumber(rawContactId, "1-800-466-4411"); 1636 assertStoredValue(uri, Contacts.DISPLAY_NAME, "1-800-466-4411"); 1637 1638 // If there are title and company, the company is display name. 1639 values.clear(); 1640 values.put(Organization.COMPANY, "Monsters Inc"); 1641 Uri organizationUri = insertOrganization(rawContactId, values); 1642 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Monsters Inc"); 1643 1644 // If there is nickname, that is display name. 1645 insertNickname(rawContactId, "Sully"); 1646 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Sully"); 1647 1648 // If there is structured name, that is display name. 1649 values.clear(); 1650 values.put(StructuredName.GIVEN_NAME, "James"); 1651 values.put(StructuredName.MIDDLE_NAME, "P."); 1652 values.put(StructuredName.FAMILY_NAME, "Sullivan"); 1653 insertStructuredName(rawContactId, values); 1654 assertStoredValue(uri, Contacts.DISPLAY_NAME, "James P. Sullivan"); 1655 } 1656 1657 public void testDisplayNameFromOrganizationWithoutPhoneticName() { 1658 long rawContactId = createRawContact(); 1659 long contactId = queryContactId(rawContactId); 1660 ContentValues values = new ContentValues(); 1661 1662 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1663 1664 // If there is title without company, the title is display name. 1665 values.clear(); 1666 values.put(Organization.TITLE, "Protagonist"); 1667 Uri organizationUri = insertOrganization(rawContactId, values); 1668 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Protagonist"); 1669 1670 // If there are title and company, the company is display name. 1671 values.clear(); 1672 values.put(Organization.COMPANY, "Monsters Inc"); 1673 mResolver.update(organizationUri, values, null, null); 1674 1675 values.clear(); 1676 values.put(Contacts.DISPLAY_NAME, "Monsters Inc"); 1677 values.putNull(Contacts.PHONETIC_NAME); 1678 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1679 values.put(Contacts.SORT_KEY_PRIMARY, "Monsters Inc"); 1680 values.put(Contacts.SORT_KEY_ALTERNATIVE, "Monsters Inc"); 1681 assertStoredValues(uri, values); 1682 } 1683 1684 public void testDisplayNameFromOrganizationWithJapanesePhoneticName() { 1685 long rawContactId = createRawContact(); 1686 long contactId = queryContactId(rawContactId); 1687 ContentValues values = new ContentValues(); 1688 1689 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1690 1691 // If there is title without company, the title is display name. 1692 values.clear(); 1693 values.put(Organization.COMPANY, "DoCoMo"); 1694 values.put(Organization.PHONETIC_NAME, "\u30C9\u30B3\u30E2"); 1695 Uri organizationUri = insertOrganization(rawContactId, values); 1696 1697 values.clear(); 1698 values.put(Contacts.DISPLAY_NAME, "DoCoMo"); 1699 values.put(Contacts.PHONETIC_NAME, "\u30C9\u30B3\u30E2"); 1700 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 1701 values.put(Contacts.SORT_KEY_PRIMARY, "\u30C9\u30B3\u30E2"); 1702 values.put(Contacts.SORT_KEY_ALTERNATIVE, "\u30C9\u30B3\u30E2"); 1703 assertStoredValues(uri, values); 1704 } 1705 1706 public void testDisplayNameFromOrganizationWithChineseName() { 1707 boolean hasChineseCollator = false; 1708 final Locale locale[] = Collator.getAvailableLocales(); 1709 for (int i = 0; i < locale.length; i++) { 1710 if (locale[i].equals(Locale.CHINA)) { 1711 hasChineseCollator = true; 1712 break; 1713 } 1714 } 1715 1716 if (!hasChineseCollator) { 1717 return; 1718 } 1719 1720 long rawContactId = createRawContact(); 1721 long contactId = queryContactId(rawContactId); 1722 ContentValues values = new ContentValues(); 1723 1724 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1725 1726 // If there is title without company, the title is display name. 1727 values.clear(); 1728 values.put(Organization.COMPANY, "\u4E2D\u56FD\u7535\u4FE1"); 1729 Uri organizationUri = insertOrganization(rawContactId, values); 1730 1731 values.clear(); 1732 values.put(Contacts.DISPLAY_NAME, "\u4E2D\u56FD\u7535\u4FE1"); 1733 values.putNull(Contacts.PHONETIC_NAME); 1734 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 1735 values.put(Contacts.SORT_KEY_PRIMARY, "ZHONG \u4E2D GUO \u56FD DIAN \u7535 XIN \u4FE1"); 1736 values.put(Contacts.SORT_KEY_ALTERNATIVE, "ZHONG \u4E2D GUO \u56FD DIAN \u7535 XIN \u4FE1"); 1737 assertStoredValues(uri, values); 1738 } 1739 1740 public void testLookupByOrganization() { 1741 long rawContactId = createRawContact(); 1742 long contactId = queryContactId(rawContactId); 1743 ContentValues values = new ContentValues(); 1744 1745 values.clear(); 1746 values.put(Organization.COMPANY, "acmecorp"); 1747 values.put(Organization.TITLE, "president"); 1748 Uri organizationUri = insertOrganization(rawContactId, values); 1749 1750 assertContactFilter(contactId, "acmecorp"); 1751 assertContactFilter(contactId, "president"); 1752 1753 values.clear(); 1754 values.put(Organization.DEPARTMENT, "software"); 1755 mResolver.update(organizationUri, values, null, null); 1756 1757 assertContactFilter(contactId, "acmecorp"); 1758 assertContactFilter(contactId, "president"); 1759 1760 values.clear(); 1761 values.put(Organization.COMPANY, "incredibles"); 1762 mResolver.update(organizationUri, values, null, null); 1763 1764 assertContactFilter(contactId, "incredibles"); 1765 assertContactFilter(contactId, "president"); 1766 1767 values.clear(); 1768 values.put(Organization.TITLE, "director"); 1769 mResolver.update(organizationUri, values, null, null); 1770 1771 assertContactFilter(contactId, "incredibles"); 1772 assertContactFilter(contactId, "director"); 1773 1774 values.clear(); 1775 values.put(Organization.COMPANY, "monsters"); 1776 values.put(Organization.TITLE, "scarer"); 1777 mResolver.update(organizationUri, values, null, null); 1778 1779 assertContactFilter(contactId, "monsters"); 1780 assertContactFilter(contactId, "scarer"); 1781 } 1782 1783 private void assertContactFilter(long contactId, String filter) { 1784 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(filter)); 1785 assertStoredValue(filterUri, Contacts._ID, contactId); 1786 } 1787 1788 public void testSearchSnippetOrganization() throws Exception { 1789 long rawContactId = createRawContactWithName(); 1790 long contactId = queryContactId(rawContactId); 1791 1792 // Some random data element 1793 insertEmail(rawContactId, "inc@corp.com"); 1794 1795 ContentValues values = new ContentValues(); 1796 values.clear(); 1797 values.put(Organization.COMPANY, "acmecorp"); 1798 values.put(Organization.TITLE, "engineer"); 1799 Uri organizationUri = insertOrganization(rawContactId, values); 1800 1801 // Add another matching organization 1802 values.put(Organization.COMPANY, "acmeinc"); 1803 insertOrganization(rawContactId, values); 1804 1805 // Add another non-matching organization 1806 values.put(Organization.COMPANY, "corpacme"); 1807 insertOrganization(rawContactId, values); 1808 1809 // And another data element 1810 insertEmail(rawContactId, "emca@corp.com", true, Email.TYPE_CUSTOM, "Custom"); 1811 1812 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("acme")); 1813 1814 values.clear(); 1815 values.put(Contacts._ID, contactId); 1816 values.put(SearchSnippetColumns.SNIPPET_DATA_ID, ContentUris.parseId(organizationUri)); 1817 values.put(SearchSnippetColumns.SNIPPET_DATA1, "acmecorp"); 1818 values.put(SearchSnippetColumns.SNIPPET_DATA4, "engineer"); 1819 values.put(SearchSnippetColumns.SNIPPET_MIMETYPE, Organization.CONTENT_ITEM_TYPE); 1820 assertStoredValues(filterUri, values); 1821 } 1822 1823 public void testSearchSnippetEmail() throws Exception { 1824 long rawContactId = createRawContact(); 1825 long contactId = queryContactId(rawContactId); 1826 ContentValues values = new ContentValues(); 1827 1828 Uri dataUri = insertEmail(rawContactId, "acme@corp.com", true, Email.TYPE_CUSTOM, "Custom"); 1829 1830 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("acme")); 1831 1832 values.clear(); 1833 values.put(Contacts._ID, contactId); 1834 values.put(SearchSnippetColumns.SNIPPET_DATA1, "acme@corp.com"); 1835 values.put(SearchSnippetColumns.SNIPPET_DATA_ID, ContentUris.parseId(dataUri)); 1836 values.put(SearchSnippetColumns.SNIPPET_MIMETYPE, Email.CONTENT_ITEM_TYPE); 1837 values.put(SearchSnippetColumns.SNIPPET_DATA2, Email.TYPE_CUSTOM); 1838 values.put(SearchSnippetColumns.SNIPPET_DATA3, "Custom"); 1839 assertStoredValues(filterUri, values); 1840 } 1841 1842 public void testSearchSnippetNickname() throws Exception { 1843 long rawContactId = createRawContactWithName(); 1844 long contactId = queryContactId(rawContactId); 1845 ContentValues values = new ContentValues(); 1846 1847 Uri dataUri = insertNickname(rawContactId, "Incredible"); 1848 1849 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("inc")); 1850 1851 values.clear(); 1852 values.put(Contacts._ID, contactId); 1853 values.put(SearchSnippetColumns.SNIPPET_DATA1, "Incredible"); 1854 values.put(SearchSnippetColumns.SNIPPET_DATA_ID, ContentUris.parseId(dataUri)); 1855 values.put(SearchSnippetColumns.SNIPPET_MIMETYPE, Nickname.CONTENT_ITEM_TYPE); 1856 assertStoredValues(filterUri, values); 1857 } 1858 1859 public void testDisplayNameUpdateFromStructuredNameUpdate() { 1860 long rawContactId = createRawContact(); 1861 Uri nameUri = insertStructuredName(rawContactId, "Slinky", "Dog"); 1862 1863 long contactId = queryContactId(rawContactId); 1864 1865 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1866 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky Dog"); 1867 1868 ContentValues values = new ContentValues(); 1869 values.putNull(StructuredName.FAMILY_NAME); 1870 1871 mResolver.update(nameUri, values, null, null); 1872 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky"); 1873 1874 values.putNull(StructuredName.GIVEN_NAME); 1875 1876 mResolver.update(nameUri, values, null, null); 1877 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 1878 1879 values.put(StructuredName.FAMILY_NAME, "Dog"); 1880 mResolver.update(nameUri, values, null, null); 1881 1882 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Dog"); 1883 } 1884 1885 public void testInsertDataWithContentProviderOperations() throws Exception { 1886 ContentProviderOperation cpo1 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) 1887 .withValues(new ContentValues()) 1888 .build(); 1889 ContentProviderOperation cpo2 = ContentProviderOperation.newInsert(Data.CONTENT_URI) 1890 .withValueBackReference(Data.RAW_CONTACT_ID, 0) 1891 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 1892 .withValue(StructuredName.GIVEN_NAME, "John") 1893 .withValue(StructuredName.FAMILY_NAME, "Doe") 1894 .build(); 1895 ContentProviderResult[] results = 1896 mResolver.applyBatch(ContactsContract.AUTHORITY, Lists.newArrayList(cpo1, cpo2)); 1897 long contactId = queryContactId(ContentUris.parseId(results[0].uri)); 1898 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1899 assertStoredValue(uri, Contacts.DISPLAY_NAME, "John Doe"); 1900 } 1901 1902 public void testSendToVoicemailDefault() { 1903 long rawContactId = createRawContactWithName(); 1904 long contactId = queryContactId(rawContactId); 1905 1906 Cursor c = queryContact(contactId); 1907 assertTrue(c.moveToNext()); 1908 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 1909 assertEquals(0, sendToVoicemail); 1910 c.close(); 1911 } 1912 1913 public void testSetSendToVoicemailAndRingtone() { 1914 long rawContactId = createRawContactWithName(); 1915 long contactId = queryContactId(rawContactId); 1916 1917 updateSendToVoicemailAndRingtone(contactId, true, "foo"); 1918 assertSendToVoicemailAndRingtone(contactId, true, "foo"); 1919 assertNetworkNotified(false); 1920 1921 updateSendToVoicemailAndRingtoneWithSelection(contactId, false, "bar"); 1922 assertSendToVoicemailAndRingtone(contactId, false, "bar"); 1923 assertNetworkNotified(false); 1924 } 1925 1926 public void testSendToVoicemailAndRingtoneAfterAggregation() { 1927 long rawContactId1 = createRawContactWithName("a", "b"); 1928 long contactId1 = queryContactId(rawContactId1); 1929 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 1930 1931 long rawContactId2 = createRawContactWithName("c", "d"); 1932 long contactId2 = queryContactId(rawContactId2); 1933 updateSendToVoicemailAndRingtone(contactId2, true, "bar"); 1934 1935 // Aggregate them 1936 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1937 rawContactId1, rawContactId2); 1938 1939 // Both contacts had "send to VM", the contact now has the same value 1940 assertSendToVoicemailAndRingtone(contactId1, true, "foo,bar"); // Either foo or bar 1941 } 1942 1943 public void testDoNotSendToVoicemailAfterAggregation() { 1944 long rawContactId1 = createRawContactWithName("e", "f"); 1945 long contactId1 = queryContactId(rawContactId1); 1946 updateSendToVoicemailAndRingtone(contactId1, true, null); 1947 1948 long rawContactId2 = createRawContactWithName("g", "h"); 1949 long contactId2 = queryContactId(rawContactId2); 1950 updateSendToVoicemailAndRingtone(contactId2, false, null); 1951 1952 // Aggregate them 1953 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1954 rawContactId1, rawContactId2); 1955 1956 // Since one of the contacts had "don't send to VM" that setting wins for the aggregate 1957 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), false, null); 1958 } 1959 1960 public void testSetSendToVoicemailAndRingtonePreservedAfterJoinAndSplit() { 1961 long rawContactId1 = createRawContactWithName("i", "j"); 1962 long contactId1 = queryContactId(rawContactId1); 1963 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 1964 1965 long rawContactId2 = createRawContactWithName("k", "l"); 1966 long contactId2 = queryContactId(rawContactId2); 1967 updateSendToVoicemailAndRingtone(contactId2, false, "bar"); 1968 1969 // Aggregate them 1970 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 1971 rawContactId1, rawContactId2); 1972 1973 // Split them 1974 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 1975 rawContactId1, rawContactId2); 1976 1977 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), true, "foo"); 1978 assertSendToVoicemailAndRingtone(queryContactId(rawContactId2), false, "bar"); 1979 } 1980 1981 public void testStatusUpdateInsert() { 1982 long rawContactId = createRawContact(); 1983 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 1984 long dataId = ContentUris.parseId(imUri); 1985 1986 ContentValues values = new ContentValues(); 1987 values.put(StatusUpdates.DATA_ID, dataId); 1988 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 1989 values.putNull(StatusUpdates.CUSTOM_PROTOCOL); 1990 values.put(StatusUpdates.IM_HANDLE, "aim"); 1991 values.put(StatusUpdates.PRESENCE, StatusUpdates.INVISIBLE); 1992 values.put(StatusUpdates.STATUS, "Hiding"); 1993 values.put(StatusUpdates.STATUS_TIMESTAMP, 100); 1994 values.put(StatusUpdates.STATUS_RES_PACKAGE, "a.b.c"); 1995 values.put(StatusUpdates.STATUS_ICON, 1234); 1996 values.put(StatusUpdates.STATUS_LABEL, 2345); 1997 1998 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 1999 2000 assertStoredValues(resultUri, values); 2001 2002 long contactId = queryContactId(rawContactId); 2003 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2004 2005 values.clear(); 2006 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 2007 values.put(Contacts.CONTACT_STATUS, "Hiding"); 2008 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 2009 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "a.b.c"); 2010 values.put(Contacts.CONTACT_STATUS_ICON, 1234); 2011 values.put(Contacts.CONTACT_STATUS_LABEL, 2345); 2012 2013 assertStoredValues(contactUri, values); 2014 2015 values.clear(); 2016 values.put(StatusUpdates.DATA_ID, dataId); 2017 values.put(StatusUpdates.STATUS, "Cloaked"); 2018 values.put(StatusUpdates.STATUS_TIMESTAMP, 200); 2019 values.put(StatusUpdates.STATUS_RES_PACKAGE, "d.e.f"); 2020 values.put(StatusUpdates.STATUS_ICON, 4321); 2021 values.put(StatusUpdates.STATUS_LABEL, 5432); 2022 mResolver.insert(StatusUpdates.CONTENT_URI, values); 2023 2024 values.clear(); 2025 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 2026 values.put(Contacts.CONTACT_STATUS, "Cloaked"); 2027 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 200); 2028 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "d.e.f"); 2029 values.put(Contacts.CONTACT_STATUS_ICON, 4321); 2030 values.put(Contacts.CONTACT_STATUS_LABEL, 5432); 2031 assertStoredValues(contactUri, values); 2032 } 2033 2034 public void testStatusUpdateInferAttribution() { 2035 long rawContactId = createRawContact(); 2036 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2037 long dataId = ContentUris.parseId(imUri); 2038 2039 ContentValues values = new ContentValues(); 2040 values.put(StatusUpdates.DATA_ID, dataId); 2041 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 2042 values.put(StatusUpdates.IM_HANDLE, "aim"); 2043 values.put(StatusUpdates.STATUS, "Hiding"); 2044 2045 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 2046 2047 values.clear(); 2048 values.put(StatusUpdates.DATA_ID, dataId); 2049 values.put(StatusUpdates.STATUS_LABEL, com.android.internal.R.string.imProtocolAim); 2050 values.put(StatusUpdates.STATUS, "Hiding"); 2051 2052 assertStoredValues(resultUri, values); 2053 } 2054 2055 public void testStatusUpdateMatchingImOrEmail() { 2056 long rawContactId = createRawContact(); 2057 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2058 insertImHandle(rawContactId, Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im"); 2059 insertEmail(rawContactId, "m@acme.com"); 2060 2061 // Match on IM (standard) 2062 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2063 StatusUpdates.CAPABILITY_HAS_CAMERA); 2064 2065 // Match on IM (custom) 2066 insertStatusUpdate(Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im", StatusUpdates.IDLE, "Idle", 2067 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 2068 2069 // Match on Email 2070 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "m@acme.com", StatusUpdates.AWAY, "Away", 2071 StatusUpdates.CAPABILITY_HAS_VOICE); 2072 2073 // No match 2074 insertStatusUpdate(Im.PROTOCOL_ICQ, null, "12345", StatusUpdates.DO_NOT_DISTURB, "Go away", 2075 StatusUpdates.CAPABILITY_HAS_CAMERA); 2076 2077 Cursor c = mResolver.query(StatusUpdates.CONTENT_URI, new String[] { 2078 StatusUpdates.DATA_ID, StatusUpdates.PROTOCOL, StatusUpdates.CUSTOM_PROTOCOL, 2079 StatusUpdates.PRESENCE, StatusUpdates.STATUS}, 2080 PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null, StatusUpdates.DATA_ID); 2081 assertTrue(c.moveToNext()); 2082 assertStatusUpdate(c, Im.PROTOCOL_AIM, null, StatusUpdates.AVAILABLE, "Available"); 2083 assertTrue(c.moveToNext()); 2084 assertStatusUpdate(c, Im.PROTOCOL_CUSTOM, "my_im_proto", StatusUpdates.IDLE, "Idle"); 2085 assertTrue(c.moveToNext()); 2086 assertStatusUpdate(c, Im.PROTOCOL_GOOGLE_TALK, null, StatusUpdates.AWAY, "Away"); 2087 assertFalse(c.moveToNext()); 2088 c.close(); 2089 2090 long contactId = queryContactId(rawContactId); 2091 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2092 2093 ContentValues values = new ContentValues(); 2094 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2095 values.put(Contacts.CONTACT_STATUS, "Available"); 2096 assertStoredValuesWithProjection(contactUri, values); 2097 } 2098 2099 public void testStatusUpdateUpdateAndDelete() { 2100 long rawContactId = createRawContact(); 2101 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2102 2103 long contactId = queryContactId(rawContactId); 2104 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2105 2106 ContentValues values = new ContentValues(); 2107 values.putNull(Contacts.CONTACT_PRESENCE); 2108 values.putNull(Contacts.CONTACT_STATUS); 2109 assertStoredValuesWithProjection(contactUri, values); 2110 2111 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AWAY, "BUSY", 2112 StatusUpdates.CAPABILITY_HAS_CAMERA); 2113 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.DO_NOT_DISTURB, "GO AWAY", 2114 StatusUpdates.CAPABILITY_HAS_CAMERA); 2115 Uri statusUri = 2116 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2117 StatusUpdates.CAPABILITY_HAS_CAMERA); 2118 long statusId = ContentUris.parseId(statusUri); 2119 2120 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2121 values.put(Contacts.CONTACT_STATUS, "Available"); 2122 assertStoredValuesWithProjection(contactUri, values); 2123 2124 // update status_updates table to set new values for 2125 // status_updates.status 2126 // status_updates.status_ts 2127 // presence 2128 long updatedTs = 200; 2129 String testUpdate = "test_update"; 2130 String selection = StatusUpdates.DATA_ID + "=" + statusId; 2131 values.clear(); 2132 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2133 values.put(StatusUpdates.STATUS, testUpdate); 2134 values.put(StatusUpdates.PRESENCE, "presence_test"); 2135 mResolver.update(StatusUpdates.CONTENT_URI, values, 2136 StatusUpdates.DATA_ID + "=" + statusId, null); 2137 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2138 2139 // update status_updates table to set new values for columns in status_updates table ONLY 2140 // i.e., no rows in presence table are to be updated. 2141 updatedTs = 300; 2142 testUpdate = "test_update_new"; 2143 selection = StatusUpdates.DATA_ID + "=" + statusId; 2144 values.clear(); 2145 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2146 values.put(StatusUpdates.STATUS, testUpdate); 2147 mResolver.update(StatusUpdates.CONTENT_URI, values, 2148 StatusUpdates.DATA_ID + "=" + statusId, null); 2149 // make sure the presence column value is still the old value 2150 values.put(StatusUpdates.PRESENCE, "presence_test"); 2151 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2152 2153 // update status_updates table to set new values for columns in presence table ONLY 2154 // i.e., no rows in status_updates table are to be updated. 2155 selection = StatusUpdates.DATA_ID + "=" + statusId; 2156 values.clear(); 2157 values.put(StatusUpdates.PRESENCE, "presence_test_new"); 2158 mResolver.update(StatusUpdates.CONTENT_URI, values, 2159 StatusUpdates.DATA_ID + "=" + statusId, null); 2160 // make sure the status_updates table is not updated 2161 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2162 values.put(StatusUpdates.STATUS, testUpdate); 2163 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2164 2165 // effect "delete status_updates" operation and expect the following 2166 // data deleted from status_updates table 2167 // presence set to null 2168 mResolver.delete(StatusUpdates.CONTENT_URI, StatusUpdates.DATA_ID + "=" + statusId, null); 2169 values.clear(); 2170 values.putNull(Contacts.CONTACT_PRESENCE); 2171 assertStoredValuesWithProjection(contactUri, values); 2172 } 2173 2174 public void testStatusUpdateUpdateToNull() { 2175 long rawContactId = createRawContact(); 2176 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2177 2178 long contactId = queryContactId(rawContactId); 2179 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2180 2181 ContentValues values = new ContentValues(); 2182 Uri statusUri = 2183 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2184 StatusUpdates.CAPABILITY_HAS_CAMERA); 2185 long statusId = ContentUris.parseId(statusUri); 2186 2187 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2188 values.put(Contacts.CONTACT_STATUS, "Available"); 2189 assertStoredValuesWithProjection(contactUri, values); 2190 2191 values.clear(); 2192 values.putNull(StatusUpdates.PRESENCE); 2193 mResolver.update(StatusUpdates.CONTENT_URI, values, 2194 StatusUpdates.DATA_ID + "=" + statusId, null); 2195 2196 values.clear(); 2197 values.putNull(Contacts.CONTACT_PRESENCE); 2198 values.put(Contacts.CONTACT_STATUS, "Available"); 2199 assertStoredValuesWithProjection(contactUri, values); 2200 } 2201 2202 public void testStatusUpdateWithTimestamp() { 2203 long rawContactId = createRawContact(); 2204 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2205 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 2206 2207 long contactId = queryContactId(rawContactId); 2208 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2209 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Offline", 80, 2210 StatusUpdates.CAPABILITY_HAS_CAMERA); 2211 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Available", 100, 2212 StatusUpdates.CAPABILITY_HAS_CAMERA); 2213 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", 0, "Busy", 90, 2214 StatusUpdates.CAPABILITY_HAS_CAMERA); 2215 2216 // Should return the latest status 2217 ContentValues values = new ContentValues(); 2218 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 2219 values.put(Contacts.CONTACT_STATUS, "Available"); 2220 assertStoredValuesWithProjection(contactUri, values); 2221 } 2222 2223 private void assertStatusUpdate(Cursor c, int protocol, String customProtocol, int presence, 2224 String status) { 2225 ContentValues values = new ContentValues(); 2226 values.put(StatusUpdates.PROTOCOL, protocol); 2227 values.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 2228 values.put(StatusUpdates.PRESENCE, presence); 2229 values.put(StatusUpdates.STATUS, status); 2230 assertCursorValues(c, values); 2231 } 2232 2233 public void testSingleStatusUpdateRowPerContact() { 2234 int protocol1 = Im.PROTOCOL_GOOGLE_TALK; 2235 String handle1 = "test@gmail.com"; 2236 2237 long rawContactId1 = createRawContact(); 2238 insertImHandle(rawContactId1, protocol1, null, handle1); 2239 2240 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AVAILABLE, "Green", 2241 StatusUpdates.CAPABILITY_HAS_CAMERA); 2242 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AWAY, "Yellow", 2243 StatusUpdates.CAPABILITY_HAS_CAMERA); 2244 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.INVISIBLE, "Red", 2245 StatusUpdates.CAPABILITY_HAS_CAMERA); 2246 2247 Cursor c = queryContact(queryContactId(rawContactId1), 2248 new String[] {Contacts.CONTACT_PRESENCE, Contacts.CONTACT_STATUS}); 2249 assertEquals(1, c.getCount()); 2250 2251 c.moveToFirst(); 2252 assertEquals(StatusUpdates.INVISIBLE, c.getInt(0)); 2253 assertEquals("Red", c.getString(1)); 2254 c.close(); 2255 } 2256 2257 private void updateSendToVoicemailAndRingtone(long contactId, boolean sendToVoicemail, 2258 String ringtone) { 2259 ContentValues values = new ContentValues(); 2260 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 2261 if (ringtone != null) { 2262 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 2263 } 2264 2265 final Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2266 int count = mResolver.update(uri, values, null, null); 2267 assertEquals(1, count); 2268 } 2269 2270 private void updateSendToVoicemailAndRingtoneWithSelection(long contactId, 2271 boolean sendToVoicemail, String ringtone) { 2272 ContentValues values = new ContentValues(); 2273 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 2274 if (ringtone != null) { 2275 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 2276 } 2277 2278 int count = mResolver.update(Contacts.CONTENT_URI, values, Contacts._ID + "=" + contactId, 2279 null); 2280 assertEquals(1, count); 2281 } 2282 2283 private void assertSendToVoicemailAndRingtone(long contactId, boolean expectedSendToVoicemail, 2284 String expectedRingtone) { 2285 Cursor c = queryContact(contactId); 2286 assertTrue(c.moveToNext()); 2287 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 2288 assertEquals(expectedSendToVoicemail ? 1 : 0, sendToVoicemail); 2289 String ringtone = c.getString(c.getColumnIndex(Contacts.CUSTOM_RINGTONE)); 2290 if (expectedRingtone == null) { 2291 assertNull(ringtone); 2292 } else { 2293 assertTrue(ArrayUtils.contains(expectedRingtone.split(","), ringtone)); 2294 } 2295 c.close(); 2296 } 2297 2298 public void testGroupCreationAfterMembershipInsert() { 2299 long rawContactId1 = createRawContact(mAccount); 2300 Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 2301 2302 long groupId = assertSingleGroup(NO_LONG, mAccount, "gsid1", null); 2303 assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 2304 rawContactId1, groupId, "gsid1"); 2305 } 2306 2307 public void testGroupReuseAfterMembershipInsert() { 2308 long rawContactId1 = createRawContact(mAccount); 2309 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 2310 Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 2311 2312 assertSingleGroup(groupId1, mAccount, "gsid1", "title1"); 2313 assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 2314 rawContactId1, groupId1, "gsid1"); 2315 } 2316 2317 public void testGroupInsertFailureOnGroupIdConflict() { 2318 long rawContactId1 = createRawContact(mAccount); 2319 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 2320 2321 ContentValues values = new ContentValues(); 2322 values.put(GroupMembership.RAW_CONTACT_ID, rawContactId1); 2323 values.put(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 2324 values.put(GroupMembership.GROUP_SOURCE_ID, "gsid1"); 2325 values.put(GroupMembership.GROUP_ROW_ID, groupId1); 2326 try { 2327 mResolver.insert(Data.CONTENT_URI, values); 2328 fail("the insert was expected to fail, but it succeeded"); 2329 } catch (IllegalArgumentException e) { 2330 // this was expected 2331 } 2332 } 2333 2334 public void testContactVisibilityUpdateOnMembershipChange() { 2335 long rawContactId = createRawContact(mAccount); 2336 assertVisibility(rawContactId, "0"); 2337 2338 long visibleGroupId = createGroup(mAccount, "123", "Visible", 1); 2339 long invisibleGroupId = createGroup(mAccount, "567", "Invisible", 0); 2340 2341 Uri membership1 = insertGroupMembership(rawContactId, visibleGroupId); 2342 assertVisibility(rawContactId, "1"); 2343 2344 Uri membership2 = insertGroupMembership(rawContactId, invisibleGroupId); 2345 assertVisibility(rawContactId, "1"); 2346 2347 mResolver.delete(membership1, null, null); 2348 assertVisibility(rawContactId, "0"); 2349 2350 ContentValues values = new ContentValues(); 2351 values.put(GroupMembership.GROUP_ROW_ID, visibleGroupId); 2352 2353 mResolver.update(membership2, values, null, null); 2354 assertVisibility(rawContactId, "1"); 2355 } 2356 2357 private void assertVisibility(long rawContactId, String expectedValue) { 2358 assertStoredValue(Contacts.CONTENT_URI, Contacts._ID + "=" + queryContactId(rawContactId), 2359 null, Contacts.IN_VISIBLE_GROUP, expectedValue); 2360 } 2361 2362 public void testContentEntityIterator() { 2363 // create multiple contacts and check that the selected ones are returned 2364 long id; 2365 2366 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 2367 long groupId2 = createGroup(mAccount, "gsid2", "title2"); 2368 2369 id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c0"); 2370 insertGroupMembership(id, "gsid1"); 2371 insertEmail(id, "c0@email.com"); 2372 insertPhoneNumber(id, "5551212c0"); 2373 2374 long c1 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c1"); 2375 Uri id_1_0 = insertGroupMembership(id, "gsid1"); 2376 Uri id_1_1 = insertGroupMembership(id, "gsid2"); 2377 Uri id_1_2 = insertEmail(id, "c1@email.com"); 2378 Uri id_1_3 = insertPhoneNumber(id, "5551212c1"); 2379 2380 long c2 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c2"); 2381 Uri id_2_0 = insertGroupMembership(id, "gsid1"); 2382 Uri id_2_1 = insertEmail(id, "c2@email.com"); 2383 Uri id_2_2 = insertPhoneNumber(id, "5551212c2"); 2384 2385 long c3 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c3"); 2386 Uri id_3_0 = insertGroupMembership(id, groupId2); 2387 Uri id_3_1 = insertEmail(id, "c3@email.com"); 2388 Uri id_3_2 = insertPhoneNumber(id, "5551212c3"); 2389 2390 EntityIterator iterator = RawContacts.newEntityIterator(mResolver.query( 2391 maybeAddAccountQueryParameters(RawContactsEntity.CONTENT_URI, mAccount), null, 2392 RawContacts.SOURCE_ID + " in ('c1', 'c2', 'c3')", null, null)); 2393 Entity entity; 2394 ContentValues[] subValues; 2395 entity = iterator.next(); 2396 assertEquals(c1, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 2397 subValues = asSortedContentValuesArray(entity.getSubValues()); 2398 assertEquals(4, subValues.length); 2399 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 2400 Data._ID, id_1_0, 2401 GroupMembership.GROUP_ROW_ID, groupId1, 2402 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 2403 assertDataRow(subValues[1], GroupMembership.CONTENT_ITEM_TYPE, 2404 Data._ID, id_1_1, 2405 GroupMembership.GROUP_ROW_ID, groupId2, 2406 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 2407 assertDataRow(subValues[2], Email.CONTENT_ITEM_TYPE, 2408 Data._ID, id_1_2, 2409 Email.DATA, "c1@email.com"); 2410 assertDataRow(subValues[3], Phone.CONTENT_ITEM_TYPE, 2411 Data._ID, id_1_3, 2412 Email.DATA, "5551212c1"); 2413 2414 entity = iterator.next(); 2415 assertEquals(c2, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 2416 subValues = asSortedContentValuesArray(entity.getSubValues()); 2417 assertEquals(3, subValues.length); 2418 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 2419 Data._ID, id_2_0, 2420 GroupMembership.GROUP_ROW_ID, groupId1, 2421 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 2422 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 2423 Data._ID, id_2_1, 2424 Email.DATA, "c2@email.com"); 2425 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 2426 Data._ID, id_2_2, 2427 Email.DATA, "5551212c2"); 2428 2429 entity = iterator.next(); 2430 assertEquals(c3, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 2431 subValues = asSortedContentValuesArray(entity.getSubValues()); 2432 assertEquals(3, subValues.length); 2433 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 2434 Data._ID, id_3_0, 2435 GroupMembership.GROUP_ROW_ID, groupId2, 2436 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 2437 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 2438 Data._ID, id_3_1, 2439 Email.DATA, "c3@email.com"); 2440 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 2441 Data._ID, id_3_2, 2442 Email.DATA, "5551212c3"); 2443 2444 assertFalse(iterator.hasNext()); 2445 iterator.close(); 2446 } 2447 2448 public void testDataCreateUpdateDeleteByMimeType() throws Exception { 2449 long rawContactId = createRawContact(); 2450 2451 ContentValues values = new ContentValues(); 2452 values.put(Data.RAW_CONTACT_ID, rawContactId); 2453 values.put(Data.MIMETYPE, "testmimetype"); 2454 values.put(Data.RES_PACKAGE, "oldpackage"); 2455 values.put(Data.IS_PRIMARY, 1); 2456 values.put(Data.IS_SUPER_PRIMARY, 1); 2457 values.put(Data.DATA1, "old1"); 2458 values.put(Data.DATA2, "old2"); 2459 values.put(Data.DATA3, "old3"); 2460 values.put(Data.DATA4, "old4"); 2461 values.put(Data.DATA5, "old5"); 2462 values.put(Data.DATA6, "old6"); 2463 values.put(Data.DATA7, "old7"); 2464 values.put(Data.DATA8, "old8"); 2465 values.put(Data.DATA9, "old9"); 2466 values.put(Data.DATA10, "old10"); 2467 values.put(Data.DATA11, "old11"); 2468 values.put(Data.DATA12, "old12"); 2469 values.put(Data.DATA13, "old13"); 2470 values.put(Data.DATA14, "old14"); 2471 values.put(Data.DATA15, "old15"); 2472 Uri uri = mResolver.insert(Data.CONTENT_URI, values); 2473 assertStoredValues(uri, values); 2474 assertNetworkNotified(true); 2475 2476 values.clear(); 2477 values.put(Data.RES_PACKAGE, "newpackage"); 2478 values.put(Data.IS_PRIMARY, 0); 2479 values.put(Data.IS_SUPER_PRIMARY, 0); 2480 values.put(Data.DATA1, "new1"); 2481 values.put(Data.DATA2, "new2"); 2482 values.put(Data.DATA3, "new3"); 2483 values.put(Data.DATA4, "new4"); 2484 values.put(Data.DATA5, "new5"); 2485 values.put(Data.DATA6, "new6"); 2486 values.put(Data.DATA7, "new7"); 2487 values.put(Data.DATA8, "new8"); 2488 values.put(Data.DATA9, "new9"); 2489 values.put(Data.DATA10, "new10"); 2490 values.put(Data.DATA11, "new11"); 2491 values.put(Data.DATA12, "new12"); 2492 values.put(Data.DATA13, "new13"); 2493 values.put(Data.DATA14, "new14"); 2494 values.put(Data.DATA15, "new15"); 2495 mResolver.update(Data.CONTENT_URI, values, Data.RAW_CONTACT_ID + "=" + rawContactId + 2496 " AND " + Data.MIMETYPE + "='testmimetype'", null); 2497 assertNetworkNotified(true); 2498 2499 assertStoredValues(uri, values); 2500 2501 int count = mResolver.delete(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 2502 + " AND " + Data.MIMETYPE + "='testmimetype'", null); 2503 assertEquals(1, count); 2504 assertEquals(0, getCount(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 2505 + " AND " + Data.MIMETYPE + "='testmimetype'", null)); 2506 assertNetworkNotified(true); 2507 } 2508 2509 public void testRawContactQuery() { 2510 Account account1 = new Account("a", "b"); 2511 Account account2 = new Account("c", "d"); 2512 long rawContactId1 = createRawContact(account1); 2513 long rawContactId2 = createRawContact(account2); 2514 2515 Uri uri1 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account1); 2516 Uri uri2 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account2); 2517 assertEquals(1, getCount(uri1, null, null)); 2518 assertEquals(1, getCount(uri2, null, null)); 2519 assertStoredValue(uri1, RawContacts._ID, rawContactId1) ; 2520 assertStoredValue(uri2, RawContacts._ID, rawContactId2) ; 2521 2522 Uri rowUri1 = ContentUris.withAppendedId(uri1, rawContactId1); 2523 Uri rowUri2 = ContentUris.withAppendedId(uri2, rawContactId2); 2524 assertStoredValue(rowUri1, RawContacts._ID, rawContactId1) ; 2525 assertStoredValue(rowUri2, RawContacts._ID, rawContactId2) ; 2526 } 2527 2528 public void testRawContactDeletion() { 2529 long rawContactId = createRawContact(mAccount); 2530 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2531 2532 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 2533 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 2534 StatusUpdates.AVAILABLE, null, 2535 StatusUpdates.CAPABILITY_HAS_CAMERA); 2536 long contactId = queryContactId(rawContactId); 2537 2538 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 2539 null, null)); 2540 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 2541 + rawContactId, null)); 2542 2543 mResolver.delete(uri, null, null); 2544 2545 assertStoredValue(uri, RawContacts.DELETED, "1"); 2546 assertNetworkNotified(true); 2547 2548 Uri permanentDeletionUri = setCallerIsSyncAdapter(uri, mAccount); 2549 mResolver.delete(permanentDeletionUri, null, null); 2550 assertEquals(0, getCount(uri, null, null)); 2551 assertEquals(0, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 2552 null, null)); 2553 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 2554 + rawContactId, null)); 2555 assertEquals(0, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 2556 assertNetworkNotified(false); 2557 } 2558 2559 public void testRawContactDeletionKeepingAggregateContact() { 2560 long rawContactId1 = createRawContactWithName(mAccount); 2561 long rawContactId2 = createRawContactWithName(mAccount); 2562 setAggregationException( 2563 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 2564 2565 long contactId = queryContactId(rawContactId1); 2566 2567 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 2568 Uri permanentDeletionUri = setCallerIsSyncAdapter(uri, mAccount); 2569 mResolver.delete(permanentDeletionUri, null, null); 2570 assertEquals(0, getCount(uri, null, null)); 2571 assertEquals(1, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 2572 } 2573 2574 public void testRawContactDeletionWithAccounts() { 2575 long rawContactId = createRawContact(mAccount); 2576 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2577 2578 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 2579 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 2580 StatusUpdates.AVAILABLE, null, 2581 StatusUpdates.CAPABILITY_HAS_CAMERA); 2582 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 2583 null, null)); 2584 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 2585 + rawContactId, null)); 2586 2587 // Do not delete if we are deleting with wrong account. 2588 Uri deleteWithWrongAccountUri = 2589 RawContacts.CONTENT_URI.buildUpon() 2590 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccountTwo.name) 2591 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccountTwo.type) 2592 .build(); 2593 mResolver.delete(deleteWithWrongAccountUri, null, null); 2594 2595 assertStoredValue(uri, RawContacts.DELETED, "0"); 2596 2597 // Delete if we are deleting with correct account. 2598 Uri deleteWithCorrectAccountUri = 2599 RawContacts.CONTENT_URI.buildUpon() 2600 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccount.name) 2601 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccount.type) 2602 .build(); 2603 mResolver.delete(deleteWithCorrectAccountUri, null, null); 2604 2605 assertStoredValue(uri, RawContacts.DELETED, "1"); 2606 } 2607 2608 public void testAccountsUpdated() { 2609 // This is to ensure we do not delete contacts with null, null (account name, type) 2610 // accidentally. 2611 long rawContactId3 = createRawContactWithName("James", "Sullivan"); 2612 insertPhoneNumber(rawContactId3, "5234567890"); 2613 Uri rawContact3 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId3); 2614 assertEquals(1, getCount(RawContacts.CONTENT_URI, null, null)); 2615 2616 ContactsProvider2 cp = (ContactsProvider2) getProvider(); 2617 cp.onAccountsUpdated(new Account[]{mAccount, mAccountTwo}); 2618 assertEquals(1, getCount(RawContacts.CONTENT_URI, null, null)); 2619 assertStoredValue(rawContact3, RawContacts.ACCOUNT_NAME, null); 2620 assertStoredValue(rawContact3, RawContacts.ACCOUNT_TYPE, null); 2621 2622 long rawContactId1 = createRawContact(mAccount); 2623 insertEmail(rawContactId1, "account1@email.com"); 2624 long rawContactId2 = createRawContact(mAccountTwo); 2625 insertEmail(rawContactId2, "account2@email.com"); 2626 insertImHandle(rawContactId2, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 2627 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 2628 StatusUpdates.AVAILABLE, null, 2629 StatusUpdates.CAPABILITY_HAS_CAMERA); 2630 2631 cp.onAccountsUpdated(new Account[]{mAccount}); 2632 assertEquals(2, getCount(RawContacts.CONTENT_URI, null, null)); 2633 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 2634 + rawContactId2, null)); 2635 } 2636 2637 public void testAccountDeletion() { 2638 Account readOnlyAccount = new Account("act", READ_ONLY_ACCOUNT_TYPE); 2639 ContactsProvider2 cp = (ContactsProvider2) getProvider(); 2640 cp.onAccountsUpdated(new Account[]{readOnlyAccount, mAccount}); 2641 2642 long rawContactId1 = createRawContactWithName("John", "Doe", readOnlyAccount); 2643 Uri photoUri1 = insertPhoto(rawContactId1); 2644 long rawContactId2 = createRawContactWithName("john", "doe", mAccount); 2645 Uri photoUri2 = insertPhoto(rawContactId2); 2646 storeValue(photoUri2, Photo.IS_SUPER_PRIMARY, "1"); 2647 2648 assertAggregated(rawContactId1, rawContactId2); 2649 2650 long contactId = queryContactId(rawContactId1); 2651 2652 // The display name should come from the writable account 2653 assertStoredValue(Uri.withAppendedPath( 2654 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 2655 Contacts.Data.CONTENT_DIRECTORY), 2656 Contacts.DISPLAY_NAME, "john doe"); 2657 2658 // The photo should be the one we marked as super-primary 2659 assertStoredValue(Contacts.CONTENT_URI, contactId, 2660 Contacts.PHOTO_ID, ContentUris.parseId(photoUri2)); 2661 2662 // Remove the writable account 2663 cp.onAccountsUpdated(new Account[]{readOnlyAccount}); 2664 2665 // The display name should come from the remaining account 2666 assertStoredValue(Uri.withAppendedPath( 2667 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 2668 Contacts.Data.CONTENT_DIRECTORY), 2669 Contacts.DISPLAY_NAME, "John Doe"); 2670 2671 // The photo should be the remaining one 2672 assertStoredValue(Contacts.CONTENT_URI, contactId, 2673 Contacts.PHOTO_ID, ContentUris.parseId(photoUri1)); 2674 } 2675 2676 public void testContactDeletion() { 2677 long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1); 2678 long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_2); 2679 2680 long contactId = queryContactId(rawContactId1); 2681 2682 mResolver.delete(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), null, null); 2683 2684 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1), 2685 RawContacts.DELETED, "1"); 2686 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2), 2687 RawContacts.DELETED, "1"); 2688 } 2689 2690 public void testMarkAsDirtyParameter() { 2691 long rawContactId = createRawContact(mAccount); 2692 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2693 2694 Uri uri = insertStructuredName(rawContactId, "John", "Doe"); 2695 clearDirty(rawContactUri); 2696 Uri updateUri = setCallerIsSyncAdapter(uri, mAccount); 2697 2698 ContentValues values = new ContentValues(); 2699 values.put(StructuredName.FAMILY_NAME, "Dough"); 2700 mResolver.update(updateUri, values, null, null); 2701 assertStoredValue(uri, StructuredName.FAMILY_NAME, "Dough"); 2702 assertDirty(rawContactUri, false); 2703 assertNetworkNotified(false); 2704 } 2705 2706 public void testRawContactDirtyAndVersion() { 2707 final long rawContactId = createRawContact(mAccount); 2708 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); 2709 assertDirty(uri, false); 2710 long version = getVersion(uri); 2711 2712 ContentValues values = new ContentValues(); 2713 values.put(ContactsContract.RawContacts.DIRTY, 0); 2714 values.put(ContactsContract.RawContacts.SEND_TO_VOICEMAIL, 1); 2715 values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 2716 RawContacts.AGGREGATION_MODE_IMMEDIATE); 2717 values.put(ContactsContract.RawContacts.STARRED, 1); 2718 assertEquals(1, mResolver.update(uri, values, null, null)); 2719 assertEquals(version, getVersion(uri)); 2720 2721 assertDirty(uri, false); 2722 assertNetworkNotified(false); 2723 2724 Uri emailUri = insertEmail(rawContactId, "goo@woo.com"); 2725 assertDirty(uri, true); 2726 assertNetworkNotified(true); 2727 ++version; 2728 assertEquals(version, getVersion(uri)); 2729 clearDirty(uri); 2730 2731 values = new ContentValues(); 2732 values.put(Email.DATA, "goo@hoo.com"); 2733 mResolver.update(emailUri, values, null, null); 2734 assertDirty(uri, true); 2735 assertNetworkNotified(true); 2736 ++version; 2737 assertEquals(version, getVersion(uri)); 2738 clearDirty(uri); 2739 2740 mResolver.delete(emailUri, null, null); 2741 assertDirty(uri, true); 2742 assertNetworkNotified(true); 2743 ++version; 2744 assertEquals(version, getVersion(uri)); 2745 } 2746 2747 public void testRawContactClearDirty() { 2748 final long rawContactId = createRawContact(mAccount); 2749 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 2750 rawContactId); 2751 long version = getVersion(uri); 2752 insertEmail(rawContactId, "goo@woo.com"); 2753 assertDirty(uri, true); 2754 version++; 2755 assertEquals(version, getVersion(uri)); 2756 2757 clearDirty(uri); 2758 assertDirty(uri, false); 2759 assertEquals(version, getVersion(uri)); 2760 } 2761 2762 public void testRawContactDeletionSetsDirty() { 2763 final long rawContactId = createRawContact(mAccount); 2764 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 2765 rawContactId); 2766 long version = getVersion(uri); 2767 clearDirty(uri); 2768 assertDirty(uri, false); 2769 2770 mResolver.delete(uri, null, null); 2771 assertStoredValue(uri, RawContacts.DELETED, "1"); 2772 assertDirty(uri, true); 2773 assertNetworkNotified(true); 2774 version++; 2775 assertEquals(version, getVersion(uri)); 2776 } 2777 2778 public void testDeleteContactWithoutName() { 2779 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()); 2780 long rawContactId = ContentUris.parseId(rawContactUri); 2781 2782 Uri phoneUri = insertPhoneNumber(rawContactId, "555-123-45678", true); 2783 2784 long contactId = queryContactId(rawContactId); 2785 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2786 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 2787 2788 int numDeleted = mResolver.delete(lookupUri, null, null); 2789 assertEquals(1, numDeleted); 2790 } 2791 2792 public void testDeleteContactWithoutAnyData() { 2793 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()); 2794 long rawContactId = ContentUris.parseId(rawContactUri); 2795 2796 long contactId = queryContactId(rawContactId); 2797 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2798 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 2799 2800 int numDeleted = mResolver.delete(lookupUri, null, null); 2801 assertEquals(1, numDeleted); 2802 } 2803 2804 public void testDeleteContactWithEscapedUri() { 2805 ContentValues values = new ContentValues(); 2806 values.put(RawContacts.SOURCE_ID, "!@#$%^&*()_+=-/.,<>?;'\":[]}{\\|`~"); 2807 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 2808 long rawContactId = ContentUris.parseId(rawContactUri); 2809 2810 long contactId = queryContactId(rawContactId); 2811 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2812 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 2813 assertEquals(1, mResolver.delete(lookupUri, null, null)); 2814 } 2815 2816 public void testQueryContactWithEscapedUri() { 2817 ContentValues values = new ContentValues(); 2818 values.put(RawContacts.SOURCE_ID, "!@#$%^&*()_+=-/.,<>?;'\":[]}{\\|`~"); 2819 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 2820 long rawContactId = ContentUris.parseId(rawContactUri); 2821 2822 long contactId = queryContactId(rawContactId); 2823 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2824 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 2825 Cursor c = mResolver.query(lookupUri, null, null, null, ""); 2826 assertEquals(1, c.getCount()); 2827 c.close(); 2828 } 2829 2830 public void testGetPhotoUri() { 2831 ContentValues values = new ContentValues(); 2832 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 2833 long rawContactId = ContentUris.parseId(rawContactUri); 2834 insertStructuredName(rawContactId, "John", "Doe"); 2835 Uri photoUri = insertPhoto(rawContactId); 2836 2837 Uri twigUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 2838 queryContactId(rawContactId)), Contacts.Photo.CONTENT_DIRECTORY); 2839 2840 assertStoredValue( 2841 ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(rawContactId)), 2842 Contacts.PHOTO_URI, twigUri.toString()); 2843 2844 long twigId = Long.parseLong(getStoredValue(twigUri, Data._ID)); 2845 assertEquals(ContentUris.parseId(photoUri), twigId); 2846 } 2847 2848 public void testInputStreamForPhoto() throws Exception { 2849 long rawContactId = createRawContact(); 2850 Uri photoUri = insertPhoto(rawContactId); 2851 assertInputStreamContent(loadTestPhoto(), mResolver.openInputStream(photoUri)); 2852 2853 Uri contactPhotoUri = Uri.withAppendedPath( 2854 ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(rawContactId)), 2855 Contacts.Photo.CONTENT_DIRECTORY); 2856 assertInputStreamContent(loadTestPhoto(), mResolver.openInputStream(contactPhotoUri)); 2857 } 2858 2859 private static void assertInputStreamContent(byte[] expected, InputStream is) 2860 throws IOException { 2861 try { 2862 byte[] observed = new byte[expected.length]; 2863 int count = is.read(observed); 2864 assertEquals(expected.length, count); 2865 assertEquals(-1, is.read()); 2866 MoreAsserts.assertEquals(expected, observed); 2867 } finally { 2868 is.close(); 2869 } 2870 } 2871 2872 public void testSuperPrimaryPhoto() { 2873 long rawContactId1 = createRawContact(new Account("a", "a")); 2874 Uri photoUri1 = insertPhoto(rawContactId1); 2875 long photoId1 = ContentUris.parseId(photoUri1); 2876 2877 long rawContactId2 = createRawContact(new Account("b", "b")); 2878 Uri photoUri2 = insertPhoto(rawContactId2); 2879 long photoId2 = ContentUris.parseId(photoUri2); 2880 2881 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2882 rawContactId1, rawContactId2); 2883 2884 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 2885 queryContactId(rawContactId1)); 2886 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 2887 assertStoredValue(contactUri, Contacts.PHOTO_URI, 2888 Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY)); 2889 2890 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 2891 rawContactId1, rawContactId2); 2892 2893 ContentValues values = new ContentValues(); 2894 values.put(Data.IS_SUPER_PRIMARY, 1); 2895 mResolver.update(photoUri2, values, null, null); 2896 2897 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2898 rawContactId1, rawContactId2); 2899 contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 2900 queryContactId(rawContactId1)); 2901 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId2); 2902 2903 mResolver.update(photoUri1, values, null, null); 2904 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 2905 } 2906 2907 public void testUpdatePhoto() { 2908 ContentValues values = new ContentValues(); 2909 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 2910 long rawContactId = ContentUris.parseId(rawContactUri); 2911 insertStructuredName(rawContactId, "John", "Doe"); 2912 2913 Uri twigUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 2914 queryContactId(rawContactId)), Contacts.Photo.CONTENT_DIRECTORY); 2915 2916 values.clear(); 2917 values.put(Data.RAW_CONTACT_ID, rawContactId); 2918 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 2919 values.putNull(Photo.PHOTO); 2920 Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 2921 long photoId = ContentUris.parseId(dataUri); 2922 2923 assertNull(getStoredValue(twigUri, Data._ID)); 2924 2925 values.clear(); 2926 values.put(Photo.PHOTO, loadTestPhoto()); 2927 mResolver.update(dataUri, values, null, null); 2928 assertNetworkNotified(true); 2929 2930 long twigId = Long.parseLong(getStoredValue(twigUri, Data._ID)); 2931 assertEquals(photoId, twigId); 2932 } 2933 2934 public void testUpdateRawContactDataPhoto() { 2935 // setup a contact with a null photo 2936 ContentValues values = new ContentValues(); 2937 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 2938 long rawContactId = ContentUris.parseId(rawContactUri); 2939 2940 // setup a photo 2941 values.put(Data.RAW_CONTACT_ID, rawContactId); 2942 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 2943 values.putNull(Photo.PHOTO); 2944 2945 // try to do an update before insert should return count == 0 2946 Uri dataUri = Uri.withAppendedPath( 2947 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 2948 RawContacts.Data.CONTENT_DIRECTORY); 2949 assertEquals(0, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 2950 new String[] {Photo.CONTENT_ITEM_TYPE})); 2951 2952 mResolver.insert(Data.CONTENT_URI, values); 2953 2954 // save a photo to the db 2955 values.clear(); 2956 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 2957 values.put(Photo.PHOTO, loadTestPhoto()); 2958 assertEquals(1, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 2959 new String[] {Photo.CONTENT_ITEM_TYPE})); 2960 2961 // verify the photo 2962 Cursor storedPhoto = mResolver.query(dataUri, new String[] {Photo.PHOTO}, 2963 Data.MIMETYPE + "=?", new String[] {Photo.CONTENT_ITEM_TYPE}, null); 2964 storedPhoto.moveToFirst(); 2965 MoreAsserts.assertEquals(loadTestPhoto(), storedPhoto.getBlob(0)); 2966 storedPhoto.close(); 2967 } 2968 2969 public void testUpdateRawContactSetStarred() { 2970 long rawContactId1 = createRawContactWithName(); 2971 Uri rawContactUri1 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 2972 long rawContactId2 = createRawContactWithName(); 2973 Uri rawContactUri2 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2); 2974 setAggregationException( 2975 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 2976 2977 long contactId = queryContactId(rawContactId1); 2978 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2979 assertStoredValue(contactUri, Contacts.STARRED, "0"); 2980 2981 ContentValues values = new ContentValues(); 2982 values.put(RawContacts.STARRED, "1"); 2983 2984 mResolver.update(rawContactUri1, values, null, null); 2985 2986 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 2987 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 2988 assertStoredValue(contactUri, Contacts.STARRED, "1"); 2989 2990 values.put(RawContacts.STARRED, "0"); 2991 mResolver.update(rawContactUri1, values, null, null); 2992 2993 assertStoredValue(rawContactUri1, RawContacts.STARRED, "0"); 2994 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 2995 assertStoredValue(contactUri, Contacts.STARRED, "0"); 2996 2997 values.put(Contacts.STARRED, "1"); 2998 mResolver.update(contactUri, values, null, null); 2999 3000 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 3001 assertStoredValue(rawContactUri2, RawContacts.STARRED, "1"); 3002 assertStoredValue(contactUri, Contacts.STARRED, "1"); 3003 } 3004 3005 public void testSetAndClearSuperPrimaryEmail() { 3006 long rawContactId1 = createRawContact(new Account("a", "a")); 3007 Uri mailUri11 = insertEmail(rawContactId1, "test1@domain1.com"); 3008 Uri mailUri12 = insertEmail(rawContactId1, "test2@domain1.com"); 3009 3010 long rawContactId2 = createRawContact(new Account("b", "b")); 3011 Uri mailUri21 = insertEmail(rawContactId2, "test1@domain2.com"); 3012 Uri mailUri22 = insertEmail(rawContactId2, "test2@domain2.com"); 3013 3014 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 3015 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 3016 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 3017 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 3018 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3019 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3020 assertStoredValue(mailUri22, Data.IS_PRIMARY, 0); 3021 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); 3022 3023 // Set super primary on the first pair, primary on the second 3024 { 3025 ContentValues values = new ContentValues(); 3026 values.put(Data.IS_SUPER_PRIMARY, 1); 3027 mResolver.update(mailUri11, values, null, null); 3028 } 3029 { 3030 ContentValues values = new ContentValues(); 3031 values.put(Data.IS_SUPER_PRIMARY, 1); 3032 mResolver.update(mailUri22, values, null, null); 3033 } 3034 3035 assertStoredValue(mailUri11, Data.IS_PRIMARY, 1); 3036 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 1); 3037 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 3038 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 3039 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3040 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3041 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 3042 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 3043 3044 // Clear primary on the first pair, make sure second is not affected and super_primary is 3045 // also cleared 3046 { 3047 ContentValues values = new ContentValues(); 3048 values.put(Data.IS_PRIMARY, 0); 3049 mResolver.update(mailUri11, values, null, null); 3050 } 3051 3052 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 3053 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 3054 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 3055 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 3056 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3057 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3058 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 3059 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 3060 3061 // Ensure that we can only clear super_primary, if we specify the correct data row 3062 { 3063 ContentValues values = new ContentValues(); 3064 values.put(Data.IS_SUPER_PRIMARY, 0); 3065 mResolver.update(mailUri21, values, null, null); 3066 } 3067 3068 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3069 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3070 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 3071 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 3072 3073 // Ensure that we can only clear primary, if we specify the correct data row 3074 { 3075 ContentValues values = new ContentValues(); 3076 values.put(Data.IS_PRIMARY, 0); 3077 mResolver.update(mailUri21, values, null, null); 3078 } 3079 3080 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3081 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3082 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 3083 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 3084 3085 // Now clear super-primary for real 3086 { 3087 ContentValues values = new ContentValues(); 3088 values.put(Data.IS_SUPER_PRIMARY, 0); 3089 mResolver.update(mailUri22, values, null, null); 3090 } 3091 3092 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 3093 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 3094 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 3095 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 3096 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 3097 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 3098 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 3099 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); 3100 } 3101 3102 /** 3103 * Common function for the testNewPrimaryIn* functions. Its four configurations 3104 * are each called from its own test 3105 */ 3106 public void testChangingPrimary(boolean inUpdate, boolean withSuperPrimary) { 3107 long rawContactId = createRawContact(new Account("a", "a")); 3108 Uri mailUri1 = insertEmail(rawContactId, "test1@domain1.com", true); 3109 3110 if (withSuperPrimary) { 3111 final ContentValues values = new ContentValues(); 3112 values.put(Data.IS_SUPER_PRIMARY, 1); 3113 mResolver.update(mailUri1, values, null, null); 3114 } 3115 3116 assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); 3117 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 3118 3119 // Insert another item 3120 final Uri mailUri2; 3121 if (inUpdate) { 3122 mailUri2 = insertEmail(rawContactId, "test2@domain1.com"); 3123 3124 assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); 3125 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 3126 assertStoredValue(mailUri2, Data.IS_PRIMARY, 0); 3127 assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, 0); 3128 3129 final ContentValues values = new ContentValues(); 3130 values.put(Data.IS_PRIMARY, 1); 3131 mResolver.update(mailUri2, values, null, null); 3132 } else { 3133 // directly add as default 3134 mailUri2 = insertEmail(rawContactId, "test2@domain1.com", true); 3135 } 3136 3137 // Ensure that primary has been unset on the first 3138 // If withSuperPrimary is set, also ensure that is has been moved to the new item 3139 assertStoredValue(mailUri1, Data.IS_PRIMARY, 0); 3140 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, 0); 3141 assertStoredValue(mailUri2, Data.IS_PRIMARY, 1); 3142 assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 3143 } 3144 3145 public void testNewPrimaryInInsert() { 3146 testChangingPrimary(false, false); 3147 } 3148 3149 public void testNewPrimaryInInsertWithSuperPrimary() { 3150 testChangingPrimary(false, true); 3151 } 3152 3153 public void testNewPrimaryInUpdate() { 3154 testChangingPrimary(true, false); 3155 } 3156 3157 public void testNewPrimaryInUpdateWithSuperPrimary() { 3158 testChangingPrimary(true, true); 3159 } 3160 3161 public void testLiveFolders() { 3162 long rawContactId1 = createRawContactWithName("James", "Sullivan"); 3163 insertPhoneNumber(rawContactId1, "5234567890"); 3164 long contactId1 = queryContactId(rawContactId1); 3165 3166 long rawContactId2 = createRawContactWithName("Mike", "Wazowski"); 3167 long contactId2 = queryContactId(rawContactId2); 3168 storeValue(Contacts.CONTENT_URI, contactId2, Contacts.STARRED, "1"); 3169 3170 long rawContactId3 = createRawContactWithName("Randall", "Boggs"); 3171 long contactId3 = queryContactId(rawContactId3); 3172 long groupId = createGroup(NO_ACCOUNT, "src1", "VIP"); 3173 insertGroupMembership(rawContactId3, groupId); 3174 3175 assertLiveFolderContents( 3176 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 3177 "live_folders/contacts"), 3178 contactId1, "James Sullivan", 3179 contactId2, "Mike Wazowski", 3180 contactId3, "Randall Boggs"); 3181 3182 assertLiveFolderContents( 3183 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 3184 "live_folders/contacts_with_phones"), 3185 contactId1, "James Sullivan"); 3186 3187 assertLiveFolderContents( 3188 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 3189 "live_folders/favorites"), 3190 contactId2, "Mike Wazowski"); 3191 3192 assertLiveFolderContents( 3193 Uri.withAppendedPath(Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 3194 "live_folders/contacts"), Uri.encode("VIP")), 3195 contactId3, "Randall Boggs"); 3196 } 3197 3198 private void assertLiveFolderContents(Uri uri, Object... expected) { 3199 Cursor c = mResolver.query(uri, new String[]{LiveFolders._ID, LiveFolders.NAME}, 3200 null, null, LiveFolders._ID); 3201 assertEquals(expected.length/2, c.getCount()); 3202 for (int i = 0; i < expected.length/2; i++) { 3203 assertTrue(c.moveToNext()); 3204 assertEquals(((Long)expected[i * 2]).longValue(), c.getLong(0)); 3205 assertEquals(expected[i * 2 + 1], c.getString(1)); 3206 } 3207 c.close(); 3208 } 3209 3210 public void testContactCounts() { 3211 Uri uri = Contacts.CONTENT_URI.buildUpon() 3212 .appendQueryParameter(ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, "true").build(); 3213 3214 createRawContact(); 3215 createRawContactWithName("James", "Sullivan"); 3216 createRawContactWithName("The Abominable", "Snowman"); 3217 createRawContactWithName("Mike", "Wazowski"); 3218 createRawContactWithName("randall", "boggs"); 3219 createRawContactWithName("Boo", null); 3220 createRawContactWithName("Mary", null); 3221 createRawContactWithName("Roz", null); 3222 3223 Cursor cursor = mResolver.query(uri, 3224 new String[]{Contacts.DISPLAY_NAME}, 3225 null, null, Contacts.SORT_KEY_PRIMARY + " COLLATE LOCALIZED"); 3226 3227 assertFirstLetterValues(cursor, null, "B", "J", "M", "R", "T"); 3228 assertFirstLetterCounts(cursor, 1, 1, 1, 2, 2, 1); 3229 cursor.close(); 3230 3231 cursor = mResolver.query(uri, 3232 new String[]{Contacts.DISPLAY_NAME}, 3233 null, null, Contacts.SORT_KEY_ALTERNATIVE + " COLLATE LOCALIZED DESC"); 3234 3235 assertFirstLetterValues(cursor, "W", "S", "R", "M", "B", null); 3236 assertFirstLetterCounts(cursor, 1, 2, 1, 1, 2, 1); 3237 cursor.close(); 3238 } 3239 3240 private void assertFirstLetterValues(Cursor cursor, String... expected) { 3241 String[] actual = cursor.getExtras() 3242 .getStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES); 3243 MoreAsserts.assertEquals(expected, actual); 3244 } 3245 3246 private void assertFirstLetterCounts(Cursor cursor, int... expected) { 3247 int[] actual = cursor.getExtras() 3248 .getIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS); 3249 MoreAsserts.assertEquals(expected, actual); 3250 } 3251 3252 public void testReadBooleanQueryParameter() { 3253 assertBooleanUriParameter("foo:bar", "bool", true, true); 3254 assertBooleanUriParameter("foo:bar", "bool", false, false); 3255 assertBooleanUriParameter("foo:bar?bool=0", "bool", true, false); 3256 assertBooleanUriParameter("foo:bar?bool=1", "bool", false, true); 3257 assertBooleanUriParameter("foo:bar?bool=false", "bool", true, false); 3258 assertBooleanUriParameter("foo:bar?bool=true", "bool", false, true); 3259 assertBooleanUriParameter("foo:bar?bool=FaLsE", "bool", true, false); 3260 assertBooleanUriParameter("foo:bar?bool=false&some=some", "bool", true, false); 3261 assertBooleanUriParameter("foo:bar?bool=1&some=some", "bool", false, true); 3262 assertBooleanUriParameter("foo:bar?some=bool", "bool", true, true); 3263 assertBooleanUriParameter("foo:bar?bool", "bool", true, true); 3264 } 3265 3266 private void assertBooleanUriParameter(String uriString, String parameter, 3267 boolean defaultValue, boolean expectedValue) { 3268 assertEquals(expectedValue, ContactsProvider2.readBooleanQueryParameter( 3269 Uri.parse(uriString), parameter, defaultValue)); 3270 } 3271 3272 public void testGetQueryParameter() { 3273 assertQueryParameter("foo:bar", "param", null); 3274 assertQueryParameter("foo:bar?param", "param", null); 3275 assertQueryParameter("foo:bar?param=", "param", ""); 3276 assertQueryParameter("foo:bar?param=val", "param", "val"); 3277 assertQueryParameter("foo:bar?param=val&some=some", "param", "val"); 3278 assertQueryParameter("foo:bar?some=some¶m=val", "param", "val"); 3279 assertQueryParameter("foo:bar?some=some¶m=val&else=else", "param", "val"); 3280 assertQueryParameter("foo:bar?param=john%40doe.com", "param", "john@doe.com"); 3281 } 3282 3283 public void testMissingAccountTypeParameter() { 3284 // Try querying for RawContacts only using ACCOUNT_NAME 3285 final Uri queryUri = RawContacts.CONTENT_URI.buildUpon().appendQueryParameter( 3286 RawContacts.ACCOUNT_NAME, "lolwut").build(); 3287 try { 3288 final Cursor cursor = mResolver.query(queryUri, null, null, null, null); 3289 fail("Able to query with incomplete account query parameters"); 3290 } catch (IllegalArgumentException e) { 3291 // Expected behavior. 3292 } 3293 } 3294 3295 public void testInsertInconsistentAccountType() { 3296 // Try inserting RawContact with inconsistent Accounts 3297 final Account red = new Account("red", "red"); 3298 final Account blue = new Account("blue", "blue"); 3299 3300 final ContentValues values = new ContentValues(); 3301 values.put(RawContacts.ACCOUNT_NAME, red.name); 3302 values.put(RawContacts.ACCOUNT_TYPE, red.type); 3303 3304 final Uri insertUri = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, blue); 3305 try { 3306 mResolver.insert(insertUri, values); 3307 fail("Able to insert RawContact with inconsistent account details"); 3308 } catch (IllegalArgumentException e) { 3309 // Expected behavior. 3310 } 3311 } 3312 3313 public void testProviderStatusNoContactsNoAccounts() throws Exception { 3314 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 3315 } 3316 3317 public void testProviderStatusOnlyLocalContacts() throws Exception { 3318 long rawContactId = createRawContact(); 3319 assertProviderStatus(ProviderStatus.STATUS_NORMAL); 3320 mResolver.delete( 3321 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), null, null); 3322 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 3323 } 3324 3325 public void testProviderStatusWithAccounts() throws Exception { 3326 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 3327 ((ContactsProvider2)getProvider()).onAccountsUpdated(new Account[]{ACCOUNT_1}); 3328 assertProviderStatus(ProviderStatus.STATUS_NORMAL); 3329 ((ContactsProvider2)getProvider()).onAccountsUpdated(new Account[0]); 3330 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 3331 } 3332 3333 private void assertProviderStatus(int expectedProviderStatus) { 3334 Cursor cursor = mResolver.query(ProviderStatus.CONTENT_URI, 3335 new String[]{ProviderStatus.DATA1, ProviderStatus.STATUS}, null, null, null); 3336 assertTrue(cursor.moveToFirst()); 3337 assertEquals(0, cursor.getLong(0)); 3338 assertEquals(expectedProviderStatus, cursor.getInt(1)); 3339 cursor.close(); 3340 } 3341 3342 public void testProperties() throws Exception { 3343 ContactsProvider2 provider = (ContactsProvider2)getProvider(); 3344 ContactsDatabaseHelper helper = (ContactsDatabaseHelper)provider.getDatabaseHelper(); 3345 assertNull(helper.getProperty("non-existent", null)); 3346 assertEquals("default", helper.getProperty("non-existent", "default")); 3347 3348 helper.setProperty("existent1", "string1"); 3349 helper.setProperty("existent2", "string2"); 3350 assertEquals("string1", helper.getProperty("existent1", "default")); 3351 assertEquals("string2", helper.getProperty("existent2", "default")); 3352 helper.setProperty("existent1", null); 3353 assertEquals("default", helper.getProperty("existent1", "default")); 3354 } 3355 3356 private class VCardTestUriCreator { 3357 private String mLookup1; 3358 private String mLookup2; 3359 3360 public VCardTestUriCreator(String lookup1, String lookup2) { 3361 super(); 3362 mLookup1 = lookup1; 3363 mLookup2 = lookup2; 3364 } 3365 3366 public Uri getUri1() { 3367 return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1); 3368 } 3369 3370 public Uri getUri2() { 3371 return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2); 3372 } 3373 3374 public Uri getCombinedUri() { 3375 return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI, 3376 Uri.encode(mLookup1 + ":" + mLookup2)); 3377 } 3378 } 3379 3380 private VCardTestUriCreator createVCardTestContacts() { 3381 final long rawContactId1 = createRawContact(mAccount, RawContacts.SOURCE_ID, "4:12"); 3382 insertStructuredName(rawContactId1, "John", "Doe"); 3383 3384 final long rawContactId2 = createRawContact(mAccount, RawContacts.SOURCE_ID, "3:4%121"); 3385 insertStructuredName(rawContactId2, "Jane", "Doh"); 3386 3387 final long contactId1 = queryContactId(rawContactId1); 3388 final long contactId2 = queryContactId(rawContactId2); 3389 final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1); 3390 final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2); 3391 final String lookup1 = 3392 Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2)); 3393 final String lookup2 = 3394 Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2)); 3395 return new VCardTestUriCreator(lookup1, lookup2); 3396 } 3397 3398 public void testQueryMultiVCard() { 3399 // No need to create any contacts here, because the query for multiple vcards 3400 // does not go into the database at all 3401 Uri uri = Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI, Uri.encode("123:456")); 3402 Cursor cursor = mResolver.query(uri, null, null, null, null); 3403 assertEquals(1, cursor.getCount()); 3404 assertTrue(cursor.moveToFirst()); 3405 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 3406 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 3407 3408 // The resulting name contains date and time. Ensure that before and after are correct 3409 assertTrue(filename.startsWith("vcards_")); 3410 assertTrue(filename.endsWith(".vcf")); 3411 cursor.close(); 3412 } 3413 3414 public void testQueryFileSingleVCard() { 3415 final VCardTestUriCreator contacts = createVCardTestContacts(); 3416 3417 { 3418 Cursor cursor = mResolver.query(contacts.getUri1(), null, null, null, null); 3419 assertEquals(1, cursor.getCount()); 3420 assertTrue(cursor.moveToFirst()); 3421 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 3422 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 3423 assertEquals("John Doe.vcf", filename); 3424 cursor.close(); 3425 } 3426 3427 { 3428 Cursor cursor = mResolver.query(contacts.getUri2(), null, null, null, null); 3429 assertEquals(1, cursor.getCount()); 3430 assertTrue(cursor.moveToFirst()); 3431 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 3432 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 3433 assertEquals("Jane Doh.vcf", filename); 3434 cursor.close(); 3435 } 3436 } 3437 3438 3439 public void testOpenAssetFileMultiVCard() throws IOException { 3440 final VCardTestUriCreator contacts = createVCardTestContacts(); 3441 3442 final AssetFileDescriptor descriptor = 3443 mResolver.openAssetFileDescriptor(contacts.getCombinedUri(), "r"); 3444 final FileInputStream inputStream = descriptor.createInputStream(); 3445 String data = readToEnd(inputStream); 3446 inputStream.close(); 3447 descriptor.close(); 3448 3449 // Ensure that the resulting VCard has both contacts 3450 assertTrue(data.contains("N:Doe;John;;;")); 3451 assertTrue(data.contains("N:Doh;Jane;;;")); 3452 } 3453 3454 public void testOpenAssetFileSingleVCard() throws IOException { 3455 final VCardTestUriCreator contacts = createVCardTestContacts(); 3456 3457 // Ensure that the right VCard is being created in each case 3458 { 3459 final AssetFileDescriptor descriptor = 3460 mResolver.openAssetFileDescriptor(contacts.getUri1(), "r"); 3461 final FileInputStream inputStream = descriptor.createInputStream(); 3462 final String data = readToEnd(inputStream); 3463 assertTrue(data.contains("N:Doe;John;;;")); 3464 assertFalse(data.contains("N:Doh;Jane;;;")); 3465 3466 inputStream.close(); 3467 descriptor.close(); 3468 } 3469 3470 { 3471 final AssetFileDescriptor descriptor = 3472 mResolver.openAssetFileDescriptor(contacts.getUri2(), "r"); 3473 final FileInputStream inputStream = descriptor.createInputStream(); 3474 final String data = readToEnd(inputStream); 3475 inputStream.close(); 3476 descriptor.close(); 3477 3478 assertFalse(data.contains("N:Doe;John;;;")); 3479 assertTrue(data.contains("N:Doh;Jane;;;")); 3480 } 3481 } 3482 3483 public void testAutoGroupMembership() { 3484 long g1 = createGroup(mAccount, "g1", "t1", 0, true /* autoAdd */, false /* favorite */); 3485 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 3486 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, true /* autoAdd */, false /* favorite */); 3487 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, false/* favorite */); 3488 long r1 = createRawContact(mAccount); 3489 long r2 = createRawContact(mAccountTwo); 3490 long r3 = createRawContact(null); 3491 3492 Cursor c = queryGroupMemberships(mAccount); 3493 try { 3494 assertTrue(c.moveToNext()); 3495 assertEquals(g1, c.getLong(0)); 3496 assertEquals(r1, c.getLong(1)); 3497 assertFalse(c.moveToNext()); 3498 } finally { 3499 c.close(); 3500 } 3501 3502 c = queryGroupMemberships(mAccountTwo); 3503 try { 3504 assertTrue(c.moveToNext()); 3505 assertEquals(g3, c.getLong(0)); 3506 assertEquals(r2, c.getLong(1)); 3507 assertFalse(c.moveToNext()); 3508 } finally { 3509 c.close(); 3510 } 3511 } 3512 3513 public void testNoAutoAddMembershipAfterGroupCreation() { 3514 long r1 = createRawContact(mAccount); 3515 long r2 = createRawContact(mAccount); 3516 long r3 = createRawContact(mAccount); 3517 long r4 = createRawContact(mAccountTwo); 3518 long r5 = createRawContact(mAccountTwo); 3519 long r6 = createRawContact(null); 3520 3521 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3522 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3523 3524 long g1 = createGroup(mAccount, "g1", "t1", 0, true /* autoAdd */, false /* favorite */); 3525 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 3526 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, true /* autoAdd */, false/* favorite */); 3527 3528 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3529 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3530 } 3531 3532 // create some starred and non-starred contacts, some associated with account, some not 3533 // favorites group created 3534 // the starred contacts should be added to group 3535 // favorites group removed 3536 // no change to starred status 3537 public void testFavoritesMembershipAfterGroupCreation() { 3538 long r1 = createRawContact(mAccount, RawContacts.STARRED, "1"); 3539 long r2 = createRawContact(mAccount); 3540 long r3 = createRawContact(mAccount, RawContacts.STARRED, "1"); 3541 long r4 = createRawContact(mAccountTwo, RawContacts.STARRED, "1"); 3542 long r5 = createRawContact(mAccountTwo); 3543 long r6 = createRawContact(null, RawContacts.STARRED, "1"); 3544 long r7 = createRawContact(null); 3545 3546 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3547 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3548 3549 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 3550 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 3551 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, false /* autoAdd */, false/* favorite */); 3552 3553 assertTrue(queryRawContactIsStarred(r1)); 3554 assertFalse(queryRawContactIsStarred(r2)); 3555 assertTrue(queryRawContactIsStarred(r3)); 3556 assertTrue(queryRawContactIsStarred(r4)); 3557 assertFalse(queryRawContactIsStarred(r5)); 3558 assertTrue(queryRawContactIsStarred(r6)); 3559 assertFalse(queryRawContactIsStarred(r7)); 3560 3561 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3562 Cursor c = queryGroupMemberships(mAccount); 3563 try { 3564 assertTrue(c.moveToNext()); 3565 assertEquals(g1, c.getLong(0)); 3566 assertEquals(r1, c.getLong(1)); 3567 assertTrue(c.moveToNext()); 3568 assertEquals(g1, c.getLong(0)); 3569 assertEquals(r3, c.getLong(1)); 3570 assertFalse(c.moveToNext()); 3571 } finally { 3572 c.close(); 3573 } 3574 3575 updateItem(RawContacts.CONTENT_URI, r6, 3576 RawContacts.ACCOUNT_NAME, mAccount.name, 3577 RawContacts.ACCOUNT_TYPE, mAccount.type); 3578 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3579 c = queryGroupMemberships(mAccount); 3580 try { 3581 assertTrue(c.moveToNext()); 3582 assertEquals(g1, c.getLong(0)); 3583 assertEquals(r1, c.getLong(1)); 3584 assertTrue(c.moveToNext()); 3585 assertEquals(g1, c.getLong(0)); 3586 assertEquals(r3, c.getLong(1)); 3587 assertTrue(c.moveToNext()); 3588 assertEquals(g1, c.getLong(0)); 3589 assertEquals(r6, c.getLong(1)); 3590 assertFalse(c.moveToNext()); 3591 } finally { 3592 c.close(); 3593 } 3594 3595 mResolver.delete(ContentUris.withAppendedId(Groups.CONTENT_URI, g1), null, null); 3596 3597 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3598 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3599 3600 assertTrue(queryRawContactIsStarred(r1)); 3601 assertFalse(queryRawContactIsStarred(r2)); 3602 assertTrue(queryRawContactIsStarred(r3)); 3603 assertTrue(queryRawContactIsStarred(r4)); 3604 assertFalse(queryRawContactIsStarred(r5)); 3605 assertTrue(queryRawContactIsStarred(r6)); 3606 assertFalse(queryRawContactIsStarred(r7)); 3607 } 3608 3609 public void testFavoritesGroupMembershipChangeAfterStarChange() { 3610 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 3611 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false/* favorite */); 3612 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, true /* favorite */); 3613 long g5 = createGroup(mAccountTwo, "g5", "t5", 0, false /* autoAdd */, false/* favorite */); 3614 long r1 = createRawContact(mAccount, RawContacts.STARRED, "1"); 3615 long r2 = createRawContact(mAccount); 3616 long r3 = createRawContact(mAccountTwo); 3617 3618 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3619 Cursor c = queryGroupMemberships(mAccount); 3620 try { 3621 assertTrue(c.moveToNext()); 3622 assertEquals(g1, c.getLong(0)); 3623 assertEquals(r1, c.getLong(1)); 3624 assertFalse(c.moveToNext()); 3625 } finally { 3626 c.close(); 3627 } 3628 3629 // remove the star from r1 3630 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "0")); 3631 3632 // Since no raw contacts are starred, there should be no group memberships. 3633 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3634 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3635 3636 // mark r1 as starred 3637 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "1")); 3638 // Now that r1 is starred it should have a membership in the one groups from mAccount 3639 // that is marked as a favorite. 3640 // There should be no memberships in mAccountTwo since it has no starred raw contacts. 3641 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3642 c = queryGroupMemberships(mAccount); 3643 try { 3644 assertTrue(c.moveToNext()); 3645 assertEquals(g1, c.getLong(0)); 3646 assertEquals(r1, c.getLong(1)); 3647 assertFalse(c.moveToNext()); 3648 } finally { 3649 c.close(); 3650 } 3651 3652 // remove the star from r1 3653 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "0")); 3654 // Since no raw contacts are starred, there should be no group memberships. 3655 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3656 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3657 3658 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(r1)); 3659 assertNotNull(contactUri); 3660 3661 // mark r1 as starred via its contact lookup uri 3662 assertEquals(1, updateItem(contactUri, Contacts.STARRED, "1")); 3663 // Now that r1 is starred it should have a membership in the one groups from mAccount 3664 // that is marked as a favorite. 3665 // There should be no memberships in mAccountTwo since it has no starred raw contacts. 3666 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3667 c = queryGroupMemberships(mAccount); 3668 try { 3669 assertTrue(c.moveToNext()); 3670 assertEquals(g1, c.getLong(0)); 3671 assertEquals(r1, c.getLong(1)); 3672 assertFalse(c.moveToNext()); 3673 } finally { 3674 c.close(); 3675 } 3676 3677 // remove the star from r1 3678 updateItem(contactUri, Contacts.STARRED, "0"); 3679 // Since no raw contacts are starred, there should be no group memberships. 3680 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3681 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3682 } 3683 3684 public void testStarChangedAfterGroupMembershipChange() { 3685 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 3686 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false/* favorite */); 3687 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, true /* favorite */); 3688 long g5 = createGroup(mAccountTwo, "g5", "t5", 0, false /* autoAdd */, false/* favorite */); 3689 long r1 = createRawContact(mAccount); 3690 long r2 = createRawContact(mAccount); 3691 long r3 = createRawContact(mAccountTwo); 3692 3693 assertFalse(queryRawContactIsStarred(r1)); 3694 assertFalse(queryRawContactIsStarred(r2)); 3695 assertFalse(queryRawContactIsStarred(r3)); 3696 3697 Cursor c; 3698 3699 // add r1 to one favorites group 3700 // r1's star should automatically be set 3701 // r1 should automatically be added to the other favorites group 3702 Uri urir1g1 = insertGroupMembership(r1, g1); 3703 assertTrue(queryRawContactIsStarred(r1)); 3704 assertFalse(queryRawContactIsStarred(r2)); 3705 assertFalse(queryRawContactIsStarred(r3)); 3706 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3707 c = queryGroupMemberships(mAccount); 3708 try { 3709 assertTrue(c.moveToNext()); 3710 assertEquals(g1, c.getLong(0)); 3711 assertEquals(r1, c.getLong(1)); 3712 assertFalse(c.moveToNext()); 3713 } finally { 3714 c.close(); 3715 } 3716 3717 // remove r1 from one favorites group 3718 mResolver.delete(urir1g1, null, null); 3719 // r1's star should no longer be set 3720 assertFalse(queryRawContactIsStarred(r1)); 3721 assertFalse(queryRawContactIsStarred(r2)); 3722 assertFalse(queryRawContactIsStarred(r3)); 3723 // there should be no membership rows 3724 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3725 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3726 3727 // add r3 to the one favorites group for that account 3728 // r3's star should automatically be set 3729 Uri urir3g4 = insertGroupMembership(r3, g4); 3730 assertFalse(queryRawContactIsStarred(r1)); 3731 assertFalse(queryRawContactIsStarred(r2)); 3732 assertTrue(queryRawContactIsStarred(r3)); 3733 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3734 c = queryGroupMemberships(mAccountTwo); 3735 try { 3736 assertTrue(c.moveToNext()); 3737 assertEquals(g4, c.getLong(0)); 3738 assertEquals(r3, c.getLong(1)); 3739 assertFalse(c.moveToNext()); 3740 } finally { 3741 c.close(); 3742 } 3743 3744 // remove r3 from the favorites group 3745 mResolver.delete(urir3g4, null, null); 3746 // r3's star should automatically be cleared 3747 assertFalse(queryRawContactIsStarred(r1)); 3748 assertFalse(queryRawContactIsStarred(r2)); 3749 assertFalse(queryRawContactIsStarred(r3)); 3750 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 3751 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 3752 } 3753 3754 public void testReadOnlyRawContact() { 3755 long rawContactId = createRawContact(); 3756 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 3757 storeValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "first"); 3758 storeValue(rawContactUri, RawContacts.RAW_CONTACT_IS_READ_ONLY, 1); 3759 3760 storeValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "second"); 3761 assertStoredValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "first"); 3762 3763 Uri syncAdapterUri = rawContactUri.buildUpon() 3764 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "1") 3765 .build(); 3766 storeValue(syncAdapterUri, RawContacts.CUSTOM_RINGTONE, "third"); 3767 assertStoredValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "third"); 3768 } 3769 3770 public void testReadOnlyDataRow() { 3771 long rawContactId = createRawContact(); 3772 Uri emailUri = insertEmail(rawContactId, "email"); 3773 Uri phoneUri = insertPhoneNumber(rawContactId, "555-1111"); 3774 3775 storeValue(emailUri, Data.IS_READ_ONLY, "1"); 3776 storeValue(emailUri, Email.ADDRESS, "changed"); 3777 storeValue(phoneUri, Phone.NUMBER, "555-2222"); 3778 assertStoredValue(emailUri, Email.ADDRESS, "email"); 3779 assertStoredValue(phoneUri, Phone.NUMBER, "555-2222"); 3780 3781 Uri syncAdapterUri = emailUri.buildUpon() 3782 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "1") 3783 .build(); 3784 storeValue(syncAdapterUri, Email.ADDRESS, "changed"); 3785 assertStoredValue(emailUri, Email.ADDRESS, "changed"); 3786 } 3787 3788 public void testContactWithReadOnlyRawContact() { 3789 long rawContactId1 = createRawContact(); 3790 Uri rawContactUri1 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 3791 storeValue(rawContactUri1, RawContacts.CUSTOM_RINGTONE, "first"); 3792 3793 long rawContactId2 = createRawContact(); 3794 Uri rawContactUri2 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2); 3795 storeValue(rawContactUri2, RawContacts.CUSTOM_RINGTONE, "second"); 3796 storeValue(rawContactUri2, RawContacts.RAW_CONTACT_IS_READ_ONLY, 1); 3797 3798 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 3799 rawContactId1, rawContactId2); 3800 3801 long contactId = queryContactId(rawContactId1); 3802 3803 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 3804 storeValue(contactUri, Contacts.CUSTOM_RINGTONE, "rt"); 3805 assertStoredValue(contactUri, Contacts.CUSTOM_RINGTONE, "rt"); 3806 assertStoredValue(rawContactUri1, RawContacts.CUSTOM_RINGTONE, "rt"); 3807 assertStoredValue(rawContactUri2, RawContacts.CUSTOM_RINGTONE, "second"); 3808 } 3809 3810 public void testNameParsingQuery() { 3811 Uri uri = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name") 3812 .appendQueryParameter(StructuredName.DISPLAY_NAME, "Mr. John Q. Doe Jr.").build(); 3813 Cursor cursor = mResolver.query(uri, null, null, null, null); 3814 ContentValues values = new ContentValues(); 3815 values.put(StructuredName.DISPLAY_NAME, "Mr. John Q. Doe Jr."); 3816 values.put(StructuredName.PREFIX, "Mr"); 3817 values.put(StructuredName.GIVEN_NAME, "John"); 3818 values.put(StructuredName.MIDDLE_NAME, "Q."); 3819 values.put(StructuredName.FAMILY_NAME, "Doe"); 3820 values.put(StructuredName.SUFFIX, "Jr."); 3821 values.put(StructuredName.FULL_NAME_STYLE, FullNameStyle.WESTERN); 3822 assertTrue(cursor.moveToFirst()); 3823 assertCursorValues(cursor, values); 3824 cursor.close(); 3825 } 3826 3827 public void testNameConcatenationQuery() { 3828 Uri uri = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name") 3829 .appendQueryParameter(StructuredName.PREFIX, "Mr") 3830 .appendQueryParameter(StructuredName.GIVEN_NAME, "John") 3831 .appendQueryParameter(StructuredName.MIDDLE_NAME, "Q.") 3832 .appendQueryParameter(StructuredName.FAMILY_NAME, "Doe") 3833 .appendQueryParameter(StructuredName.SUFFIX, "Jr.") 3834 .build(); 3835 Cursor cursor = mResolver.query(uri, null, null, null, null); 3836 ContentValues values = new ContentValues(); 3837 values.put(StructuredName.DISPLAY_NAME, "John Q. Doe, Jr."); 3838 values.put(StructuredName.PREFIX, "Mr"); 3839 values.put(StructuredName.GIVEN_NAME, "John"); 3840 values.put(StructuredName.MIDDLE_NAME, "Q."); 3841 values.put(StructuredName.FAMILY_NAME, "Doe"); 3842 values.put(StructuredName.SUFFIX, "Jr."); 3843 values.put(StructuredName.FULL_NAME_STYLE, FullNameStyle.WESTERN); 3844 assertTrue(cursor.moveToFirst()); 3845 assertCursorValues(cursor, values); 3846 cursor.close(); 3847 } 3848 3849 private Cursor queryGroupMemberships(Account account) { 3850 Cursor c = mResolver.query(maybeAddAccountQueryParameters(Data.CONTENT_URI, account), 3851 new String[]{GroupMembership.GROUP_ROW_ID, GroupMembership.RAW_CONTACT_ID}, 3852 Data.MIMETYPE + "=?", new String[]{GroupMembership.CONTENT_ITEM_TYPE}, 3853 GroupMembership.GROUP_SOURCE_ID); 3854 return c; 3855 } 3856 3857 private String readToEnd(FileInputStream inputStream) { 3858 try { 3859 int ch; 3860 StringBuilder stringBuilder = new StringBuilder(); 3861 while ((ch = inputStream.read()) != -1) 3862 stringBuilder.append((char)ch); 3863 return stringBuilder.toString(); 3864 } catch (IOException e) { 3865 return null; 3866 } 3867 } 3868 3869 private void assertQueryParameter(String uriString, String parameter, String expectedValue) { 3870 assertEquals(expectedValue, ContactsProvider2.getQueryParameter( 3871 Uri.parse(uriString), parameter)); 3872 } 3873 3874 private long createContact(ContentValues values, String firstName, String givenName, 3875 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 3876 long groupId, int chatMode) { 3877 return queryContactId(createRawContact(values, firstName, givenName, phoneNumber, email, 3878 presenceStatus, timesContacted, starred, groupId, chatMode)); 3879 } 3880 3881 private long createRawContact(ContentValues values, String firstName, String givenName, 3882 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 3883 long groupId, int chatMode) { 3884 long rawContactId = createRawContact(values, phoneNumber, email, presenceStatus, 3885 timesContacted, starred, groupId, chatMode); 3886 insertStructuredName(rawContactId, firstName, givenName); 3887 return rawContactId; 3888 } 3889 3890 private long createRawContact(ContentValues values, String phoneNumber, String email, 3891 int presenceStatus, int timesContacted, int starred, long groupId, int chatMode) { 3892 values.put(RawContacts.STARRED, starred); 3893 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 3894 values.put(RawContacts.CUSTOM_RINGTONE, "beethoven5"); 3895 values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 3896 values.put(RawContacts.TIMES_CONTACTED, timesContacted); 3897 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 3898 long rawContactId = ContentUris.parseId(rawContactUri); 3899 Uri photoUri = insertPhoto(rawContactId); 3900 long photoId = ContentUris.parseId(photoUri); 3901 values.put(Contacts.PHOTO_ID, photoId); 3902 insertPhoneNumber(rawContactId, phoneNumber); 3903 insertEmail(rawContactId, email); 3904 3905 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, email, presenceStatus, "hacking", 3906 chatMode); 3907 3908 if (groupId != 0) { 3909 insertGroupMembership(rawContactId, groupId); 3910 } 3911 return rawContactId; 3912 } 3913 3914 private void putDataValues(ContentValues values, long rawContactId) { 3915 values.put(Data.RAW_CONTACT_ID, rawContactId); 3916 values.put(Data.MIMETYPE, "testmimetype"); 3917 values.put(Data.RES_PACKAGE, "oldpackage"); 3918 values.put(Data.IS_PRIMARY, 1); 3919 values.put(Data.IS_SUPER_PRIMARY, 1); 3920 values.put(Data.DATA1, "one"); 3921 values.put(Data.DATA2, "two"); 3922 values.put(Data.DATA3, "three"); 3923 values.put(Data.DATA4, "four"); 3924 values.put(Data.DATA5, "five"); 3925 values.put(Data.DATA6, "six"); 3926 values.put(Data.DATA7, "seven"); 3927 values.put(Data.DATA8, "eight"); 3928 values.put(Data.DATA9, "nine"); 3929 values.put(Data.DATA10, "ten"); 3930 values.put(Data.DATA11, "eleven"); 3931 values.put(Data.DATA12, "twelve"); 3932 values.put(Data.DATA13, "thirteen"); 3933 values.put(Data.DATA14, "fourteen"); 3934 values.put(Data.DATA15, "fifteen"); 3935 values.put(Data.SYNC1, "sync1"); 3936 values.put(Data.SYNC2, "sync2"); 3937 values.put(Data.SYNC3, "sync3"); 3938 values.put(Data.SYNC4, "sync4"); 3939 } 3940} 3941 3942