LegacyContactsProviderTest.java revision fb362d1a5df250a49fad06db323b0d41fe0e3757
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 android.app.SearchManager; 20import android.content.ContentProvider; 21import android.content.ContentUris; 22import android.content.ContentValues; 23import android.database.Cursor; 24import android.net.Uri; 25import android.provider.Contacts; 26import android.provider.Contacts.ContactMethods; 27import android.provider.Contacts.Extensions; 28import android.provider.Contacts.GroupMembership; 29import android.provider.Contacts.Groups; 30import android.provider.Contacts.Intents; 31import android.provider.Contacts.Organizations; 32import android.provider.Contacts.People; 33import android.provider.Contacts.Phones; 34import android.provider.Contacts.Photos; 35import android.provider.Contacts.Presence; 36import android.test.suitebuilder.annotation.LargeTest; 37 38import java.io.IOException; 39 40/** 41 * Tests for legacy contacts APIs. 42 */ 43@LargeTest 44public class LegacyContactsProviderTest extends BaseContactsProvider2Test { 45 46 private static final boolean USE_LEGACY_PROVIDER = false; 47 48 @Override 49 protected Class<? extends ContentProvider> getProviderClass() { 50 return USE_LEGACY_PROVIDER ? ContactsProvider.class : SynchronousContactsProvider2.class; 51 } 52 53 @Override 54 protected String getAuthority() { 55 return Contacts.AUTHORITY; 56 } 57 58 public void testPeopleInsert() { 59 ContentValues values = new ContentValues(); 60 putContactValues(values); 61 62 Uri uri = mResolver.insert(People.CONTENT_URI, values); 63 assertStoredValues(uri, values); 64 assertSelection(People.CONTENT_URI, values, People._ID, ContentUris.parseId(uri)); 65 } 66 67 public void testPeopleDelete() { 68 ContentValues values = new ContentValues(); 69 values.put(People.NAME, "John Doe"); 70 Uri personId = mResolver.insert(People.CONTENT_URI, values); 71 mResolver.delete(personId, null, null); 72 73 Cursor c = mResolver.query(personId, null, People.NAME + "='John Doe'" , null, null); 74 assertEquals("Record count after deletion", 0, c.getCount()); 75 c.close(); 76 77 try { 78 mResolver.query(People.DELETED_CONTENT_URI, null, null, null, null); 79 } catch (UnsupportedOperationException e) { 80 // Expected exception 81 } 82 } 83 84 public void testPeopleFilter() { 85 ContentValues values = new ContentValues(); 86 values.put(People.NAME, "Deer Doe"); 87 mResolver.insert(People.CONTENT_URI, values); 88 89 values.clear(); 90 values.put(People.NAME, "Dear Dough"); 91 mResolver.insert(People.CONTENT_URI, values); 92 93 values.clear(); 94 values.put(People.NAME, "D.R. Dauwe"); 95 mResolver.insert(People.CONTENT_URI, values); 96 97 assertFilteredContacts("d", "Deer Doe", "Dear Dough", "D.R. Dauwe"); 98 assertFilteredContacts("de", "Deer Doe", "Dear Dough"); 99 assertFilteredContacts("dee", "Deer Doe"); 100 assertFilteredContacts("der"); 101 } 102 103 public void testDefaultDisplayName() { 104 ContentValues values = new ContentValues(); 105 values.put(People.NAME, "John Doe"); 106 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 107 assertStoredValues(personUri, People.DISPLAY_NAME, "John Doe"); 108 } 109 110 public void testPrimaryOrganization() { 111 ContentValues values = new ContentValues(); 112 final Uri personUri = mResolver.insert(People.CONTENT_URI, values); 113 long personId = ContentUris.parseId(personUri); 114 115 // Primary 116 values.clear(); 117 values.put(Organizations.ISPRIMARY, 1); 118 values.put(Organizations.COMPANY, "Google"); 119 values.put(Organizations.TYPE, Organizations.TYPE_WORK); 120 values.put(Organizations.PERSON_ID, personId); 121 Uri orgUri1 = mResolver.insert(Organizations.CONTENT_URI, values); 122 123 // Non-primary 124 values.clear(); 125 values.put(Organizations.COMPANY, "Acme"); 126 values.put(Organizations.TYPE, Organizations.TYPE_WORK); 127 values.put(Organizations.PERSON_ID, personId); 128 Uri orgUri2 = mResolver.insert(Organizations.CONTENT_URI, values); 129 130 values.clear(); 131 values.put(People.PRIMARY_ORGANIZATION_ID, ContentUris.parseId(orgUri1)); 132 values.put(People.DISPLAY_NAME, "Google"); 133 assertStoredValues(personUri, values); 134 135 // Remove the original primary organization 136 mResolver.delete(orgUri1, null, null); 137 138 values.clear(); 139 values.put(People.PRIMARY_ORGANIZATION_ID, ContentUris.parseId(orgUri2)); 140 values.put(People.DISPLAY_NAME, "Acme"); 141 assertStoredValues(personUri, values); 142 143 // Remove the remaining organization 144 mResolver.delete(orgUri2, null, null); 145 146 values.clear(); 147 values.putNull(People.PRIMARY_ORGANIZATION_ID); 148 values.putNull(People.DISPLAY_NAME); 149 assertStoredValues(personUri, values); 150 } 151 152 public void testPrimaryPhone() { 153 ContentValues values = new ContentValues(); 154 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 155 long personId = ContentUris.parseId(personUri); 156 157 // Primary 158 values.clear(); 159 values.put(Phones.ISPRIMARY, 1); 160 values.put(Phones.TYPE, Phones.TYPE_WORK); 161 values.put(Phones.PERSON_ID, personId); 162 values.put(Phones.NUMBER, "12345"); 163 Uri phoneUri1 = mResolver.insert(Phones.CONTENT_URI, values); 164 165 // Non-primary 166 values.clear(); 167 values.put(Phones.TYPE, Phones.TYPE_WORK); 168 values.put(Phones.PERSON_ID, personId); 169 values.put(Phones.NUMBER, "67890"); 170 Uri phoneUri2 = mResolver.insert(Phones.CONTENT_URI, values); 171 172 values.clear(); 173 values.put(People.PRIMARY_PHONE_ID, ContentUris.parseId(phoneUri1)); 174 values.put(People.DISPLAY_NAME, "12345"); 175 assertStoredValues(personUri, values); 176 177 // Remove the primary phone number 178 mResolver.delete(phoneUri1, null, null); 179 180 values.clear(); 181 values.put(People.PRIMARY_PHONE_ID, ContentUris.parseId(phoneUri2)); 182 values.put(People.DISPLAY_NAME, "67890"); 183 assertStoredValues(personUri, values); 184 185 // Remove the remaining phone number 186 mResolver.delete(phoneUri2, null, null); 187 188 values.clear(); 189 values.putNull(People.PRIMARY_PHONE_ID); 190 values.putNull(People.DISPLAY_NAME); 191 assertStoredValues(personUri, values); 192 } 193 194 public void testPrimaryEmail() { 195 ContentValues values = new ContentValues(); 196 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 197 long personId = ContentUris.parseId(personUri); 198 199 // Primary 200 values.clear(); 201 values.put(ContactMethods.PERSON_ID, personId); 202 values.put(ContactMethods.KIND, Contacts.KIND_EMAIL); 203 values.put(ContactMethods.TYPE, ContactMethods.TYPE_HOME); 204 values.put(ContactMethods.DATA, "foo@acme.com"); 205 values.put(ContactMethods.ISPRIMARY, 1); 206 Uri emailUri1 = mResolver.insert(ContactMethods.CONTENT_URI, values); 207 208 // Non-primary 209 values.clear(); 210 values.put(ContactMethods.PERSON_ID, personId); 211 values.put(ContactMethods.KIND, Contacts.KIND_EMAIL); 212 values.put(ContactMethods.TYPE, ContactMethods.TYPE_WORK); 213 values.put(ContactMethods.DATA, "bar@acme.com"); 214 Uri emailUri2 = mResolver.insert(ContactMethods.CONTENT_URI, values); 215 216 values.clear(); 217 values.put(People.PRIMARY_EMAIL_ID, ContentUris.parseId(emailUri1)); 218 values.put(People.DISPLAY_NAME, "foo@acme.com"); 219 assertStoredValues(personUri, values); 220 221 // Remove the primary email 222 mResolver.delete(emailUri1, null, null); 223 224 values.clear(); 225 values.put(People.PRIMARY_EMAIL_ID, ContentUris.parseId(emailUri2)); 226 values.put(People.DISPLAY_NAME, "bar@acme.com"); 227 assertStoredValues(personUri, values); 228 229 // Remove the remaining email 230 mResolver.delete(emailUri2, null, null); 231 232 values.clear(); 233 values.putNull(People.PRIMARY_EMAIL_ID); 234 values.putNull(People.DISPLAY_NAME); 235 assertStoredValues(personUri, values); 236 } 237 238 public void testMarkAsContacted() { 239 ContentValues values = new ContentValues(); 240 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 241 long personId = ContentUris.parseId(personUri); 242 243 int timesContactedBefore = 244 Integer.parseInt(getStoredValue(personUri, People.TIMES_CONTACTED)); 245 long timeBefore = System.currentTimeMillis(); 246 People.markAsContacted(mResolver, personId); 247 long timeAfter = System.currentTimeMillis(); 248 249 long lastContacted = Long.parseLong(getStoredValue(personUri, People.LAST_TIME_CONTACTED)); 250 int timesContactedAfter = 251 Integer.parseInt(getStoredValue(personUri, People.TIMES_CONTACTED)); 252 253 assertTrue(lastContacted >= timeBefore); 254 assertTrue(lastContacted <= timeAfter); 255 assertEquals(timesContactedAfter, timesContactedBefore + 1); 256 } 257 258 public void testOrganizationsInsert() { 259 ContentValues values = new ContentValues(); 260 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 261 long personId = ContentUris.parseId(personUri); 262 263 values.clear(); 264 values.put(Organizations.COMPANY, "Sierra"); 265 values.put(Organizations.PERSON_ID, personId); 266 values.put(Organizations.TYPE, Organizations.TYPE_CUSTOM); 267 values.put(Organizations.LABEL, "Club"); 268 values.put(Organizations.TITLE, "Member"); 269 values.put(Organizations.ISPRIMARY, 1); 270 271 Uri uri = mResolver.insert(Organizations.CONTENT_URI, values); 272 assertStoredValues(uri, values); 273 assertSelection(Organizations.CONTENT_URI, values, 274 Organizations._ID, ContentUris.parseId(uri)); 275 276 assertPersonIdConstraint(Organizations.CONTENT_URI, Organizations.TYPE, 277 Organizations.TYPE_WORK); 278 279 assertTypeAndLabelConstraints(Organizations.CONTENT_URI, Organizations.PERSON_ID, personId, 280 Organizations.TYPE, Organizations.TYPE_CUSTOM, Organizations.TYPE_OTHER, 281 Organizations.LABEL); 282 } 283 284 public void testPhonesInsert() { 285 ContentValues values = new ContentValues(); 286 putContactValues(values); 287 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 288 long personId = ContentUris.parseId(personUri); 289 290 values.clear(); 291 values.put(Phones.PERSON_ID, personId); 292 values.put(Phones.TYPE, Phones.TYPE_CUSTOM); 293 values.put(Phones.LABEL, "Directory"); 294 values.put(Phones.NUMBER, "1-800-4664-411"); 295 values.put(Phones.ISPRIMARY, 1); 296 297 Uri uri = mResolver.insert(Phones.CONTENT_URI, values); 298 299 // Adding another value to assert 300 values.put(Phones.NUMBER_KEY, "11446640081"); 301 302 // The result is joined with People 303 putContactValues(values); 304 assertStoredValues(uri, values); 305 assertSelection(Phones.CONTENT_URI, values, 306 Phones._ID, ContentUris.parseId(uri)); 307 308 // Access the phone through People 309 Uri twigUri = Uri.withAppendedPath(personUri, People.Phones.CONTENT_DIRECTORY); 310 assertStoredValues(twigUri, values); 311 312 // Now the person should be joined with Phone 313 values.clear(); 314 putContactValues(values); 315 values.put(People.TYPE, Phones.TYPE_CUSTOM); 316 values.put(People.LABEL, "Directory"); 317 values.put(People.NUMBER, "1-800-4664-411"); 318 assertStoredValues(personUri, values); 319 320 assertPersonIdConstraint(Phones.CONTENT_URI, Phones.TYPE, Phones.TYPE_WORK); 321 322 assertTypeAndLabelConstraints(Phones.CONTENT_URI, Phones.PERSON_ID, personId, Phones.TYPE, 323 Phones.TYPE_CUSTOM, Phones.TYPE_OTHER, Phones.LABEL); 324 } 325 326 public void testPhonesFilterQuery() { 327 ContentValues values = new ContentValues(); 328 putContactValues(values); 329 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 330 long personId = ContentUris.parseId(personUri); 331 332 values.clear(); 333 values.put(Phones.PERSON_ID, personId); 334 values.put(Phones.TYPE, Phones.TYPE_CUSTOM); 335 values.put(Phones.LABEL, "Directory"); 336 values.put(Phones.NUMBER, "1-800-4664-411"); 337 values.put(Phones.ISPRIMARY, 1); 338 339 Uri uri = mResolver.insert(Phones.CONTENT_URI, values); 340 341 Uri filterUri1 = Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, "8004664411"); 342 assertStoredValues(filterUri1, values); 343 344 Uri filterUri2 = Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, "7773334444"); 345 assertEquals(0, getCount(filterUri2, null, null)); 346 } 347 348 349 public void testEmailInsert() { 350 assertContactMethodInsert(Contacts.KIND_EMAIL, ContactMethods.TYPE_CUSTOM, 351 "Some other way", "foo@acme.com", null, true); 352 } 353 354 public void testImInsert() { 355 assertContactMethodInsert(Contacts.KIND_IM, ContactMethods.TYPE_CUSTOM, "Some other way", 356 "Foo", "Bar", true); 357 } 358 359 public void testPostalInsert() { 360 assertContactMethodInsert(Contacts.KIND_POSTAL, ContactMethods.TYPE_CUSTOM, 361 "Some other way", "Foo", "Bar", true); 362 } 363 364 private void assertContactMethodInsert(int kind, int type, String label, String data, 365 String auxData, boolean primary) { 366 ContentValues values = new ContentValues(); 367 putContactValues(values); 368 final Uri personUri = mResolver.insert(People.CONTENT_URI, values); 369 long personId = ContentUris.parseId(personUri); 370 371 values.clear(); 372 values.put(ContactMethods.PERSON_ID, personId); 373 values.put(ContactMethods.KIND, kind); 374 values.put(ContactMethods.TYPE, type); 375 values.put(ContactMethods.LABEL, label); 376 values.put(ContactMethods.DATA, data); 377 values.put(ContactMethods.AUX_DATA, auxData); 378 values.put(ContactMethods.ISPRIMARY, primary ? 1 : 0); 379 380 Uri uri = mResolver.insert(ContactMethods.CONTENT_URI, values); 381 382 // The result is joined with People 383 putContactValues(values); 384 assertStoredValues(uri, values); 385 assertSelection(ContactMethods.CONTENT_URI, values, 386 ContactMethods._ID, ContentUris.parseId(uri)); 387 388 // Access the contact method through People 389 Uri twigUri = Uri.withAppendedPath(personUri, People.ContactMethods.CONTENT_DIRECTORY); 390 assertStoredValues(twigUri, values); 391 392 assertPersonIdConstraint(ContactMethods.CONTENT_URI, ContactMethods.TYPE, 393 ContactMethods.TYPE_WORK); 394 395 assertTypeAndLabelConstraints(ContactMethods.CONTENT_URI, ContactMethods.PERSON_ID, 396 personId, ContactMethods.TYPE, ContactMethods.TYPE_CUSTOM, 397 ContactMethods.TYPE_OTHER, ContactMethods.LABEL); 398 } 399 400 public void testExtensionsInsert() { 401 ContentValues values = new ContentValues(); 402 final Uri personUri = mResolver.insert(People.CONTENT_URI, values); 403 long personId = ContentUris.parseId(personUri); 404 405 values.clear(); 406 values.put(Extensions.PERSON_ID, personId); 407 values.put(Extensions.NAME, "Foo"); 408 values.put(Extensions.VALUE, "Bar"); 409 410 Uri uri = mResolver.insert(Extensions.CONTENT_URI, values); 411 assertStoredValues(uri, values); 412 assertSelection(Extensions.CONTENT_URI, values, 413 Extensions._ID, ContentUris.parseId(uri)); 414 415 // Access the extensions through People 416 Uri twigUri = Uri.withAppendedPath(personUri, People.Extensions.CONTENT_DIRECTORY); 417 assertStoredValues(twigUri, values); 418 } 419 420 public void testGroupsInsert() { 421 ContentValues values = new ContentValues(); 422 values.put(Groups.NAME, "Galois"); 423 values.put(Groups.NOTES, "Abel"); 424 values.put(Groups.SYSTEM_ID, "12345"); 425 426 Uri groupUri = mResolver.insert(Groups.CONTENT_URI, values); 427 assertStoredValues(groupUri, values); 428 } 429 430 public void testGroupMembershipsInsert() { 431 ContentValues values = new ContentValues(); 432 values.put(Groups.NAME, "Galois"); 433 values.put(Groups.NOTES, "Abel"); 434 Uri groupUri = mResolver.insert(Groups.CONTENT_URI, values); 435 436 values.clear(); 437 values.put(People.NAME, "Klein"); 438 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 439 440 long groupId = ContentUris.parseId(groupUri); 441 long personId = ContentUris.parseId(personUri); 442 443 values.clear(); 444 values.put(GroupMembership.GROUP_ID, groupId); 445 values.put(GroupMembership.PERSON_ID, personId); 446 Uri membershipUri = mResolver.insert(GroupMembership.CONTENT_URI, values); 447 assertStoredValues(membershipUri, values); 448 assertSelection(GroupMembership.CONTENT_URI, values, 449 GroupMembership._ID, ContentUris.parseId(membershipUri)); 450 451 Uri personsGroupsUri = Uri.withAppendedPath(personUri, GroupMembership.CONTENT_DIRECTORY); 452 assertStoredValues(personsGroupsUri, values); 453 } 454 455 public void testAddToGroup() { 456 ContentValues values = new ContentValues(); 457 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 458 long personId = ContentUris.parseId(personUri); 459 460 values.clear(); 461 values.put(Groups.NAME, "Galois"); 462 Uri groupUri = mResolver.insert(Groups.CONTENT_URI, values); 463 464 People.addToGroup(mResolver, personId, "Galois"); 465 466 values.clear(); 467 values.put(GroupMembership.GROUP_ID, ContentUris.parseId(groupUri)); 468 values.put(GroupMembership.PERSON_ID, personId); 469 470 Uri personsGroupsUri = Uri.withAppendedPath(personUri, GroupMembership.CONTENT_DIRECTORY); 471 assertStoredValues(personsGroupsUri, values); 472 } 473 474 // TODO fix and reenable test 475 public void __testPresenceInsertMatchOnHandle() { 476 ContentValues values = new ContentValues(); 477 putContactValues(values); 478 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 479 long personId = ContentUris.parseId(personUri); 480 481 String encodedProtocol = 482 ContactMethods.encodePredefinedImProtocol(ContactMethods.PROTOCOL_GOOGLE_TALK); 483 484 values.clear(); 485 values.put(ContactMethods.PERSON_ID, personId); 486 values.put(ContactMethods.KIND, Contacts.KIND_IM); 487 values.put(ContactMethods.TYPE, ContactMethods.TYPE_HOME); 488 values.put(ContactMethods.DATA, "Android"); 489 values.put(ContactMethods.AUX_DATA, encodedProtocol); 490 mResolver.insert(ContactMethods.CONTENT_URI, values); 491 492 values.clear(); 493 values.put(Presence.IM_PROTOCOL, encodedProtocol); 494 values.put(Presence.IM_HANDLE, "Android"); 495 values.put(Presence.IM_ACCOUNT, "foo"); 496 values.put(Presence.PRESENCE_STATUS, Presence.OFFLINE); 497 values.put(Presence.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 498 499 Uri presenceUri = mResolver.insert(Presence.CONTENT_URI, values); 500 assertSelection(Presence.CONTENT_URI, values, 501 Presence._ID, ContentUris.parseId(presenceUri)); 502 503 values.put(Presence.PERSON_ID, personId); 504 assertStoredValues(presenceUri, values); 505 506 // Now the person should be joined with Presence 507 values.clear(); 508 putContactValues(values); 509 values.put(People.IM_PROTOCOL, encodedProtocol); 510 values.put(People.IM_HANDLE, "Android"); 511 values.put(People.IM_ACCOUNT, "foo"); 512 values.put(People.PRESENCE_STATUS, Presence.OFFLINE); 513 values.put(People.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 514 assertStoredValues(personUri, values); 515 } 516 517 // TODO fix and reenable test 518 public void __testPresenceInsertMatchOnEmail() { 519 ContentValues values = new ContentValues(); 520 putContactValues(values); 521 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 522 long personId = ContentUris.parseId(personUri); 523 524 String protocol = 525 ContactMethods.encodePredefinedImProtocol(ContactMethods.PROTOCOL_GOOGLE_TALK); 526 527 values.clear(); 528 values.put(ContactMethods.PERSON_ID, personId); 529 values.put(ContactMethods.KIND, Contacts.KIND_EMAIL); 530 values.put(ContactMethods.TYPE, ContactMethods.TYPE_HOME); 531 values.put(ContactMethods.DATA, "Android@android.com"); 532 mResolver.insert(ContactMethods.CONTENT_URI, values); 533 534 values.clear(); 535 values.put(Presence.IM_PROTOCOL, protocol); 536 values.put(Presence.IM_HANDLE, "Android@android.com"); 537 values.put(Presence.IM_ACCOUNT, "foo"); 538 values.put(Presence.PRESENCE_STATUS, Presence.OFFLINE); 539 values.put(Presence.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 540 541 Uri presenceUri = mResolver.insert(Presence.CONTENT_URI, values); 542 543 // FIXME person_id was not available in legacy ContactsProvider 544 // values.put(Presence.PERSON_ID, personId); 545 assertStoredValues(presenceUri, values); 546 assertSelection(Presence.CONTENT_URI, values, 547 Presence._ID, ContentUris.parseId(presenceUri)); 548 549 // Now the person should be joined with Presence 550 values.clear(); 551 putContactValues(values); 552 values.put(People.IM_PROTOCOL, protocol); 553 values.put(People.IM_HANDLE, "Android@android.com"); 554 values.put(People.IM_ACCOUNT, "foo"); 555 values.put(People.PRESENCE_STATUS, Presence.OFFLINE); 556 values.put(People.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 557 assertStoredValues(personUri, values); 558 } 559 560 public void testPhotoUpdate() throws Exception { 561 byte[] photo = loadTestPhoto(); 562 563 ContentValues values = new ContentValues(); 564 Uri personUri = mResolver.insert(People.CONTENT_URI, values); 565 566 values.clear(); 567 values.put(Photos.DATA, photo); 568 values.put(Photos.LOCAL_VERSION, "10"); 569 // FIXME this column was unavailable for update in legacy ContactsProvider 570 // values.put(Photos.DOWNLOAD_REQUIRED, 1); 571 values.put(Photos.EXISTS_ON_SERVER, 1); 572 values.put(Photos.SYNC_ERROR, "404 does not exist"); 573 574 Uri photoUri = Uri.withAppendedPath(personUri, Photos.CONTENT_DIRECTORY); 575 mResolver.update(photoUri, values, null, null); 576 assertStoredValues(photoUri, values); 577 } 578 579 /** 580 * Capturing the search suggestion requirements in test cases as a reference. 581 */ 582 public void testSearchSuggestionsNotInMyContacts() throws Exception { 583 584 // We don't provide compatibility for search suggestions 585 if (!USE_LEGACY_PROVIDER) { 586 return; 587 } 588 589 ContentValues values = new ContentValues(); 590 putContactValues(values); 591 mResolver.insert(People.CONTENT_URI, values); 592 593 Uri searchUri = new Uri.Builder().scheme("content").authority(Contacts.AUTHORITY) 594 .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("D").build(); 595 596 // If the contact is not in the "my contacts" group, nothing should be found 597 Cursor c = mResolver.query(searchUri, null, null, null, null); 598 assertEquals(0, c.getCount()); 599 c.close(); 600 } 601 602 /** 603 * Capturing the search suggestion requirements in test cases as a reference. 604 */ 605 public void testSearchSuggestionsByName() throws Exception { 606 607 // We don't provide compatibility for search suggestions 608 if (!USE_LEGACY_PROVIDER) { 609 return; 610 } 611 612 assertSearchSuggestion( 613 true, // name 614 true, // photo 615 true, // organization 616 false, // phone 617 false, // email 618 "D", // query 619 true, // expect icon URI 620 null, "Deer Dough", "Google"); 621 622 assertSearchSuggestion( 623 true, // name 624 true, // photo 625 false, // organization 626 true, // phone 627 false, // email 628 "D", // query 629 true, // expect icon URI 630 null, "Deer Dough", "1-800-4664-411"); 631 632 assertSearchSuggestion( 633 true, // name 634 true, // photo 635 false, // organization 636 false, // phone 637 true, // email 638 "D", // query 639 true, // expect icon URI 640 String.valueOf(Presence.getPresenceIconResourceId(Presence.OFFLINE)), 641 "Deer Dough", "foo@acme.com"); 642 643 assertSearchSuggestion( 644 true, // name 645 false, // photo 646 true, // organization 647 false, // phone 648 false, // email 649 "D", // query 650 false, // expect icon URI 651 null, "Deer Dough", "Google"); 652 } 653 654 private void assertSearchSuggestion(boolean name, boolean photo, boolean organization, 655 boolean phone, boolean email, String query, boolean expectIcon1Uri, String expectedIcon2, 656 String expectedText1, String expectedText2) throws IOException { 657 ContentValues values = new ContentValues(); 658 659 if (name) { 660 values.put(People.NAME, "Deer Dough"); 661 } 662 663 final Uri personUri = mResolver.insert(People.CONTENT_URI, values); 664 long personId = ContentUris.parseId(personUri); 665 666 People.addToMyContactsGroup(mResolver, personId); 667 668 if (photo) { 669 values.clear(); 670 byte[] photoData = loadTestPhoto(); 671 values.put(Photos.DATA, photoData); 672 values.put(Photos.LOCAL_VERSION, "1"); 673 values.put(Photos.EXISTS_ON_SERVER, 0); 674 Uri photoUri = Uri.withAppendedPath(personUri, Photos.CONTENT_DIRECTORY); 675 mResolver.update(photoUri, values, null, null); 676 } 677 678 if (organization) { 679 values.clear(); 680 values.put(Organizations.ISPRIMARY, 1); 681 values.put(Organizations.COMPANY, "Google"); 682 values.put(Organizations.TYPE, Organizations.TYPE_WORK); 683 values.put(Organizations.PERSON_ID, personId); 684 mResolver.insert(Organizations.CONTENT_URI, values); 685 } 686 687 if (email) { 688 values.clear(); 689 values.put(ContactMethods.PERSON_ID, personId); 690 values.put(ContactMethods.KIND, Contacts.KIND_EMAIL); 691 values.put(ContactMethods.TYPE, ContactMethods.TYPE_HOME); 692 values.put(ContactMethods.DATA, "foo@acme.com"); 693 values.put(ContactMethods.ISPRIMARY, 1); 694 mResolver.insert(ContactMethods.CONTENT_URI, values); 695 696 697 String protocol = ContactMethods 698 .encodePredefinedImProtocol(ContactMethods.PROTOCOL_GOOGLE_TALK); 699 values.clear(); 700 values.put(Presence.IM_PROTOCOL, protocol); 701 values.put(Presence.IM_HANDLE, "foo@acme.com"); 702 values.put(Presence.IM_ACCOUNT, "foo"); 703 values.put(Presence.PRESENCE_STATUS, Presence.OFFLINE); 704 values.put(Presence.PRESENCE_CUSTOM_STATUS, "Coding for Android"); 705 mResolver.insert(Presence.CONTENT_URI, values); 706 } 707 708 if (phone) { 709 values.clear(); 710 values.put(Phones.PERSON_ID, personId); 711 values.put(Phones.TYPE, Phones.TYPE_HOME); 712 values.put(Phones.NUMBER, "1-800-4664-411"); 713 values.put(Phones.ISPRIMARY, 1); 714 mResolver.insert(Phones.CONTENT_URI, values); 715 } 716 717 Uri searchUri = new Uri.Builder().scheme("content").authority(Contacts.AUTHORITY) 718 .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath(query).build(); 719 720 Cursor c = mResolver.query(searchUri, null, null, null, null); 721 assertEquals(1, c.getCount()); 722 c.moveToFirst(); 723 values.clear(); 724 725 String icon1 = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1)); 726 if (expectIcon1Uri) { 727 assertTrue(icon1.startsWith("content:")); 728 } else { 729 assertEquals(String.valueOf(com.android.internal.R.drawable.ic_contact_picture), icon1); 730 } 731 732 // SearchManager does not declare a constant for _id 733 values.put("_id", personId); 734 values.put(SearchManager.SUGGEST_COLUMN_ICON_2, expectedIcon2); 735 values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, personId); 736 values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, personId); 737 values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, expectedText1); 738 values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, expectedText2); 739 assertCursorValues(c, values); 740 c.close(); 741 742 // Cleanup 743 mResolver.delete(personUri, null, null); 744 } 745 746 /** 747 * Capturing the search suggestion requirements in test cases as a reference. 748 */ 749 public void testSearchSuggestionsByPhoneNumber() throws Exception { 750 751 // We don't provide compatibility for search suggestions 752 if (!USE_LEGACY_PROVIDER) { 753 return; 754 } 755 756 ContentValues values = new ContentValues(); 757 758 Uri searchUri = new Uri.Builder().scheme("content").authority(Contacts.AUTHORITY) 759 .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("12345").build(); 760 761 Cursor c = mResolver.query(searchUri, null, null, null, null); 762 assertEquals(2, c.getCount()); 763 c.moveToFirst(); 764 765 values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Execute"); 766 values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, ""); 767 values.put(SearchManager.SUGGEST_COLUMN_ICON_1, 768 String.valueOf(com.android.internal.R.drawable.call_contact)); 769 values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, 770 Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED); 771 values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345"); 772 values.putNull(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID); 773 assertCursorValues(c, values); 774 775 c.moveToNext(); 776 values.clear(); 777 values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Dial number"); 778 values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using 12345"); 779 values.put(SearchManager.SUGGEST_COLUMN_ICON_1, 780 String.valueOf(com.android.internal.R.drawable.create_contact)); 781 values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, 782 Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED); 783 values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345"); 784 values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, 785 SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT); 786 assertCursorValues(c, values); 787 c.close(); 788 } 789 790 private void putContactValues(ContentValues values) { 791 // Populating only unhidden columns 792 values.put(People.NAME, "Deer Dough"); 793 values.put(People.PHONETIC_NAME, "Dear Doe"); 794 values.put(People.NOTES, "Cash Cow"); 795 values.put(People.TIMES_CONTACTED, 3); 796 values.put(People.LAST_TIME_CONTACTED, 10); 797 values.put(People.CUSTOM_RINGTONE, "ringtone"); 798 values.put(People.SEND_TO_VOICEMAIL, 1); 799 values.put(People.STARRED, 1); 800 } 801 802 private void assertFilteredContacts(String filter, String... expectedNames) { 803 Uri filterUri = Uri.withAppendedPath(People.CONTENT_FILTER_URI, filter); 804 Cursor c = mResolver.query(filterUri, null, null, null, null); 805 try { 806 assertEquals("Record count", expectedNames.length, c.getCount()); 807 int column = c.getColumnIndex(People.NAME); 808 for (int i = 0; i < expectedNames.length; i++) { 809 c.moveToNext(); 810 assertEquals(expectedNames[i], c.getString(column)); 811 } 812 } finally { 813 c.close(); 814 } 815 } 816 817 private void assertPersonIdConstraint(Uri uri, String typeColumn, int defaultType) { 818 ContentValues values = new ContentValues(); 819 values.put(typeColumn, defaultType); 820 try { 821 mResolver.insert(uri, values); 822 fail("Inserted row without person ID"); 823 } catch (Exception e) { 824 // Exception expected 825 } 826 } 827 828 private void assertTypeAndLabelConstraints(Uri uri, String personIdColumn, long personId, 829 String typeColumn, int defaultType, int otherType, String labelColumn) { 830 ContentValues values = new ContentValues(); 831 values.put(personIdColumn, personId); 832 values.put(typeColumn, defaultType); 833 try { 834 mResolver.insert(uri, values); 835 fail("Inserted row with custom type but without label"); 836 } catch (Exception e) { 837 // Exception expected 838 } 839 840 values.clear(); 841 values.put(personIdColumn, personId); 842 try { 843 mResolver.insert(uri, values); 844 fail("Inserted row without either type or label"); 845 } catch (Exception e) { 846 // Exception expected 847 } 848 849 values.clear(); 850 values.put(personIdColumn, personId); 851 values.put(typeColumn, otherType); 852 values.put(labelColumn, "Foo"); 853 try { 854 mResolver.insert(uri, values); 855 fail("Inserted row with both type and label"); 856 } catch (Exception e) { 857 // Exception expected 858 } 859 } 860 861 @Override 862 protected void assertSelection(Uri uri, ContentValues values, String idColumn, long id) { 863 if (USE_LEGACY_PROVIDER) { 864 // A bug in the legacy ContactsProvider prevents us from using the 865 // _id column in selection. 866 super.assertSelection(uri, values, null, 0); 867 } else { 868 values.put(idColumn, id); 869 super.assertSelection(uri, values, idColumn, id); 870 } 871 } 872} 873