ContactsProvider2Test.java revision f1efadb1255fd75305b59802f736905b9d66e449
1d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov/* 2d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * Copyright (C) 2009 The Android Open Source Project 3d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * 4d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * you may not use this file except in compliance with the License. 6d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * You may obtain a copy of the License at 7d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * 8d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * 10d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * See the License for the specific language governing permissions and 14d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov * limitations under the License. 15d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov */ 168920a04b4a68ed6b548bcdef5ca8736dcf8b69b1Omari Stephens 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 18d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 19d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport com.android.common.contacts.DataUsageStatUpdater; 20b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.internal.util.ArrayUtils; 21d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 22d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns; 2370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 24d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikovimport com.android.providers.contacts.tests.R; 25d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikovimport com.google.android.collect.Lists; 26d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 27d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.accounts.Account; 289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintanaimport android.content.ContentProviderOperation; 2933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikovimport android.content.ContentProviderResult; 30d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.content.ContentUris; 31d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.content.ContentValues; 3233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikovimport android.content.Entity; 33c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.content.EntityIterator; 341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikovimport android.content.res.AssetFileDescriptor; 35d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.database.Cursor; 36ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 37c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.net.Uri; 389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintanaimport android.provider.ContactsContract; 395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 403cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 4309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 4433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 4562318e1ea8306142a10526534b7d83560ecf5b3aFred Quintanaimport android.provider.ContactsContract.CommonDataKinds.Photo; 46916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 4789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 4882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintanaimport android.provider.ContactsContract.Contacts; 509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintanaimport android.provider.ContactsContract.Data; 51bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millarimport android.provider.ContactsContract.DataUsageFeedback; 52916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 53a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaokaimport android.provider.ContactsContract.DisplayNameSources; 549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintanaimport android.provider.ContactsContract.DisplayPhoto; 558e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 564097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.Groups; 574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 587d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekhimport android.provider.ContactsContract.PhoneticNameStyle; 59d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.ContactsContract.Profile; 60d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.RawContactsEntity; 635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.Settings; 658920a04b4a68ed6b548bcdef5ca8736dcf8b69b1Omari Stephensimport android.provider.ContactsContract.StatusUpdates; 66d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.ContactsContract.StreamItemPhotos; 67d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.ContactsContract.StreamItems; 68d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.LiveFolders; 69d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.provider.OpenableColumns; 70d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport android.test.MoreAsserts; 718920a04b4a68ed6b548bcdef5ca8736dcf8b69b1Omari Stephensimport android.test.suitebuilder.annotation.LargeTest; 7228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport android.text.TextUtils; 73d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 74d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport java.io.FileInputStream; 75d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport java.io.IOException; 76d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport java.io.InputStream; 77d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikovimport java.io.OutputStream; 783cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport java.text.Collator; 793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport java.util.ArrayList; 803cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport java.util.Arrays; 813cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport java.util.List; 823cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport java.util.Locale; 833cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov 843cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov/** 853cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * Unit tests for {@link ContactsProvider2}. 863cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * 873cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * Run the test like this: 883cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * <code> 893cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * adb shell am instrument -e class com.android.providers.contacts.ContactsProvider2Test -w \ 903cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner 913cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov * </code> 923cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov */ 933cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov@LargeTest 943cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovpublic class ContactsProvider2Test extends BaseContactsProvider2Test { 953cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov 963cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov private static final Account ACCOUNT_1 = new Account("account_name_1", "account_type_1"); 973cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov private static final Account ACCOUNT_2 = new Account("account_name_2", "account_type_2"); 984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 993cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov public void testContactsProjection() { 1003cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov assertProjection(Contacts.CONTENT_URI, new String[]{ 1014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts._ID, 10281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Contacts.DISPLAY_NAME_PRIMARY, 1033cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE, 1043cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Contacts.DISPLAY_NAME_SOURCE, 1053cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Contacts.PHONETIC_NAME, 1064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHONETIC_NAME_STYLE, 1074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SORT_KEY_PRIMARY, 1084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE, 1094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LAST_TIME_CONTACTED, 1104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.TIMES_CONTACTED, 1114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.STARRED, 1124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.IN_VISIBLE_GROUP, 1134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_ID, 1144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_FILE_ID, 1154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_URI, 1164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_THUMBNAIL_URI, 1174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CUSTOM_RINGTONE, 1184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.HAS_PHONE_NUMBER, 1194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SEND_TO_VOICEMAIL, 1204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.IS_USER_PROFILE, 1214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LOOKUP_KEY, 1224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID, 1234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_PRESENCE, 1244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_CHAT_CAPABILITY, 1254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS, 1264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP, 1274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 1284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 12981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 1304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov }); 1313cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov } 13289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov 13389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov public void testContactsWithSnippetProjection() { 13489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov assertProjection(Contacts.CONTENT_FILTER_URI.buildUpon().appendPath("nothing").build(), 13589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov new String[]{ 13689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts._ID, 13789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.DISPLAY_NAME_PRIMARY, 13889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE, 13989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.DISPLAY_NAME_SOURCE, 14089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.PHONETIC_NAME, 14189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.PHONETIC_NAME_STYLE, 14289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.SORT_KEY_PRIMARY, 14389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE, 14489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.LAST_TIME_CONTACTED, 14589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Contacts.TIMES_CONTACTED, 1464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.STARRED, 1477d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh Contacts.IN_VISIBLE_GROUP, 1483cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Contacts.PHOTO_ID, 1494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_FILE_ID, 1504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_URI, 1514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_THUMBNAIL_URI, 1524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CUSTOM_RINGTONE, 1534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.HAS_PHONE_NUMBER, 1544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SEND_TO_VOICEMAIL, 1554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.IS_USER_PROFILE, 1564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LOOKUP_KEY, 1574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID, 1584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_PRESENCE, 1594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_CHAT_CAPABILITY, 1604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS, 1614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP, 1624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 1634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 1644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 1654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 1663cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov SearchSnippetColumns.SNIPPET, 1674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov }); 1684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 1694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 1704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov public void testRawContactsProjection() { 1714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertProjection(RawContacts.CONTENT_URI, new String[]{ 1724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts._ID, 1734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.CONTACT_ID, 1744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 1754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 1764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SOURCE_ID, 1774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.VERSION, 1784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.RAW_CONTACT_IS_USER_PROFILE, 17948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov RawContacts.DIRTY, 1804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DELETED, 1814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY, 1824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE, 1834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE, 1845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.PHONETIC_NAME, 1855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE, 1865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.NAME_VERIFIED, 1875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY, 1885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE, 1895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.TIMES_CONTACTED, 1905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED, 1914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.CUSTOM_RINGTONE, 1924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SEND_TO_VOICEMAIL, 1934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.STARRED, 1944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.AGGREGATION_MODE, 1955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.SYNC1, 1964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC2, 1974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC3, 1985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.SYNC4, 1994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov }); 2005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 2015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 2025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov public void testDataProjection() { 2035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov assertProjection(Data.CONTENT_URI, new String[]{ 2045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data._ID, 2055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.RAW_CONTACT_ID, 2065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA_VERSION, 2075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.IS_PRIMARY, 2084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 2094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.RES_PACKAGE, 210e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.MIMETYPE, 211e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA1, 212e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA2, 213e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA3, 214e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA4, 215e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA5, 216e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA6, 217e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA7, 218e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA8, 2194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA9, 2204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA10, 2214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA11, 222e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA12, 223e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA13, 224e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA14, 225e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.DATA15, 226e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.SYNC1, 227e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.SYNC2, 228e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.SYNC3, 229e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.SYNC4, 230e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Data.CONTACT_ID, 2314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.PRESENCE, 2324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.CHAT_CAPABILITY, 2334e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa Data.STATUS, 2344e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa Data.STATUS_TIMESTAMP, 2354e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa Data.STATUS_RES_PACKAGE, 2364e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa Data.STATUS_LABEL, 2374e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa Data.STATUS_ICON, 2384e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa RawContacts.ACCOUNT_NAME, 2394e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa RawContacts.ACCOUNT_TYPE, 2404e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa RawContacts.SOURCE_ID, 241e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov RawContacts.VERSION, 2424e3790e646bce315a1b34c9dc474eb8152c8eea2Daisuke Miyakawa RawContacts.DIRTY, 2434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.NAME_VERIFIED, 2444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.RAW_CONTACT_IS_USER_PROFILE, 245653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts._ID, 246653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.DISPLAY_NAME_PRIMARY, 247653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE, 248653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.DISPLAY_NAME_SOURCE, 249653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHONETIC_NAME, 250653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHONETIC_NAME_STYLE, 251653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.SORT_KEY_PRIMARY, 252653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE, 253653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.LAST_TIME_CONTACTED, 2545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.TIMES_CONTACTED, 255653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.STARRED, 256653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.IN_VISIBLE_GROUP, 257653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHOTO_ID, 258653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHOTO_FILE_ID, 259653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHOTO_URI, 260653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.PHOTO_THUMBNAIL_URI, 2615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CUSTOM_RINGTONE, 262653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.SEND_TO_VOICEMAIL, 263653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.LOOKUP_KEY, 264653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID, 265653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.HAS_PHONE_NUMBER, 266653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_PRESENCE, 267653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_CHAT_CAPABILITY, 268653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_STATUS, 269653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP, 270653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 271653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 272653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 273653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID, 2745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }); 27581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 276653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 277653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void testDistinctDataProjection() { 2784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertProjection(Phone.CONTENT_FILTER_URI.buildUpon().appendPath("123").build(), 2794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov new String[]{ 2804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data._ID, 2814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA_VERSION, 2824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.IS_PRIMARY, 2834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 2844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.RES_PACKAGE, 2854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.MIMETYPE, 2864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA1, 2874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA2, 2884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA3, 2894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA4, 2904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA5, 2914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA6, 2924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA7, 2934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA8, 2944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA9, 2954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA10, 2964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA11, 2974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA12, 2984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA13, 2994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA14, 3004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA15, 3014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC1, 3024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC2, 3034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC3, 3044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC4, 3054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.CONTACT_ID, 3064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.PRESENCE, 3074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.CHAT_CAPABILITY, 3084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS, 30948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov Data.STATUS_TIMESTAMP, 3104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_RES_PACKAGE, 3114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_LABEL, 3124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_ICON, 3135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov RawContacts.RAW_CONTACT_IS_USER_PROFILE, 3144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts._ID, 3154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.DISPLAY_NAME_PRIMARY, 3164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE, 3175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.DISPLAY_NAME_SOURCE, 3184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHONETIC_NAME, 3194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHONETIC_NAME_STYLE, 3204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SORT_KEY_PRIMARY, 3214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE, 3224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LAST_TIME_CONTACTED, 3234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.TIMES_CONTACTED, 3244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.STARRED, 3254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.IN_VISIBLE_GROUP, 32608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov Contacts.PHOTO_ID, 32708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov Contacts.PHOTO_FILE_ID, 32808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov Contacts.PHOTO_URI, 32908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov Contacts.PHOTO_THUMBNAIL_URI, 33008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov Contacts.HAS_PHONE_NUMBER, 3314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CUSTOM_RINGTONE, 3324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SEND_TO_VOICEMAIL, 3335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.LOOKUP_KEY, 3345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_PRESENCE, 3355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_CHAT_CAPABILITY, 3365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_STATUS, 3375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP, 3385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 3395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 3405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 3415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID, 3425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov }); 3435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 3445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov public void testEntityProjection() { 3465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov assertProjection( 3475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 0), 3485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.Entity.CONTENT_DIRECTORY), 3495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov new String[]{ 3505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.Entity._ID, 3515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.Entity.DATA_ID, 3525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Contacts.Entity.RAW_CONTACT_ID, 3535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA_VERSION, 3545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.IS_PRIMARY, 3555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 3561e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov Data.RES_PACKAGE, 3575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.MIMETYPE, 3585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA1, 3595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA2, 3605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA3, 3615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA4, 3625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Data.DATA5, 3634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA6, 3644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA7, 3654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA8, 3664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA9, 3674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA10, 3684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA11, 3694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA12, 3704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA13, 3714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA14, 3724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA15, 3734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC1, 3744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC2, 3754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC3, 3764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC4, 37748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov Data.CONTACT_ID, 37848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov Data.PRESENCE, 3794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.CHAT_CAPABILITY, 3804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS, 3814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_TIMESTAMP, 3824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_RES_PACKAGE, 3834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_LABEL, 3844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.STATUS_ICON, 38582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 3864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 3874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SOURCE_ID, 3884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.VERSION, 3894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DELETED, 3904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DIRTY, 3914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.NAME_VERIFIED, 3920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov RawContacts.SYNC1, 3934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC2, 3944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC3, 39582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov RawContacts.SYNC4, 39682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts._ID, 397ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.DISPLAY_NAME_PRIMARY, 398ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE, 399ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.DISPLAY_NAME_SOURCE, 4004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHONETIC_NAME, 4014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHONETIC_NAME_STYLE, 402ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.SORT_KEY_PRIMARY, 4034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE, 4044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LAST_TIME_CONTACTED, 40582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.TIMES_CONTACTED, 40682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.STARRED, 407ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP, 408ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.PHOTO_ID, 4094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_FILE_ID, 410ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.PHOTO_URI, 4114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.PHOTO_THUMBNAIL_URI, 4124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CUSTOM_RINGTONE, 4134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.SEND_TO_VOICEMAIL, 414ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.IS_USER_PROFILE, 4154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.LOOKUP_KEY, 4164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID, 41782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.HAS_PHONE_NUMBER, 4184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_PRESENCE, 4194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_CHAT_CAPABILITY, 42082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 4214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP, 4224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 42382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 4244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 4254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID, 42682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov }); 4274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 428ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov public void testRawEntityProjection() { 4304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertProjection(RawContactsEntity.CONTENT_URI, new String[]{ 4314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.Entity.DATA_ID, 4324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts._ID, 4334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.CONTACT_ID, 4344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 4354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 4364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SOURCE_ID, 4374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.VERSION, 4384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DIRTY, 439ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov RawContacts.NAME_VERIFIED, 4404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.DELETED, 4414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC1, 4424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC2, 4434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC3, 4444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.SYNC4, 4454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.STARRED, 4464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.RAW_CONTACT_IS_USER_PROFILE, 447ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Data.DATA_VERSION, 4484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.IS_PRIMARY, 4494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 4504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.RES_PACKAGE, 4514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.MIMETYPE, 45282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.DATA1, 4534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA2, 4544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA3, 4554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA4, 45682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.DATA5, 4574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA6, 458ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Data.DATA7, 4594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA8, 4604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA9, 4614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA10, 4624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA11, 4634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA12, 4644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA13, 465ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Data.DATA14, 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.DATA15, 4674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC1, 4684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC2, 4694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC3, 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Data.SYNC4, 471ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov GroupMembership.GROUP_SOURCE_ID, 4724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov }); 4734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4753cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov public void testPhoneLookupProjection() { 4763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov assertProjection(PhoneLookup.CONTENT_FILTER_URI.buildUpon().appendPath("123").build(), 4770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov new String[]{ 47819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup._ID, 47919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.LOOKUP_KEY, 48019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.DISPLAY_NAME, 48119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.LAST_TIME_CONTACTED, 48219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.TIMES_CONTACTED, 48319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.STARRED, 48419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.IN_VISIBLE_GROUP, 48519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.PHOTO_ID, 48619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.PHOTO_URI, 48719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.PHOTO_THUMBNAIL_URI, 48819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.CUSTOM_RINGTONE, 48919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.HAS_PHONE_NUMBER, 49019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov PhoneLookup.SEND_TO_VOICEMAIL, 49182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov PhoneLookup.NUMBER, 49282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov PhoneLookup.TYPE, 49382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov PhoneLookup.LABEL, 49482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov PhoneLookup.NORMALIZED_NUMBER, 49519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov }); 49619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 49782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 49819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov public void testGroupsProjection() { 499a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov assertProjection(Groups.CONTENT_URI, new String[]{ 500a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov Groups._ID, 50119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.ACCOUNT_NAME, 50219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.ACCOUNT_TYPE, 50319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SOURCE_ID, 50419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.DIRTY, 50519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.VERSION, 50682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Groups.RES_PACKAGE, 5070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Groups.TITLE, 50819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.TITLE_RES, 50919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.GROUP_VISIBLE, 51019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SYSTEM_ID, 511a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov Groups.DELETED, 51219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.NOTES, 51319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.ACTION, 51419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.ACTION_URI, 51519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SHOULD_SYNC, 51619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.FAVORITES, 51782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Groups.AUTO_ADD, 5180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Groups.GROUP_IS_READ_ONLY, 51919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SYNC1, 52019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SYNC2, 52119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov Groups.SYNC3, 522a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov Groups.SYNC4, 52319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov }); 52419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 52519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 52619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov public void testGroupsSummaryProjection() { 52719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov assertProjection(Groups.CONTENT_SUMMARY_URI, new String[]{ 52889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups._ID, 52989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.ACCOUNT_NAME, 53089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.ACCOUNT_TYPE, 53189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.SOURCE_ID, 53289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.DIRTY, 53389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.VERSION, 53489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.RES_PACKAGE, 53589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.TITLE, 53689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.TITLE_RES, 53789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.GROUP_VISIBLE, 53889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.SYSTEM_ID, 53989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.DELETED, 54089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Groups.NOTES, 5413cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.ACTION, 5423cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.ACTION_URI, 5433cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SHOULD_SYNC, 5443cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.FAVORITES, 5453cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.AUTO_ADD, 5463cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.GROUP_IS_READ_ONLY, 5473cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SYNC1, 5483cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SYNC2, 5493cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SYNC3, 5503cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SYNC4, 5513cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SUMMARY_COUNT, 5523cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Groups.SUMMARY_WITH_PHONES, 5533cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov }); 55494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 5553cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov 5563cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov public void testAggregateExceptionProjection() { 5573cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov assertProjection(AggregationExceptions.CONTENT_URI, new String[]{ 5583cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov AggregationExceptionColumns._ID, 5593cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov AggregationExceptions.TYPE, 5603cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1, 5613cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID2, 56273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov }); 5633cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov } 5643cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov 5653cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov public void testSettingsProjection() { 56689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov assertProjection(Settings.CONTENT_URI, new String[]{ 56789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.ACCOUNT_NAME, 56889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.ACCOUNT_TYPE, 56989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.UNGROUPED_VISIBLE, 57089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.SHOULD_SYNC, 57189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.ANY_UNSYNCED, 57289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.UNGROUPED_COUNT, 57389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov Settings.UNGROUPED_WITH_PHONES, 57489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov }); 57589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } 57689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov 57789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov public void testStatusUpdatesProjection() { 57889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov assertProjection(StatusUpdates.CONTENT_URI, new String[]{ 57989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov PresenceColumns.RAW_CONTACT_ID, 58089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov StatusUpdates.DATA_ID, 5814097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.IM_ACCOUNT, 582d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov StatusUpdates.IM_HANDLE, 5834097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.PROTOCOL, 5844097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.CUSTOM_PROTOCOL, 5855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov StatusUpdates.PRESENCE, 5864097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.CHAT_CAPABILITY, 587635a11c53a532d9b5aba5fd7c51a8d47dcb0aaf2Dmitri Plotnikov StatusUpdates.STATUS, 5884097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP, 5894097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 59067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov StatusUpdates.STATUS_ICON, 59167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov StatusUpdates.STATUS_LABEL, 59267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov }); 59367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 59467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 59567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov public void testLiveFoldersProjection() { 59667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov assertProjection( 597635a11c53a532d9b5aba5fd7c51a8d47dcb0aaf2Dmitri Plotnikov Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "live_folders/contacts"), 59867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov new String[]{ 59967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov LiveFolders._ID, 6004097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov LiveFolders.NAME, 601d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov }); 6024097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 6034097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 6044097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov public void testDirectoryProjection() { 6055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov assertProjection(Directory.CONTENT_URI, new String[]{ 6064097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov Directory._ID, 6075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Directory.PACKAGE_NAME, 6084097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov Directory.TYPE_RESOURCE_ID, 6094097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov Directory.DISPLAY_NAME, 6105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 6115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.ACCOUNT_TYPE, 6125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.ACCOUNT_NAME, 6135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.EXPORT_SUPPORT, 6145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.SHORTCUT_SUPPORT, 6155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Directory.PHOTO_SUPPORT, 6165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov }); 6175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 6185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testRawContactsInsert() { 6205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 6215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, "a"); 6235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, "b"); 6245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SOURCE_ID, "c"); 6255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.VERSION, 42); 6265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.DIRTY, 1); 6275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.DELETED, 1); 6285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 6295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 6305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 6315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 6325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.STARRED, 1); 6335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SYNC1, "e"); 6345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SYNC2, "f"); 6355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SYNC3, "g"); 6365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SYNC4, "h"); 6375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri rowUri = mResolver.insert(RawContacts.CONTENT_URI, values); 6395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId = ContentUris.parseId(rowUri); 6405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertStoredValues(rowUri, values); 6425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertSelection(RawContacts.CONTENT_URI, values, RawContacts._ID, rawContactId); 6435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertNetworkNotified(true); 6445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 6455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testDataDirectoryWithLookupUri() { 6475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 6485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId = createRawContactWithName(); 6505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertPhoneNumber(rawContactId, "555-GOOG-411"); 6515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertEmail(rawContactId, "google@android.com"); 6525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long contactId = queryContactId(rawContactId); 6545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String lookupKey = queryLookupKey(contactId); 6555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Complete and valid lookup URI 6575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); 6585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY); 6595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertDataRows(dataUri, values); 6615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Complete but stale lookup URI 6635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov lookupUri = ContactsContract.Contacts.getLookupUri(contactId + 1, lookupKey); 6645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY); 6655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertDataRows(dataUri, values); 6665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Incomplete lookup URI (lookup key only, no contact ID) 6685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov dataUri = Uri.withAppendedPath(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, 6694cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao lookupKey), Contacts.Data.CONTENT_DIRECTORY); 6704cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao assertDataRows(dataUri, values); 6715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 6725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void assertDataRows(Uri dataUri, ContentValues values) { 6745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Cursor cursor = mResolver.query(dataUri, new String[]{ Data.DATA1 }, null, null, Data._ID); 6755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertEquals(3, cursor.getCount()); 6765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.moveToFirst(); 6775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Data.DATA1, "John Doe"); 6785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertCursorValues(cursor, values); 6795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.moveToNext(); 6814cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao values.put(Data.DATA1, "555-GOOG-411"); 6824cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao assertCursorValues(cursor, values); 6835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.moveToNext(); 6855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Data.DATA1, "google@android.com"); 6865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertCursorValues(cursor, values); 6875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.close(); 6895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 6905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testContactEntitiesWithIdBasedUri() { 6925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 6935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Account account1 = new Account("act1", "actype1"); 6945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Account account2 = new Account("act2", "actype2"); 6955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 6965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId1 = createRawContactWithName(account1); 6975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertImHandle(rawContactId1, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 6985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", StatusUpdates.IDLE, "Busy", 90, 6995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA); 7005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId2 = createRawContact(account2); 7025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setAggregationException( 7035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 7045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long contactId = queryContactId(rawContactId1); 7065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 7085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY); 7095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 7115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 7125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testContactEntitiesWithLookupUri() { 7145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 7155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Account account1 = new Account("act1", "actype1"); 7165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Account account2 = new Account("act2", "actype2"); 7175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId1 = createRawContactWithName(account1); 7195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertImHandle(rawContactId1, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 7205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", StatusUpdates.IDLE, "Busy", 90, 7215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA); 7225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId2 = createRawContact(account2); 7245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setAggregationException( 7255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 7265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long contactId = queryContactId(rawContactId1); 7285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String lookupKey = queryLookupKey(contactId); 72925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 73025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov // First try with a matching contact ID 73125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Uri contactLookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); 73225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Uri entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 73325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 73425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 73525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov // Now try with a contact ID mismatch 7360c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov contactLookupUri = ContactsContract.Contacts.getLookupUri(contactId + 1, lookupKey); 7370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 73825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 73925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 74025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov // Now try without an ID altogether 74125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov contactLookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey); 74225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov entityUri = Uri.withAppendedPath(contactLookupUri, Contacts.Entity.CONTENT_DIRECTORY); 74325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov assertEntityRows(entityUri, contactId, rawContactId1, rawContactId2); 74481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 74525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 74625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void assertEntityRows(Uri entityUri, long contactId, long rawContactId1, 74701911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov long rawContactId2) { 74801911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov ContentValues values = new ContentValues(); 74901911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov 750a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Cursor cursor = mResolver.query(entityUri, null, null, null, 75101911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov Contacts.Entity.RAW_CONTACT_ID + "," + Contacts.Entity.DATA_ID); 75201911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov assertEquals(3, cursor.getCount()); 75301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov 75401911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov // First row - name 75501911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov cursor.moveToFirst(); 75601911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_ID, contactId); 75701911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId1); 75801911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 75901911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.DATA1, "John Doe"); 76001911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.ACCOUNT_NAME, "act1"); 76101911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.ACCOUNT_TYPE, "actype1"); 76201911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 76301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 764a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 765a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 766a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 7675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 76801911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov values.putNull(Contacts.Entity.PRESENCE); 76901911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov assertCursorValues(cursor, values); 770a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 771a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Second row - IM 772a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka cursor.moveToNext(); 773a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.CONTACT_ID, contactId); 774a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId1); 775a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.MIMETYPE, Im.CONTENT_ITEM_TYPE); 776a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.DATA1, "gtalk"); 777a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.ACCOUNT_NAME, "act1"); 778a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.ACCOUNT_TYPE, "actype1"); 779a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 7805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 7815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 7825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 7835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 7845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 7855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.PRESENCE, StatusUpdates.IDLE); 7865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertCursorValues(cursor, values); 7875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 7885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Third row - second raw contact, not data 7895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.moveToNext(); 7905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_ID, contactId); 7915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.RAW_CONTACT_ID, rawContactId2); 7925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.putNull(Contacts.Entity.MIMETYPE); 7935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.putNull(Contacts.Entity.DATA_ID); 7945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.putNull(Contacts.Entity.DATA1); 7955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.ACCOUNT_NAME, "act2"); 7965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.ACCOUNT_TYPE, "actype2"); 7975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.DISPLAY_NAME, "John Doe"); 7985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.DISPLAY_NAME_ALTERNATIVE, "Doe, John"); 7995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.NAME_RAW_CONTACT_ID, rawContactId1); 8005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 8015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_PRESENCE, StatusUpdates.IDLE); 8025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(Contacts.Entity.CONTACT_STATUS, "Busy"); 8035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.putNull(Contacts.Entity.PRESENCE); 8045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertCursorValues(cursor, values); 8055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov cursor.close(); 8075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 8085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testDataInsert() { 8105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId = createRawContactWithName("John", "Doe"); 8115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 8135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov putDataValues(values, rawContactId); 8145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 8155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long dataId = ContentUris.parseId(dataUri); 8165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long contactId = queryContactId(rawContactId); 8185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.CONTACT_ID, contactId); 8195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertStoredValues(dataUri, values); 8205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertSelection(Data.CONTENT_URI, values, Data._ID, dataId); 8225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Access the same data through the directory under RawContacts 8245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 8255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri rawContactDataUri = 8265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri.withAppendedPath(rawContactUri, RawContacts.Data.CONTENT_DIRECTORY); 8275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertSelection(rawContactDataUri, values, Data._ID, dataId); 8285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Access the same data through the directory under Contacts 8305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 8315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri contactDataUri = Uri.withAppendedPath(contactUri, Contacts.Data.CONTENT_DIRECTORY); 8325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertSelection(contactDataUri, values, Data._ID, dataId); 8330b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov assertNetworkNotified(true); 8340b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov } 8350b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov 8360b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov public void testRawContactDataQuery() { 8370b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Account account1 = new Account("a", "b"); 8380b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Account account2 = new Account("c", "d"); 8390b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov long rawContactId1 = createRawContact(account1); 8400b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Uri dataUri1 = insertStructuredName(rawContactId1, "John", "Doe"); 8410b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov long rawContactId2 = createRawContact(account2); 8420b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Uri dataUri2 = insertStructuredName(rawContactId2, "Jane", "Doe"); 8430b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov 8440b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Uri uri1 = maybeAddAccountQueryParameters(dataUri1, account1); 8450b1eaf562411ffec26fd9113c3209ebdd29202e1Dmitri Plotnikov Uri uri2 = maybeAddAccountQueryParameters(dataUri2, account2); 8465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertStoredValue(uri1, Data._ID, ContentUris.parseId(dataUri1)) ; 8475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov assertStoredValue(uri2, Data._ID, ContentUris.parseId(dataUri2)) ; 8485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 8495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void testPhonesQuery() { 8515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ContentValues values = new ContentValues(); 8535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 8545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 8555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 8565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.TIMES_CONTACTED, 54321); 8575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov values.put(RawContacts.STARRED, 1); 8585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 8595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 8605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov long rawContactId = ContentUris.parseId(rawContactUri); 8614cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 8624cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao insertStructuredName(rawContactId, "Meghan", "Knox"); 8635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Uri uri = insertPhoneNumber(rawContactId, "18004664411"); 86401911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov long phoneId = ContentUris.parseId(uri); 86501911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov 86631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 86731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov long contactId = queryContactId(rawContactId); 86831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.clear(); 86931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Data._ID, phoneId); 87031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 87131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(RawContacts.CONTACT_ID, contactId); 87231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 87331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Phone.NUMBER, "18004664411"); 87431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Phone.TYPE, Phone.TYPE_HOME); 87531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.putNull(Phone.LABEL); 87631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 87731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.CUSTOM_RINGTONE, "d"); 87831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.SEND_TO_VOICEMAIL, 1); 87931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.LAST_TIME_CONTACTED, 12345); 88031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.TIMES_CONTACTED, 54321); 88131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.STARRED, 1); 88231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 88331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertStoredValues(ContentUris.withAppendedId(Phone.CONTENT_URI, phoneId), values); 88431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertSelection(Phone.CONTENT_URI, values, Data._ID, phoneId); 88531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 88631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 88731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov public void testPhonesFilterQuery() { 88831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov long rawContactId1 = createRawContactWithName("Hot", "Tamale", ACCOUNT_1); 88931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertPhoneNumber(rawContactId1, "1-800-466-4411"); 89031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 89131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov long rawContactId2 = createRawContactWithName("Chilled", "Guacamole", ACCOUNT_2); 89231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertPhoneNumber(rawContactId2, "1-800-466-5432"); 89331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 89431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "tamale"); 89531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov ContentValues values = new ContentValues(); 89631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 89731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 89831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Phone.NUMBER, "1-800-466-4411"); 89931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.put(Phone.TYPE, Phone.TYPE_HOME); 90031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov values.putNull(Phone.LABEL); 90131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertStoredValuesWithProjection(filterUri1, values); 90231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 90331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov Uri filterUri2 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1-800-GOOG-411"); 90431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertStoredValues(filterUri2, values); 90531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 90631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov Uri filterUri3 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "18004664"); 90731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertStoredValues(filterUri3, values); 90831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 90931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov Uri filterUri4 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "encilada"); 91031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertEquals(0, getCount(filterUri4, null, null)); 91131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 91231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov Uri filterUri5 = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "*"); 91331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov assertEquals(0, getCount(filterUri5, null, null)); 914916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 915916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 916916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov public void testPhoneLookup() { 917916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ContentValues values = new ContentValues(); 918916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 919916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 920916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 921916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 922916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov long rawContactId = ContentUris.parseId(rawContactUri); 923916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 9249c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov insertStructuredName(rawContactId, "Hot", "Tamale"); 925916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov insertPhoneNumber(rawContactId, "18004664411"); 926916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 927916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 928916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 929916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.clear(); 930916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup._ID, queryContactId(rawContactId)); 931916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 932916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup.NUMBER, "18004664411"); 933916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup.TYPE, Phone.TYPE_HOME); 934916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.putNull(PhoneLookup.LABEL); 935916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup.CUSTOM_RINGTONE, "d"); 936916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(PhoneLookup.SEND_TO_VOICEMAIL, 1); 937916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov assertStoredValues(lookupUri1, values); 938916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 939916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // In the context that 8004664411 is a valid number, "4664411" as a 940916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // call id should not match to "8004664411" 941916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "4664411"); 942916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov assertEquals(0, getCount(lookupUri2, null, null)); 9439c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 9449c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 945916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov public void testPhoneLookupUseCases() { 946916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ContentValues values = new ContentValues(); 947916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Uri rawContactUri; 948916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov long rawContactId; 949916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Uri lookupUri2; 950916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 951916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 952916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 953916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 954916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // International format in contacts 955916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 956916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov rawContactId = ContentUris.parseId(rawContactUri); 957916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 958916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov insertStructuredName(rawContactId, "Hot", "Tamale"); 959916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov insertPhoneNumber(rawContactId, "+1-650-861-0000"); 9609c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 961916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.clear(); 962916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 9639c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov // match with international format 9649c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0000"); 965916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov assertEquals(1, getCount(lookupUri2, null, null)); 966916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 967916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // match with national format 968916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0000"); 969916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov assertEquals(1, getCount(lookupUri2, null, null)); 970916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 971916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // National format in contacts 972916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.clear(); 973916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 974916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 975916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 976916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov rawContactId = ContentUris.parseId(rawContactUri); 977916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 978916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov insertStructuredName(rawContactId, "Hot1", "Tamale"); 9799c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov insertPhoneNumber(rawContactId, "650-861-0001"); 980916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 981916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov values.clear(); 982916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 983916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // match with international format 984916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0001"); 985dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov assertEquals(2, getCount(lookupUri2, null, null)); 986dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 987dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov // match with national format 988dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0001"); 989dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov assertEquals(2, getCount(lookupUri2, null, null)); 990dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 991dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov // Local format in contacts 992dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov values.clear(); 993dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 994dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 995dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 996dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov rawContactId = ContentUris.parseId(rawContactUri); 997dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 998dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov insertStructuredName(rawContactId, "Hot2", "Tamale"); 999dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov insertPhoneNumber(rawContactId, "861-0002"); 1000dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 1001dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov values.clear(); 1002dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 1003dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov // match with international format 1004dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "+1 650 861 0002"); 1005dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov assertEquals(1, getCount(lookupUri2, null, null)); 1006dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov 1007dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov // match with national format 1008dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "650 861 0002"); 1009dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov assertEquals(1, getCount(lookupUri2, null, null)); 1010dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov } 1011d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 1012d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public void testPhoneUpdate() { 1013d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov ContentValues values = new ContentValues(); 1014d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1015d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov long rawContactId = ContentUris.parseId(rawContactUri); 1016d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 1017d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov insertStructuredName(rawContactId, "Hot", "Tamale"); 1018d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Uri phoneUri = insertPhoneNumber(rawContactId, "18004664411"); 1019d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 1020d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Uri lookupUri1 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664411"); 1021d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov assertStoredValue(lookupUri1, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1022d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 1023d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov values.clear(); 1024d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov values.put(Phone.NUMBER, "18004664422"); 1025d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mResolver.update(phoneUri, values, null, null); 1026d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 1027d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Uri lookupUri2 = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "8004664422"); 1028d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1029c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 1030d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Setting number to null will remove the phone lookup record 1031d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.clear(); 1032d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.putNull(Phone.NUMBER); 1033d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov mResolver.update(phoneUri, values, null, null); 1034d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1035d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertEquals(0, getCount(lookupUri2, null, null)); 1036d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1037d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Let's restore that phone lookup record 1038d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.clear(); 1039d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Phone.NUMBER, "18004664422"); 1040c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mResolver.update(phoneUri, values, null, null); 1041d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov assertStoredValue(lookupUri2, PhoneLookup.DISPLAY_NAME, "Hot Tamale"); 1042d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertNetworkNotified(true); 1043d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov } 1044d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 104581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov public void testEmailsQuery() { 10468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov ContentValues values = new ContentValues(); 10478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values.put(RawContacts.CUSTOM_RINGTONE, "d"); 10488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 10498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values.put(RawContacts.LAST_TIME_CONTACTED, 12345); 1050d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(RawContacts.TIMES_CONTACTED, 54321); 1051d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(RawContacts.STARRED, 1); 1052d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 10533cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1054d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long rawContactId = ContentUris.parseId(rawContactUri); 1055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1056d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov insertStructuredName(rawContactId, "Meghan", "Knox"); 10573cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Uri uri = insertEmail(rawContactId, "meghan@acme.com"); 1058d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long emailId = ContentUris.parseId(uri); 1059d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1060d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov long contactId = queryContactId(rawContactId); 1061d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.clear(); 10620c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov values.put(Data._ID, emailId); 10630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 1064d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(RawContacts.CONTACT_ID, contactId); 1065d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1066d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Email.DATA, "meghan@acme.com"); 1067d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Email.TYPE, Email.TYPE_HOME); 1068d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.putNull(Email.LABEL); 1069d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "Meghan Knox"); 10703cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov values.put(Contacts.CUSTOM_RINGTONE, "d"); 1071d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Contacts.SEND_TO_VOICEMAIL, 1); 1072d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Contacts.LAST_TIME_CONTACTED, 12345); 1073d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.TIMES_CONTACTED, 54321); 10743cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov values.put(Contacts.STARRED, 1); 1075d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1076d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov assertStoredValues(ContentUris.withAppendedId(Email.CONTENT_URI, emailId), values); 1077d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertSelection(Email.CONTENT_URI, values, Data._ID, emailId); 1078d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 10790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 10800c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov public void testEmailsLookupQuery() { 1081d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov long rawContactId = createRawContactWithName("Hot", "Tamale"); 1082d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov insertEmail(rawContactId, "tamale@acme.com"); 10830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 1084d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "tamale@acme.com"); 1085d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov ContentValues values = new ContentValues(); 1086d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 10873cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1088d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Email.DATA, "tamale@acme.com"); 1089d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Email.TYPE, Email.TYPE_HOME); 1090d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.putNull(Email.LABEL); 10913cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov assertStoredValues(filterUri1, values); 1092d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1093d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "Ta<TaMale@acme.com>"); 1094d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertStoredValues(filterUri2, values); 1095d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 10960c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov Uri filterUri3 = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, "encilada@acme.com"); 10970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov assertEquals(0, getCount(filterUri3, null, null)); 1098d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1099d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 11000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov public void testEmailsFilterQuery() { 11010c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1 = createRawContactWithName("Hot", "Tamale", ACCOUNT_1); 1102d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov insertEmail(rawContactId1, "tamale@acme.com"); 11033cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov insertEmail(rawContactId1, "tamale@acme.com"); 1104d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1105d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov long rawContactId2 = createRawContactWithName("Hot", "Tamale", ACCOUNT_2); 1106d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov insertEmail(rawContactId2, "tamale@acme.com"); 110782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 11084dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tam"); 11090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues values = new ContentValues(); 11100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "Hot Tamale"); 11110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 11120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.put(Email.DATA, "tamale@acme.com"); 11130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.put(Email.TYPE, Email.TYPE_HOME); 11140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.putNull(Email.LABEL); 11150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesWithProjection(filterUri1, values); 11160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri2 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hot"); 11180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesWithProjection(filterUri2, values); 11190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri3 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "hot tamale"); 11210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesWithProjection(filterUri3, values); 11220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri4 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "tamale@acme"); 11240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesWithProjection(filterUri4, values); 11250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri5 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "encilada"); 11270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertEquals(0, getCount(filterUri5, null, null)); 11280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 11290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov /** 11310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * Tests if ContactsProvider2 returns addresses according to registration order. 11320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov */ 11330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov public void testEmailFilterDefaultSortOrder() { 11340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long rawContactId1 = createRawContact(); 11350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "address1@email.com"); 11360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "address2@email.com"); 11370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "address3@email.com"); 11380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v1 = new ContentValues(); 11390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v1.put(Email.ADDRESS, "address1@email.com"); 11400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v2 = new ContentValues(); 11410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v2.put(Email.ADDRESS, "address2@email.com"); 11420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v3 = new ContentValues(); 11430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v3.put(Email.ADDRESS, "address3@email.com"); 11440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address"); 11460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesOrderly(filterUri, new ContentValues[] { v1, v2, v3 }); 11470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 11480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov /** 11500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * Tests if ContactsProvider2 returns primary addresses before the other addresses. 11510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov */ 11520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov public void testEmailFilterPrimaryAddress() { 11530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long rawContactId1 = createRawContact(); 11540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "address1@email.com"); 11550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "address2@email.com", true); 11560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v1 = new ContentValues(); 11570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v1.put(Email.ADDRESS, "address1@email.com"); 11580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v2 = new ContentValues(); 11590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v2.put(Email.ADDRESS, "address2@email.com"); 11600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address"); 11620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov assertStoredValuesOrderly(filterUri, new ContentValues[] { v2, v1 }); 11630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 11640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov /** 11660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * Tests if ContactsProvider2 has email address associated with a primary account before the 11670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * other address. 11680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov */ 11690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov public void testEmailFilterPrimaryAccount() { 11700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long rawContactId1 = createRawContact(ACCOUNT_1); 11710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId1, "account1@email.com"); 11720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long rawContactId2 = createRawContact(ACCOUNT_2); 11730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov insertEmail(rawContactId2, "account2@email.com"); 11740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v1 = new ContentValues(); 11750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v1.put(Email.ADDRESS, "account1@email.com"); 11760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov ContentValues v2 = new ContentValues(); 11770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v2.put(Email.ADDRESS, "account2@email.com"); 11780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 11790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Uri filterUri1 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("acc") 11800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME, ACCOUNT_1.name) 11810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE, ACCOUNT_1.type) 11820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov .build(); 11834dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov assertStoredValuesOrderly(filterUri1, new ContentValues[] { v1, v2 }); 11844dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 118582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Uri filterUri2 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("acc") 11864dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME, ACCOUNT_2.name) 11874dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE, ACCOUNT_2.type) 118882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .build(); 11894dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov assertStoredValuesOrderly(filterUri2, new ContentValues[] { v2, v1 }); 11904dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 119182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // Just with PRIMARY_ACCOUNT_NAME 11924dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov Uri filterUri3 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("acc") 11934dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME, ACCOUNT_1.name) 119482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .build(); 11954dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov assertStoredValuesOrderly(filterUri3, new ContentValues[] { v1, v2 }); 11964dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 119782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Uri filterUri4 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("acc") 11984dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov .appendQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME, ACCOUNT_2.name) 119982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .build(); 120082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri4, new ContentValues[] { v2, v1 }); 12010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 120282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 12034dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov /** Tests {@link DataUsageFeedback} correctly promotes a data row instead of a raw contact. */ 120482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public void testEmailFilterSortOrderWithFeedback() { 12054dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov long rawContactId1 = createRawContact(); 120682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String address1 = "address1@email.com"; 12074dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov insertEmail(rawContactId1, address1); 120882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long rawContactId2 = createRawContact(); 12094dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String address2 = "address2@email.com"; 12104dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov insertEmail(rawContactId2, address2); 1211bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov String address3 = "address3@email.com"; 1212bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov ContentUris.parseId(insertEmail(rawContactId2, address3)); 1213bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 1214bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov ContentValues v1 = new ContentValues(); 1215bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov v1.put(Email.ADDRESS, "address1@email.com"); 121682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov ContentValues v2 = new ContentValues(); 12170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov v2.put(Email.ADDRESS, "address2@email.com"); 1218bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov ContentValues v3 = new ContentValues(); 1219bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov v3.put(Email.ADDRESS, "address3@email.com"); 1220bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 122182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address"); 1222bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov Uri filterUri2 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("address") 1223bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 1224bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov DataUsageFeedback.USAGE_TYPE_CALL) 1225bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov .build(); 1226bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov Uri filterUri3 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("address") 1227bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 1228bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov DataUsageFeedback.USAGE_TYPE_LONG_TEXT) 122982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .build(); 123082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Uri filterUri4 = Email.CONTENT_FILTER_URI.buildUpon().appendPath("address") 1231bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 1232bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov DataUsageFeedback.USAGE_TYPE_SHORT_TEXT) 123382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .build(); 123482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri1, new ContentValues[] { v1, v2, v3 }); 123582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri2, new ContentValues[] { v1, v2, v3 }); 123682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri3, new ContentValues[] { v1, v2, v3 }); 123782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri4, new ContentValues[] { v1, v2, v3 }); 1238bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 123982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sendFeedback(address3, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, v3); 124082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 1241bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov // account3@email.com should be the first. account2@email.com should also be promoted as 1242bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov // it has same contact id. 12439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori assertStoredValuesOrderly(filterUri1, new ContentValues[] { v3, v1, v2 }); 12449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori assertStoredValuesOrderly(filterUri3, new ContentValues[] { v3, v1, v2 }); 12459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 12469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 12489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Tests {@link DataUsageFeedback} correctly bucketize contacts using each 12499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * {@link DataUsageStatColumns#LAST_TIME_USED} 12509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 12519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori public void testEmailFilterSortOrderWithOldHistory() { 12529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long rawContactId1 = createRawContact(); 12539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long dataId1 = ContentUris.parseId(insertEmail(rawContactId1, "address1@email.com")); 12549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long dataId2 = ContentUris.parseId(insertEmail(rawContactId1, "address2@email.com")); 12559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long dataId3 = ContentUris.parseId(insertEmail(rawContactId1, "address3@email.com")); 12569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long dataId4 = ContentUris.parseId(insertEmail(rawContactId1, "address4@email.com")); 12579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address"); 12599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues v1 = new ContentValues(); 12619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori v1.put(Email.ADDRESS, "address1@email.com"); 12629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues v2 = new ContentValues(); 12639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori v2.put(Email.ADDRESS, "address2@email.com"); 12649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues v3 = new ContentValues(); 12659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori v3.put(Email.ADDRESS, "address3@email.com"); 12669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues v4 = new ContentValues(); 12679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori v4.put(Email.ADDRESS, "address4@email.com"); 12689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori final ContactsProvider2 provider = (ContactsProvider2) getProvider(); 12709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long nowInMillis = System.currentTimeMillis(); 12729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long yesterdayInMillis = (nowInMillis - 24 * 60 * 60 * 1000); 12739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long sevenDaysAgoInMillis = (nowInMillis - 7 * 24 * 60 * 60 * 1000); 12749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori long oneYearAgoInMillis = (nowInMillis - 365L * 24 * 60 * 60 * 1000); 12759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // address4 is contacted just once yesterday. 12779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori provider.updateDataUsageStat(Arrays.asList(dataId4), 12789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DataUsageFeedback.USAGE_TYPE_LONG_TEXT, yesterdayInMillis); 12799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // address3 is contacted twice 1 week ago. 12819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori provider.updateDataUsageStat(Arrays.asList(dataId3), 12829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis); 12839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori provider.updateDataUsageStat(Arrays.asList(dataId3), 12849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis); 12859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 12869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // address2 is contacted three times 1 year ago. 128782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov provider.updateDataUsageStat(Arrays.asList(dataId2), 12889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis); 128982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov provider.updateDataUsageStat(Arrays.asList(dataId2), 1290a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis); 1291a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov provider.updateDataUsageStat(Arrays.asList(dataId2), 1292a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis); 129382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 1294a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // auto-complete should prefer recently contacted methods 1295a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov assertStoredValuesOrderly(filterUri1, new ContentValues[] { v4, v3, v2, v1 }); 1296a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1297a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Pretend address2 is contacted right now 1298a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov provider.updateDataUsageStat(Arrays.asList(dataId2), 1299a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis); 130082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 130182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // Now address2 is the most recently used address 130282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v4, v3, v1 }); 1303a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1304a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Pretend address1 is contacted right now 1305a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov provider.updateDataUsageStat(Arrays.asList(dataId1), 130682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis); 130782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 1308bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov // address2 is preferred to address1 as address2 is used 4 times in total 13094dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v1, v4, v3 }); 13104dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 131182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 131282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public void testPostalsQuery() { 13134dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov long rawContactId = createRawContactWithName("Alice", "Nextore"); 131482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Uri dataUri = insertPostalAddress(rawContactId, "1600 Amphiteatre Ave, Mountain View"); 131582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long dataId = ContentUris.parseId(dataUri); 131682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 131782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long contactId = queryContactId(rawContactId); 13184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov ContentValues values = new ContentValues(); 13194dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov values.put(Data._ID, dataId); 13204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 132182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.put(RawContacts.CONTACT_ID, contactId); 1322bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar values.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); 1323bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar values.put(StructuredPostal.FORMATTED_ADDRESS, "1600 Amphiteatre Ave, Mountain View"); 1324bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar values.put(Contacts.DISPLAY_NAME, "Alice Nextore"); 1325d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 13264dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov assertStoredValues(ContentUris.withAppendedId(StructuredPostal.CONTENT_URI, dataId), 1327bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar values); 132882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertSelection(StructuredPostal.CONTENT_URI, values, Data._ID, dataId); 132982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 133082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 1331bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar public void testQueryContactData() { 1332af088aeb51685eed17580edc04b495d12232ecf9Dmitri Plotnikov ContentValues values = new ContentValues(); 133382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long contactId = createContact(values, "John", "Doe", 13344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 1335bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 1336bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 133782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 133882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov assertStoredValues(contactUri, values); 13390265a180cf027d149f11f8750652ac67ea08ca24Dmitri Plotnikov assertSelection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 1340bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } 1341bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar 1342d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void testQueryContactWithStatusUpdate() { 1343d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov ContentValues values = new ContentValues(); 1344d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov long contactId = createContact(values, "John", "Doe", 1345d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 1346d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA); 1347d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 1348d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA); 1349d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 1350d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov assertStoredValuesWithProjection(contactUri, values); 1351d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertSelectionWithProjection(Contacts.CONTENT_URI, values, Contacts._ID, contactId); 1352d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 13538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 13548c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov public void testQueryContactFilterByName() { 13558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov ContentValues values = new ContentValues(); 13568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long rawContactId = createRawContact(values, "18004664411", 13578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 13588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 13598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_VOICE); 13608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 13618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov ContentValues nameValues = new ContentValues(); 13628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov nameValues.put(StructuredName.GIVEN_NAME, "Stu"); 13638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov nameValues.put(StructuredName.FAMILY_NAME, "Goulash"); 13648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov nameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "goo"); 13658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov nameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "LASH"); 1366d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov Uri nameUri = insertStructuredName(rawContactId, nameValues); 1367d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1368d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = queryContactId(rawContactId); 1369d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 1370d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1371d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goulash"); 1372d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov assertStoredValuesWithProjection(filterUri1, values); 1373d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1374d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov assertContactFilter(contactId, "goolash"); 1375d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertContactFilter(contactId, "lash"); 1376d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1377d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertContactFilterNoResult("goolish"); 1378d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1379d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Phonetic name with given/family reversed should not match 1380d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov assertContactFilterNoResult("lashgoo"); 1381d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 13829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana nameValues.clear(); 13839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana nameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "ga"); 1384d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov nameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "losh"); 1385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 13869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana mResolver.update(nameUri, nameValues, null, null); 13879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 13889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "galosh"); 1389d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 13909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilterNoResult("goolish"); 13919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 1393d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void testQueryContactFilterByEmailAddress() { 13949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values = new ContentValues(); 1395d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long rawContactId = createRawContact(values, "18004664411", 13969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 13979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 13989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana StatusUpdates.CAPABILITY_HAS_VOICE); 1399d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 14009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana insertStructuredName(rawContactId, "James", "Bond"); 14019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long contactId = queryContactId(rawContactId); 1403d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 14049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goog411@acme.com"); 14069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValuesWithProjection(filterUri1, values); 1407d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 14089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "goog"); 14099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "goog411"); 14109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "goog411@"); 14119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "goog411@acme"); 14129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilter(contactId, "goog411@acme.com"); 14139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilterNoResult("goog411@acme.combo"); 14159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilterNoResult("goog411@le.com"); 14169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertContactFilterNoResult("goolish"); 14179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 14189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14190be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public void testQueryContactFilterByPhoneNumber() { 14200be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov ContentValues values = new ContentValues(); 14210be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = createRawContact(values, "18004664411", 14220be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 14230be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 14240be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov StatusUpdates.CAPABILITY_HAS_VOICE); 14250be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14260be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov insertStructuredName(rawContactId, "James", "Bond"); 14270be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14280be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long contactId = queryContactId(rawContactId); 14290be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 14300be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14310be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "18004664411"); 14320be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertStoredValuesWithProjection(filterUri1, values); 14330be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14340be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilter(contactId, "18004664411"); 14350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilter(contactId, "1800466"); 14360be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilter(contactId, "+18004664411"); 14370be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilter(contactId, "8004664411"); 14380be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14390be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilterNoResult("78004664411"); 14400be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilterNoResult("18004664412"); 14410be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov assertContactFilterNoResult("8884664411"); 14420be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 14430be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14440be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov /** 14450be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov * Checks ContactsProvider2 works well with strequent Uris. The provider should return starred 14460be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov * contacts and frequently used contacts. 14479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 14489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana public void testQueryContactStrequent() { 14499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values1 = new ContentValues(); 14509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final String email1 = "a@acme.com"; 14519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final int timesContacted1 = 0; 14529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values1, "Noah", "Tever", "18004664411", 14539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana email1, StatusUpdates.OFFLINE, timesContacted1, 0, 0, 14543cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 14553cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov final String phoneNumber2 = "18004664412"; 14563cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov ContentValues values2 = new ContentValues(); 14573cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov createContact(values2, "Sam", "Times", phoneNumber2, 14589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "b@acme.com", StatusUpdates.INVISIBLE, 3, 0, 0, 1459226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana StatusUpdates.CAPABILITY_HAS_CAMERA); 14609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values3 = new ContentValues(); 14619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final String phoneNumber3 = "18004664413"; 14629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final int timesContacted3 = 5; 14639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values3, "Lotta", "Calling", phoneNumber3, 14649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "c@acme.com", StatusUpdates.AWAY, timesContacted3, 0, 0, 1465226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana StatusUpdates.CAPABILITY_HAS_VIDEO); 14669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values4 = new ContentValues(); 14679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values4, "Fay", "Veritt", "18004664414", 14689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "d@acme.com", StatusUpdates.AVAILABLE, 0, 1, 0, 14699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana StatusUpdates.CAPABILITY_HAS_VIDEO | StatusUpdates.CAPABILITY_HAS_VOICE); 14703cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov 14719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Starred contacts should be returned. TIMES_CONTACTED should be ignored and only data 14729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // usage feedback should be used for "frequently contacted" listing. 14739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValues(Contacts.CONTENT_STREQUENT_URI, values4); 14749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 147562318e1ea8306142a10526534b7d83560ecf5b3aFred Quintana // Send feedback for the 3rd phone number, pretending we called that person via phone. 147662318e1ea8306142a10526534b7d83560ecf5b3aFred Quintana sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3); 147762318e1ea8306142a10526534b7d83560ecf5b3aFred Quintana 14789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // After the feedback, 3rd contact should be shown after starred one. 14799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI, 14809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana new ContentValues[] { values4, values3 }); 14816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov 14829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1); 14839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Twice. 14849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1); 14859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // After the feedback, 1st and 3rd contacts should be shown after starred one. 14879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI, 14889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana new ContentValues[] { values4, values1, values3 }); 14899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // With phone-only parameter, the 1st contact shouldn't be returned, since it is only 14919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // about email, not phone-call. 14929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Uri phoneOnlyStrequentUri = Contacts.CONTENT_STREQUENT_URI.buildUpon() 14939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana .appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true") 14949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana .build(); 14959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] { values4, values3 }); 14969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Send feedback for the 2rd phone number, pretending we send the person a SMS message. 14989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sendFeedback(phoneNumber2, DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, values1); 14999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 15006cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // SMS feedback shouldn't affect phone-only results. 15019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] { values4, values3 }); 15029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 15039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_STREQUENT_FILTER_URI, "fay"); 15049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana assertStoredValues(filterUri, values4); 15059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 15069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 15079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 15089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * Checks ContactsProvider2 works well with frequent Uri. The provider should return frequently 15099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * contacted person ordered by number of times contacted. 15109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 15119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana public void testQueryContactFrequent() { 15129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values1 = new ContentValues(); 15139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final String email1 = "a@acme.com"; 15149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values1, "Noah", "Tever", "18004664411", 15156cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov email1, StatusUpdates.OFFLINE, 0, 0, 0, 0); 15169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values2 = new ContentValues(); 15179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final String email2 = "b@acme.com"; 15189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values2, "Sam", "Times", "18004664412", 15199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana email2, StatusUpdates.INVISIBLE, 0, 0, 0, 0); 15209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values3 = new ContentValues(); 15219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana final String phoneNumber3 = "18004664413"; 15229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values3, "Lotta", "Calling", phoneNumber3, 15239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "c@acme.com", StatusUpdates.AWAY, 0, 0, 0, 0); 15249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues values4 = new ContentValues(); 15259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana createContact(values4, "Fay", "Veritt", "18004664414", 15269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "d@acme.com", StatusUpdates.AVAILABLE, 0, 1, 0, 0); 15279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 15289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1); 15299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 15303cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov assertStoredValues(Contacts.CONTENT_FREQUENT_URI, values1); 15319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 153220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Pretend email was sent to the address twice. 153320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov sendFeedback(email2, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values2); 1534d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sendFeedback(email2, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values2); 153520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 153620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertStoredValues(Contacts.CONTENT_FREQUENT_URI, new ContentValues[] {values2, values1}); 15375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 153820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Three times 153920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3); 154020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3); 154120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3); 154220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 154320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertStoredValues(Contacts.CONTENT_FREQUENT_URI, 154420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov new ContentValues[] {values3, values2, values1}); 154520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 154620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 154720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public void testQueryContactGroup() { 154820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov long groupId = createGroup(null, "testGroup", "Test Group"); 154920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 155020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov ContentValues values1 = new ContentValues(); 155120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov createContact(values1, "Best", "West", "18004664411", 155220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov "west@acme.com", StatusUpdates.OFFLINE, 0, 0, groupId, 155320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA); 155420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 155520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov ContentValues values2 = new ContentValues(); 155620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov createContact(values2, "Rest", "East", "18004664422", 155720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov "east@acme.com", StatusUpdates.AVAILABLE, 0, 0, 0, 155820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_VOICE); 155981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 156020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 156120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = mResolver.query(filterUri1, null, null, null, Contacts._ID); 156220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertEquals(1, c.getCount()); 156320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.moveToFirst(); 156420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertCursorValues(c, values1); 156520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 156620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 156720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Uri filterUri2 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Test Group"); 156820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c = mResolver.query(filterUri2, null, Contacts.DISPLAY_NAME + "=?", 156920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov new String[] { "Best West" }, Contacts._ID); 157020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertEquals(1, c.getCount()); 157120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 157220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 157320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Uri filterUri3 = Uri.withAppendedPath(Contacts.CONTENT_GROUP_URI, "Next Group"); 157420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c = mResolver.query(filterUri3, null, null, null, Contacts._ID); 157520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov assertEquals(0, c.getCount()); 157620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 157720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 157820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 157920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public void testQueryProfileRequiresReadPermission() { 15805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mActor.removePermissions("android.permission.READ_PROFILE"); 158120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 158281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov createBasicProfileContact(new ContentValues()); 158370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 158470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov // Queries for the profile should fail. 158570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov Cursor c = null; 158670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 158720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Case 1: Retrieving profile contact. 158820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 15895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov c = mResolver.query(Profile.CONTENT_URI, null, null, null, Contacts._ID); 159020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov fail("Querying for the profile without READ_PROFILE access should fail."); 159120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } catch (SecurityException expected) { 15925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } finally { 159333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (c != null) { 159481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov c.close(); 159533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 159620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 159789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov 159889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov // Case 2: Retrieving profile data. 159989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov try { 160089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov c = mResolver.query(Profile.CONTENT_URI.buildUpon().appendPath("data").build(), 160189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov null, null, null, Contacts._ID); 160289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov fail("Querying for the profile data without READ_PROFILE access should fail."); 160389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } catch (SecurityException expected) { 160489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } finally { 160589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov if (c != null) { 160689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov c.close(); 160789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } 160889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } 160989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov 161089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov // Case 3: Retrieving profile entities. 161189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov try { 161289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov c = mResolver.query(Profile.CONTENT_URI.buildUpon() 161389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov .appendPath("entities").build(), null, null, null, Contacts._ID); 161489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov fail("Querying for the profile entities without READ_PROFILE access should fail."); 161589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } catch (SecurityException expected) { 1616373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov } finally { 1617e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (c != null) { 16185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov c.close(); 161933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 16204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 162182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 162282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 1623a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov public void testQueryProfileByContactIdRequiresReadPermission() { 1624a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov long profileRawContactId = createBasicProfileContact(new ContentValues()); 162533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long profileContactId = queryContactId(profileRawContactId); 162633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 162782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mActor.removePermissions("android.permission.READ_PROFILE"); 16284dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 162933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov // A query for the profile contact by ID should fail. 163033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov Cursor c = null; 163133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov try { 16325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c = mResolver.query(ContentUris.withAppendedId(Contacts.CONTENT_URI, profileContactId), 163381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov null, null, null, Contacts._ID); 163433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov fail("Querying for the profile by contact ID without READ_PROFILE access should fail."); 1635e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } catch (SecurityException expected) { 163633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } finally { 163733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (c != null) { 163833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov c.close(); 163933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 164082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 16414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 1642a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov 164381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov public void testQueryProfileByRawContactIdRequiresReadPermission() { 1644a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov long profileRawContactId = createBasicProfileContact(new ContentValues()); 1645a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov 1646a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov // Remove profile read permission and attempt to retrieve the raw contact. 1647e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mActor.removePermissions("android.permission.READ_PROFILE"); 1648e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Cursor c = null; 1649a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov try { 1650a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov c = mResolver.query(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 1651a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov profileRawContactId), null, null, null, RawContacts._ID); 1652a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov fail("Querying for the raw contact profile without READ_PROFILE access should fail."); 1653a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov } catch (SecurityException expected) { 1654a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov } finally { 1655a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov if (c != null) { 1656e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey c.close(); 1657a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov } 1658a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov } 1659a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov } 166020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 16611fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana public void testQueryProfileRawContactRequiresReadPermission() { 1662e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong long profileRawContactId = createBasicProfileContact(new ContentValues()); 1663e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 1664e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong // Remove profile read permission and attempt to retrieve the profile's raw contact data. 1665e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong mActor.removePermissions("android.permission.READ_PROFILE"); 1666e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Cursor c = null; 166782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 166882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // Case 1: Retrieve the overall raw contact set for the profile. 1669e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong try { 1670e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong c = mResolver.query(Profile.CONTENT_RAW_CONTACTS_URI, null, null, null, null); 167182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov fail("Querying for the raw contact profile without READ_PROFILE access should fail."); 1672e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } catch (SecurityException expected) { 1673e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } finally { 1674e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (c != null) { 1675e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong c.close(); 1676e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 1677e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 1678e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 1679e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong // Case 2: Retrieve the raw contact profile data for the inserted raw contact ID. 1680e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong try { 1681e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong c = mResolver.query(ContentUris.withAppendedId( 16825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId).buildUpon() 1683e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong .appendPath("data").build(), null, null, null, null); 1684e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong fail("Querying for the raw profile data without READ_PROFILE access should fail."); 1685e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } catch (SecurityException expected) { 1686e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } finally { 1687e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (c != null) { 1688e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong c.close(); 1689e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 1690e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 1691e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 16925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // Case 3: Retrieve the raw contact profile entity for the inserted raw contact ID. 1693e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong try { 1694e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong c = mResolver.query(ContentUris.withAppendedId( 1695627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId).buildUpon() 169670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong .appendPath("entity").build(), null, null, null, null); 169770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong fail("Querying for the raw profile entities without READ_PROFILE access should fail."); 169870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } catch (SecurityException expected) { 169970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 170070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (c != null) { 170182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov c.close(); 170282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 170370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 170470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 170570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 170670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void testQueryProfileDataByDataIdRequiresReadPermission() { 170770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong createBasicProfileContact(new ContentValues()); 1708627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Cursor c = mResolver.query(Profile.CONTENT_URI.buildUpon().appendPath("data").build(), 170970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong new String[]{Data._ID, Data.MIMETYPE}, null, null, null); 171070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong assertEquals(4, c.getCount()); // Photo, phone, email, name. 171170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong c.moveToFirst(); 171270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong long profileDataId = c.getLong(0); 171370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong c.close(); 1714627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 171582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // Remove profile read permission and attempt to retrieve the data 171670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mActor.removePermissions("android.permission.READ_PROFILE"); 1717627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 1718627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c = mResolver.query(ContentUris.withAppendedId(Data.CONTENT_URI, profileDataId), 171970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong null, null, null, null); 172070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong fail("Querying for the data in the profile without READ_PROFILE access should fail."); 1721cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } catch (SecurityException expected) { 1722cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 1723cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov if (c != null) { 1724cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 1725cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 1726cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 1727cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 1728cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 1729cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov public void testQueryProfileDataRequiresReadPermission() { 1730cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov createBasicProfileContact(new ContentValues()); 1731cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 1732cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // Remove profile read permission and attempt to retrieve all profile data. 1733cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mActor.removePermissions("android.permission.READ_PROFILE"); 1734cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = null; 173573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov try { 173673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov c = mResolver.query(Profile.CONTENT_URI.buildUpon().appendPath("data").build(), 173773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov null, null, null, null); 173873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov fail("Querying for the data in the profile without READ_PROFILE access should fail."); 173973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } catch (SecurityException expected) { 174073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 1741e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (c != null) { 174273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov c.close(); 174373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 174473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 174573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 17465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 174773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov public void testInsertProfileRequiresWritePermission() { 174881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mActor.removePermissions("android.permission.WRITE_PROFILE"); 17491fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 17501fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana // Creating a non-profile contact should be fine. 175161d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov createBasicNonProfileContact(new ContentValues()); 1752d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1753d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Creating a profile contact should throw an exception. 175473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov try { 17551fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana createBasicProfileContact(new ContentValues()); 17561fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana fail("Creating a profile contact should fail without WRITE_PROFILE access."); 17571fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana } catch (SecurityException expected) { 17581fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana } 17591fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana } 176061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov 1761c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens public void testInsertProfileDataRequiresWritePermission() { 176261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov long profileRawContactId = createBasicProfileContact(new ContentValues()); 17631fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 17641fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana mActor.removePermissions("android.permission.WRITE_PROFILE"); 17651fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana try { 17661fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana insertEmail(profileRawContactId, "foo@bar.net", false); 176781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov fail("Inserting data into a profile contact should fail without WRITE_PROFILE access."); 17681fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana } catch (SecurityException expected) { 176961d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov } 177061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov } 177181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 17721fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana public void testUpdateDataDoesNotRequireProfilePermission() { 17731fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana mActor.removePermissions("android.permission.READ_PROFILE"); 177461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov mActor.removePermissions("android.permission.WRITE_PROFILE"); 17751fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 177661d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov // Create a non-profile contact. 177761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov long rawContactId = createRawContactWithName("Domo", "Arigato"); 177861d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov long dataId = getStoredLongValue(Data.CONTENT_URI, 17791fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?", 178081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov new String[]{String.valueOf(rawContactId), StructuredName.CONTENT_ITEM_TYPE}, 17811fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana Data._ID); 17821fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 178361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov // Updates its name using a selection. 17841fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana ContentValues values = new ContentValues(); 178561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, "Bob"); 17861fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana values.put(StructuredName.FAMILY_NAME, "Blob"); 178781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mResolver.update(Data.CONTENT_URI, values, Data._ID + "=?", 17881fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana new String[]{String.valueOf(dataId)}); 17891fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 179061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov // Check that the update went through. 17911fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana assertStoredValues(ContentUris.withAppendedId(Data.CONTENT_URI, dataId), values); 179261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov } 179361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov 179461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov public void testQueryContactIncludeProfile() { 179561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov ContentValues profileValues = new ContentValues(); 179661d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov long profileRawContactId = createBasicProfileContact(profileValues); 179761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov long profileContactId = queryContactId(profileRawContactId); 17981fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 179961d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov ContentValues nonProfileValues = new ContentValues(); 18001fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana long nonProfileRawContactId = createBasicNonProfileContact(nonProfileValues); 18011fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana long nonProfileContactId = queryContactId(nonProfileRawContactId); 18021fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 18031fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana Uri contactWithProfilesUri = Contacts.CONTENT_URI.buildUpon() 18041fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana .appendQueryParameter(ContactsContract.ALLOW_PROFILE, "1").build(); 18051fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana assertStoredValuesOrderly(contactWithProfilesUri, 18061fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana new ContentValues[]{profileValues, nonProfileValues}); 180761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov assertSelection(contactWithProfilesUri, profileValues, Contacts._ID, profileContactId); 180861d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov assertSelection(Contacts.CONTENT_URI, nonProfileValues, Contacts._ID, nonProfileContactId); 18091fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana } 181061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov 18111fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana public void testQueryContactExcludeProfile() { 181261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov // Create a profile contact (it should not be returned by the general contact URI). 181361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov createBasicProfileContact(new ContentValues()); 181461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov 181561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov // Create a non-profile contact - this should be returned. 18165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContentValues nonProfileValues = new ContentValues(); 181761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov createBasicNonProfileContact(nonProfileValues); 181881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 181961d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov assertStoredValues(Contacts.CONTENT_URI, new ContentValues[] {nonProfileValues}); 182061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov } 18211fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana 18224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov public void testQueryProfile() { 18239fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann ContentValues profileValues = new ContentValues(); 18249fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann createBasicProfileContact(profileValues); 18259fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 18269fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann assertStoredValues(Profile.CONTENT_URI, profileValues); 18279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 18289fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 18299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann private ContentValues[] getExpectedProfileDataValues() { 18309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // Expected photo data values (only field is the photo BLOB, which we can't check). 18319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann ContentValues photoRow = new ContentValues(); 18329fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann photoRow.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 18339fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 18349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // Expected phone data values. 18359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann ContentValues phoneRow = new ContentValues(); 18369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann phoneRow.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 18379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann phoneRow.put(Phone.NUMBER, "18005554411"); 18389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 18399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // Expected email data values. 18409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann ContentValues emailRow = new ContentValues(); 18419fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann emailRow.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 18429fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann emailRow.put(Email.ADDRESS, "mia.prophyl@acme.com"); 18439fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 18449fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // Expected name data values. 18459fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann ContentValues nameRow = new ContentValues(); 18469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann nameRow.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 18479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann nameRow.put(StructuredName.DISPLAY_NAME, "Mia Prophyl"); 18489fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann nameRow.put(StructuredName.GIVEN_NAME, "Mia"); 184960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann nameRow.put(StructuredName.FAMILY_NAME, "Prophyl"); 185060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 185160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann return new ContentValues[]{photoRow, phoneRow, emailRow, nameRow}; 185260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann } 185360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 185460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann public void testQueryProfileData() { 185560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann createBasicProfileContact(new ContentValues()); 185660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 185760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann assertStoredValues(Profile.CONTENT_URI.buildUpon().appendPath("data").build(), 185860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann getExpectedProfileDataValues()); 185960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann } 186060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 186160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann public void testQueryProfileEntities() { 186260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann createBasicProfileContact(new ContentValues()); 186360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 186460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann assertStoredValues(Profile.CONTENT_URI.buildUpon().appendPath("entities").build(), 186560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann getExpectedProfileDataValues()); 186660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann } 186760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 186860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann public void testQueryRawProfile() { 186960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann ContentValues profileValues = new ContentValues(); 187060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann createBasicProfileContact(profileValues); 187160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 187260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann // The raw contact view doesn't include the photo ID. 187360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann profileValues.remove(Contacts.PHOTO_ID); 187460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann assertStoredValues(Profile.CONTENT_RAW_CONTACTS_URI, profileValues); 1875074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov } 1876074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov 1877074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov public void testQueryRawProfileById() { 1878074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov ContentValues profileValues = new ContentValues(); 1879074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov long profileRawContactId = createBasicProfileContact(profileValues); 1880074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov 1881074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov // The raw contact view doesn't include the photo ID. 18823653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov profileValues.remove(Contacts.PHOTO_ID); 18838e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov assertStoredValues(ContentUris.withAppendedId( 1884074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId), profileValues); 18853653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 18863653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 1887074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov public void testQueryRawProfileData() { 1888074cf38e39d500e92fa851a171d0378ab2c528c2Dmitri Plotnikov long profileRawContactId = createBasicProfileContact(new ContentValues()); 1889732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1890732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov assertStoredValues(ContentUris.withAppendedId( 1891732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId).buildUpon() 1892732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov .appendPath("data").build(), getExpectedProfileDataValues()); 1893732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov } 1894732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1895732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov public void testQueryRawProfileEntity() { 1896732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov long profileRawContactId = createBasicProfileContact(new ContentValues()); 1897732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1898732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov assertStoredValues(ContentUris.withAppendedId( 1899732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId).buildUpon() 1900732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov .appendPath("entity").build(), getExpectedProfileDataValues()); 1901732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov } 1902732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1903732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov public void testQueryDataForProfile() { 1904732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov createBasicProfileContact(new ContentValues()); 1905732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1906732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov assertStoredValues(Profile.CONTENT_URI.buildUpon().appendPath("data").build(), 1907732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov getExpectedProfileDataValues()); 1908732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov } 1909732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1910732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov public void testPhonesWithStatusUpdate() { 1911732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov 1912732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov ContentValues values = new ContentValues(); 1913732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 1914732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov long rawContactId = ContentUris.parseId(rawContactUri); 1915732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov insertStructuredName(rawContactId, "John", "Doe"); 1916732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov Uri photoUri = insertPhoto(rawContactId); 1917732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov long photoId = ContentUris.parseId(photoUri); 1918732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov insertPhoneNumber(rawContactId, "18004664411"); 1919732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov insertPhoneNumber(rawContactId, "18004664412"); 1920732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov insertEmail(rawContactId, "goog411@acme.com"); 1921732961a5b936d316482f9ded6bfc5fe1c99a65c8Dmitri Plotnikov insertEmail(rawContactId, "goog412@acme.com"); 19228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog411@acme.com", 19248e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov StatusUpdates.INVISIBLE, "Bad", 19258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA); 19268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog412@acme.com", 19278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov StatusUpdates.AVAILABLE, "Good", 19288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VOICE); 19298e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = queryContactId(rawContactId); 19308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov Uri uri = Data.CONTENT_URI; 19328e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov Cursor c = mResolver.query(uri, null, RawContacts.CONTACT_ID + "=" + contactId + " AND " 19348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null, Phone.NUMBER); 19358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov assertEquals(2, c.getCount()); 19368e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19378e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov c.moveToFirst(); 19388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.clear(); 19408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 19418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.put(Contacts.CONTACT_STATUS, "Bad"); 19428e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME, "John Doe"); 194381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov values.put(Phone.NUMBER, "18004664411"); 19448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.putNull(Phone.LABEL); 19458e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov values.put(RawContacts.CONTACT_ID, contactId); 19468e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov assertCursorValues(c, values); 19478e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 19488e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov c.moveToNext(); 19494e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 19507d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.clear(); 19517d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 19527d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Contacts.CONTACT_STATUS, "Bad"); 19537d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Contacts.DISPLAY_NAME, "John Doe"); 19547d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Phone.NUMBER, "18004664412"); 19557d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.putNull(Phone.LABEL); 19567d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(RawContacts.CONTACT_ID, contactId); 19577d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh assertCursorValues(c, values); 19587d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 19597d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh c.close(); 19607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 19617d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 19627d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh public void testGroupQuery() { 19637d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh Account account1 = new Account("a", "b"); 19647d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh Account account2 = new Account("c", "d"); 19657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh long groupId1 = createGroup(account1, "e", "f"); 19667d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh long groupId2 = createGroup(account2, "g", "h"); 19677d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh Uri uri1 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account1); 19687d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh Uri uri2 = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account2); 19697d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh assertEquals(1, getCount(uri1, null, null)); 19707d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh assertEquals(1, getCount(uri2, null, null)); 19717d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh assertStoredValue(uri1, Groups._ID + "=" + groupId1, null, Groups._ID, groupId1) ; 19727d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh assertStoredValue(uri2, Groups._ID + "=" + groupId2, null, Groups._ID, groupId2) ; 19737d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 19747d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 19757d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh public void testGroupInsert() { 19767d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh ContentValues values = new ContentValues(); 19774e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 19787d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Groups.ACCOUNT_NAME, "a"); 19794e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.ACCOUNT_TYPE, "b"); 19807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Groups.SOURCE_ID, "c"); 19810265a180cf027d149f11f8750652ac67ea08ca24Dmitri Plotnikov values.put(Groups.VERSION, 42); 19827d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Groups.GROUP_VISIBLE, 1); 19837d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh values.put(Groups.TITLE, "d"); 19844e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.TITLE_RES, 1234); 19854e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.NOTES, "e"); 19864e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.RES_PACKAGE, "f"); 19874e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.SYSTEM_ID, "g"); 19884e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.DELETED, 1); 19894e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.SYNC1, "h"); 19904e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.SYNC2, "i"); 19914e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.SYNC3, "j"); 19924e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.SYNC4, "k"); 19934e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 19944e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov Uri rowUri = mResolver.insert(Groups.CONTENT_URI, values); 19954e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 19964e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov values.put(Groups.DIRTY, 1); 19974e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov assertStoredValues(rowUri, values); 19984e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov } 19994e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 20004e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov public void testGroupCreationAfterMembershipInsert() { 20014e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov long rawContactId1 = createRawContact(mAccount); 20024e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 20034e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 20044e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov long groupId = assertSingleGroup(NO_LONG, mAccount, "gsid1", null); 20054e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 20064e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov rawContactId1, groupId, "gsid1"); 20074e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov } 20084e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 20094e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov public void testGroupReuseAfterMembershipInsert() { 20104e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov long rawContactId1 = createRawContact(mAccount); 20114e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov long groupId1 = createGroup(mAccount, "gsid1", "title1"); 20124e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov Uri groupMembershipUri = insertGroupMembership(rawContactId1, "gsid1"); 20134e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 20144e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov assertSingleGroup(groupId1, mAccount, "gsid1", "title1"); 20154e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov assertSingleGroupMembership(ContentUris.parseId(groupMembershipUri), 20164e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov rawContactId1, groupId1, "gsid1"); 20174e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov } 20184e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov 20194e8ced99f8bbb01abd610a6ca60afcabb6ffe737Dmitri Plotnikov public void testGroupInsertFailureOnGroupIdConflict() { 20201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov long rawContactId1 = createRawContact(mAccount); 20211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov long groupId1 = createGroup(mAccount, "gsid1", "title1"); 20221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov ContentValues values = new ContentValues(); 20241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov values.put(GroupMembership.RAW_CONTACT_ID, rawContactId1); 20251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov values.put(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 20261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov values.put(GroupMembership.GROUP_SOURCE_ID, "gsid1"); 20271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId1); 20281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov try { 20291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov mResolver.insert(Data.CONTENT_URI, values); 20301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov fail("the insert was expected to fail, but it succeeded"); 20311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } catch (IllegalArgumentException e) { 20321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // this was expected 20331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 20341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 20351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov public void testGroupSummaryQuery() { 20371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final Account account1 = new Account("accountName1", "accountType1"); 20381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final Account account2 = new Account("accountName2", "accountType2"); 20391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long groupId1 = createGroup(account1, "sourceId1", "title1"); 20401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long groupId2 = createGroup(account2, "sourceId2", "title2"); 20411b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long groupId3 = createGroup(account2, "sourceId3", "title3"); 20421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Prepare raw contact id not used at all, to test group summary uri won't be confused 20441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // with it. 20451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long rawContactId0 = createRawContactWithName("firstName0", "lastName0"); 20461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long rawContactId1 = createRawContactWithName("firstName1", "lastName1"); 20481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov insertEmail(rawContactId1, "address1@email.com"); 20491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov insertGroupMembership(rawContactId1, groupId1); 20501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov final long rawContactId2 = createRawContactWithName("firstName2", "lastName2"); 20521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov insertEmail(rawContactId2, "address2@email.com"); 20531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov insertPhoneNumber(rawContactId2, "222-222-2222"); 20541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov insertGroupMembership(rawContactId2, groupId1); 20551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov ContentValues v1 = new ContentValues(); 20571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups._ID, groupId1); 20581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.TITLE, "title1"); 20591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.SOURCE_ID, "sourceId1"); 20601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.ACCOUNT_NAME, account1.name); 20611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.ACCOUNT_TYPE, account1.type); 20621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.SUMMARY_COUNT, 2); 20631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v1.put(Groups.SUMMARY_WITH_PHONES, 1); 20641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov ContentValues v2 = new ContentValues(); 20661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v2.put(Groups._ID, groupId2); 20671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v2.put(Groups.TITLE, "title2"); 20681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov v2.put(Groups.SOURCE_ID, "sourceId2"); 2069ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.ACCOUNT_NAME, account2.name); 2070ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.ACCOUNT_TYPE, account2.type); 2071ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.SUMMARY_COUNT, 0); 2072ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.SUMMARY_WITH_PHONES, 0); 2073ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2074ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov ContentValues v3 = new ContentValues(); 2075ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups._ID, groupId3); 2076ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.TITLE, "title3"); 2077ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.SOURCE_ID, "sourceId3"); 2078ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.ACCOUNT_NAME, account2.name); 2079ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.ACCOUNT_TYPE, account2.type); 2080ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.SUMMARY_COUNT, 0); 2081ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.SUMMARY_WITH_PHONES, 0); 2082ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2083ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov assertStoredValues(Groups.CONTENT_SUMMARY_URI, new ContentValues[] { v1, v2, v3 }); 2084ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2085ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // Now rawContactId1 has two phone numbers. 2086ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov insertPhoneNumber(rawContactId1, "111-111-1111"); 2087ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov insertPhoneNumber(rawContactId1, "111-111-1112"); 2088ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // Result should reflect it correctly (don't count phone numbers but raw contacts) 2089ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v1.put(Groups.SUMMARY_WITH_PHONES, v1.getAsInteger(Groups.SUMMARY_WITH_PHONES) + 1); 2090ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov assertStoredValues(Groups.CONTENT_SUMMARY_URI, new ContentValues[] { v1, v2, v3 }); 2091ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2092ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // Introduce new raw contact, pretending the user added another info. 2093ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final long rawContactId3 = createRawContactWithName("firstName3", "lastName3"); 2094ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov insertEmail(rawContactId3, "address3@email.com"); 2095ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov insertPhoneNumber(rawContactId3, "333-333-3333"); 2096ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov insertGroupMembership(rawContactId3, groupId2); 2097ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.SUMMARY_COUNT, v2.getAsInteger(Groups.SUMMARY_COUNT) + 1); 2098ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.SUMMARY_WITH_PHONES, v2.getAsInteger(Groups.SUMMARY_WITH_PHONES) + 1); 2099ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2100ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov assertStoredValues(Groups.CONTENT_SUMMARY_URI, new ContentValues[] { v1, v2, v3 }); 2101ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2102ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Uri uri = Groups.CONTENT_SUMMARY_URI.buildUpon() 2103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov .appendQueryParameter(Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, "true") 2104ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov .build(); 2105ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v1.put(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 1); 2106ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v2.put(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 2); 2107ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov v3.put(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 2); 2108ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov assertStoredValues(uri, new ContentValues[] { v1, v2, v3 }); 2109ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 2110ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // Introduce another group in account1, testing SUMMARY_GROUP_COUNT_PER_ACCOUNT correctly 2111f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // reflects the change. 2112f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final long groupId4 = createGroup(account1, "sourceId4", "title4"); 2113f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v1.put(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 2114f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v1.getAsInteger(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT) + 1); 2115f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov ContentValues v4 = new ContentValues(); 2116f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups._ID, groupId4); 2117f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.TITLE, "title4"); 2118f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.SOURCE_ID, "sourceId4"); 2119f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.ACCOUNT_NAME, account1.name); 2120f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.ACCOUNT_TYPE, account1.type); 2121f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.SUMMARY_COUNT, 0); 2122f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.SUMMARY_WITH_PHONES, 0); 2123f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v4.put(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 2124f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov v1.getAsInteger(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT)); 2125f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertStoredValues(uri, new ContentValues[] { v1, v2, v3, v4 }); 2126f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2127f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2128f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov public void testSettingsQuery() { 2129f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Account account1 = new Account("a", "b"); 2130f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Account account2 = new Account("c", "d"); 2131f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov createSettings(account1, "0", "0"); 2132f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov createSettings(account2, "1", "1"); 2133f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Uri uri1 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account1); 2134f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Uri uri2 = maybeAddAccountQueryParameters(Settings.CONTENT_URI, account2); 2135f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertEquals(1, getCount(uri1, null, null)); 2136f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertEquals(1, getCount(uri2, null, null)); 2137f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertStoredValue(uri1, Settings.SHOULD_SYNC, "0") ; 2138f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertStoredValue(uri1, Settings.UNGROUPED_VISIBLE, "0") ; 2139f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertStoredValue(uri2, Settings.SHOULD_SYNC, "1") ; 2140f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov assertStoredValue(uri2, Settings.UNGROUPED_VISIBLE, "1") ; 2141f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2142e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2143e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey public void testDisplayNameParsingWhenPartsUnspecified() { 2144e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey long rawContactId = createRawContact(); 2145e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ContentValues values = new ContentValues(); 2146e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 2147e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey insertStructuredName(rawContactId, values); 2148e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2149e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey assertStructuredName(rawContactId, "Mr.", "John", "Kevin", "von Smith", "Jr."); 2150e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2151e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2152e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey public void testDisplayNameParsingWhenPartsAreNull() { 2153e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey long rawContactId = createRawContact(); 2154e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ContentValues values = new ContentValues(); 2155e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 2156e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.putNull(StructuredName.GIVEN_NAME); 2157e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.putNull(StructuredName.FAMILY_NAME); 2158e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey insertStructuredName(rawContactId, values); 2159e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey assertStructuredName(rawContactId, "Mr.", "John", "Kevin", "von Smith", "Jr."); 2160e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2161e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2162e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey public void testDisplayNameParsingWhenPartsSpecified() { 2163e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey long rawContactId = createRawContact(); 2164e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ContentValues values = new ContentValues(); 2165e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.put(StructuredName.DISPLAY_NAME, "Mr.John Kevin von Smith, Jr."); 2166e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey values.put(StructuredName.FAMILY_NAME, "Johnson"); 2167e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey insertStructuredName(rawContactId, values); 2168e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2169e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey assertStructuredName(rawContactId, null, null, null, "Johnson", null); 2170e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2171e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 217209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov public void testContactWithoutPhoneticName() { 217309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov final long rawContactId = createRawContact(null); 217409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 217509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov ContentValues values = new ContentValues(); 217609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov values.put(StructuredName.PREFIX, "Mr"); 217709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, "John"); 217809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, "K."); 217909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov values.put(StructuredName.FAMILY_NAME, "Doe"); 218009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov values.put(StructuredName.SUFFIX, "Jr."); 2181f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Uri dataUri = insertStructuredName(rawContactId, values); 2182f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2183f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.clear(); 2184f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 2185f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_PRIMARY, "Mr John K. Doe, Jr."); 21864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "Mr Doe, John K., Jr."); 21874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.putNull(RawContacts.PHONETIC_NAME); 21884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 21894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.SORT_KEY_PRIMARY, "John K. Doe, Jr."); 21904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.SORT_KEY_ALTERNATIVE, "Doe, John K., Jr."); 21914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 21924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 21934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertStoredValues(rawContactUri, values); 21944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 21954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.clear(); 21964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 21974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME_PRIMARY, "Mr John K. Doe, Jr."); 21984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "Mr Doe, John K., Jr."); 21994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.putNull(Contacts.PHONETIC_NAME); 2200f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 2201f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov values.put(Contacts.SORT_KEY_PRIMARY, "John K. Doe, Jr."); 22024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(Contacts.SORT_KEY_ALTERNATIVE, "Doe, John K., Jr."); 220382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 22044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 22054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov queryContactId(rawContactId)); 22064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertStoredValues(contactUri, values); 22074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // The same values should be available through a join with Data 22094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertStoredValues(dataUri, values); 22104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 22114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov public void testContactWithChineseName() { 22134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Only run this test when Chinese collation is supported 22154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) { 22164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov return; 22174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 22184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long rawContactId = createRawContact(null); 22204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov ContentValues values = new ContentValues(); 22224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(StructuredName.DISPLAY_NAME, "\u6BB5\u5C0F\u6D9B"); 22234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Uri dataUri = insertStructuredName(rawContactId, values); 22244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.clear(); 22264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 22274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_PRIMARY, "\u6BB5\u5C0F\u6D9B"); 22284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "\u6BB5\u5C0F\u6D9B"); 22294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.putNull(RawContacts.PHONETIC_NAME); 22304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 22314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.SORT_KEY_PRIMARY, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 22324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.put(RawContacts.SORT_KEY_ALTERNATIVE, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 22334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 22354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov assertStoredValues(rawContactUri, values); 22364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 22374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov values.clear(); 2238d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 2239d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.put(Contacts.DISPLAY_NAME_PRIMARY, "\u6BB5\u5C0F\u6D9B"); 2240 values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "\u6BB5\u5C0F\u6D9B"); 2241 values.putNull(Contacts.PHONETIC_NAME); 2242 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 2243 values.put(Contacts.SORT_KEY_PRIMARY, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 2244 values.put(Contacts.SORT_KEY_ALTERNATIVE, "DUAN \u6BB5 XIAO \u5C0F TAO \u6D9B"); 2245 2246 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 2247 queryContactId(rawContactId)); 2248 assertStoredValues(contactUri, values); 2249 2250 // The same values should be available through a join with Data 2251 assertStoredValues(dataUri, values); 2252 } 2253 2254 public void testContactWithJapaneseName() { 2255 long rawContactId = createRawContact(null); 2256 2257 ContentValues values = new ContentValues(); 2258 values.put(StructuredName.GIVEN_NAME, "\u7A7A\u6D77"); 2259 values.put(StructuredName.PHONETIC_GIVEN_NAME, "\u304B\u3044\u304F\u3046"); 2260 Uri dataUri = insertStructuredName(rawContactId, values); 2261 2262 values.clear(); 2263 values.put(RawContacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 2264 values.put(RawContacts.DISPLAY_NAME_PRIMARY, "\u7A7A\u6D77"); 2265 values.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, "\u7A7A\u6D77"); 2266 values.put(RawContacts.PHONETIC_NAME, "\u304B\u3044\u304F\u3046"); 2267 values.put(RawContacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 2268 values.put(RawContacts.SORT_KEY_PRIMARY, "\u304B\u3044\u304F\u3046"); 2269 values.put(RawContacts.SORT_KEY_ALTERNATIVE, "\u304B\u3044\u304F\u3046"); 2270 2271 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 2272 assertStoredValues(rawContactUri, values); 2273 2274 values.clear(); 2275 values.put(Contacts.DISPLAY_NAME_SOURCE, DisplayNameSources.STRUCTURED_NAME); 2276 values.put(Contacts.DISPLAY_NAME_PRIMARY, "\u7A7A\u6D77"); 2277 values.put(Contacts.DISPLAY_NAME_ALTERNATIVE, "\u7A7A\u6D77"); 2278 values.put(Contacts.PHONETIC_NAME, "\u304B\u3044\u304F\u3046"); 2279 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 2280 values.put(Contacts.SORT_KEY_PRIMARY, "\u304B\u3044\u304F\u3046"); 2281 values.put(Contacts.SORT_KEY_ALTERNATIVE, "\u304B\u3044\u304F\u3046"); 2282 2283 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 2284 queryContactId(rawContactId)); 2285 assertStoredValues(contactUri, values); 2286 2287 // The same values should be available through a join with Data 2288 assertStoredValues(dataUri, values); 2289 } 2290 2291 public void testDisplayNameUpdate() { 2292 long rawContactId1 = createRawContact(); 2293 insertEmail(rawContactId1, "potato@acme.com", true); 2294 2295 long rawContactId2 = createRawContact(); 2296 insertPhoneNumber(rawContactId2, "123456789", true); 2297 2298 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2299 rawContactId1, rawContactId2); 2300 2301 assertAggregated(rawContactId1, rawContactId2, "123456789"); 2302 2303 insertStructuredName(rawContactId2, "Potato", "Head"); 2304 2305 assertAggregated(rawContactId1, rawContactId2, "Potato Head"); 2306 assertNetworkNotified(true); 2307 } 2308 2309 public void testDisplayNameFromData() { 2310 long rawContactId = createRawContact(); 2311 long contactId = queryContactId(rawContactId); 2312 ContentValues values = new ContentValues(); 2313 2314 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2315 2316 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 2317 insertEmail(rawContactId, "mike@monstersinc.com"); 2318 assertStoredValue(uri, Contacts.DISPLAY_NAME, "mike@monstersinc.com"); 2319 2320 insertEmail(rawContactId, "james@monstersinc.com", true); 2321 assertStoredValue(uri, Contacts.DISPLAY_NAME, "james@monstersinc.com"); 2322 2323 insertPhoneNumber(rawContactId, "1-800-466-4411"); 2324 assertStoredValue(uri, Contacts.DISPLAY_NAME, "1-800-466-4411"); 2325 2326 // If there are title and company, the company is display name. 2327 values.clear(); 2328 values.put(Organization.COMPANY, "Monsters Inc"); 2329 Uri organizationUri = insertOrganization(rawContactId, values); 2330 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Monsters Inc"); 2331 2332 // If there is nickname, that is display name. 2333 insertNickname(rawContactId, "Sully"); 2334 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Sully"); 2335 2336 // If there is structured name, that is display name. 2337 values.clear(); 2338 values.put(StructuredName.GIVEN_NAME, "James"); 2339 values.put(StructuredName.MIDDLE_NAME, "P."); 2340 values.put(StructuredName.FAMILY_NAME, "Sullivan"); 2341 insertStructuredName(rawContactId, values); 2342 assertStoredValue(uri, Contacts.DISPLAY_NAME, "James P. Sullivan"); 2343 } 2344 2345 public void testDisplayNameFromOrganizationWithoutPhoneticName() { 2346 long rawContactId = createRawContact(); 2347 long contactId = queryContactId(rawContactId); 2348 ContentValues values = new ContentValues(); 2349 2350 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2351 2352 // If there is title without company, the title is display name. 2353 values.clear(); 2354 values.put(Organization.TITLE, "Protagonist"); 2355 Uri organizationUri = insertOrganization(rawContactId, values); 2356 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Protagonist"); 2357 2358 // If there are title and company, the company is display name. 2359 values.clear(); 2360 values.put(Organization.COMPANY, "Monsters Inc"); 2361 mResolver.update(organizationUri, values, null, null); 2362 2363 values.clear(); 2364 values.put(Contacts.DISPLAY_NAME, "Monsters Inc"); 2365 values.putNull(Contacts.PHONETIC_NAME); 2366 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 2367 values.put(Contacts.SORT_KEY_PRIMARY, "Monsters Inc"); 2368 values.put(Contacts.SORT_KEY_ALTERNATIVE, "Monsters Inc"); 2369 assertStoredValues(uri, values); 2370 } 2371 2372 public void testDisplayNameFromOrganizationWithJapanesePhoneticName() { 2373 long rawContactId = createRawContact(); 2374 long contactId = queryContactId(rawContactId); 2375 ContentValues values = new ContentValues(); 2376 2377 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2378 2379 // If there is title without company, the title is display name. 2380 values.clear(); 2381 values.put(Organization.COMPANY, "DoCoMo"); 2382 values.put(Organization.PHONETIC_NAME, "\u30C9\u30B3\u30E2"); 2383 Uri organizationUri = insertOrganization(rawContactId, values); 2384 2385 values.clear(); 2386 values.put(Contacts.DISPLAY_NAME, "DoCoMo"); 2387 values.put(Contacts.PHONETIC_NAME, "\u30C9\u30B3\u30E2"); 2388 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.JAPANESE); 2389 values.put(Contacts.SORT_KEY_PRIMARY, "\u30C9\u30B3\u30E2"); 2390 values.put(Contacts.SORT_KEY_ALTERNATIVE, "\u30C9\u30B3\u30E2"); 2391 assertStoredValues(uri, values); 2392 } 2393 2394 public void testDisplayNameFromOrganizationWithChineseName() { 2395 boolean hasChineseCollator = false; 2396 final Locale locale[] = Collator.getAvailableLocales(); 2397 for (int i = 0; i < locale.length; i++) { 2398 if (locale[i].equals(Locale.CHINA)) { 2399 hasChineseCollator = true; 2400 break; 2401 } 2402 } 2403 2404 if (!hasChineseCollator) { 2405 return; 2406 } 2407 2408 long rawContactId = createRawContact(); 2409 long contactId = queryContactId(rawContactId); 2410 ContentValues values = new ContentValues(); 2411 2412 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2413 2414 // If there is title without company, the title is display name. 2415 values.clear(); 2416 values.put(Organization.COMPANY, "\u4E2D\u56FD\u7535\u4FE1"); 2417 Uri organizationUri = insertOrganization(rawContactId, values); 2418 2419 values.clear(); 2420 values.put(Contacts.DISPLAY_NAME, "\u4E2D\u56FD\u7535\u4FE1"); 2421 values.putNull(Contacts.PHONETIC_NAME); 2422 values.put(Contacts.PHONETIC_NAME_STYLE, PhoneticNameStyle.UNDEFINED); 2423 values.put(Contacts.SORT_KEY_PRIMARY, "ZHONG \u4E2D GUO \u56FD DIAN \u7535 XIN \u4FE1"); 2424 values.put(Contacts.SORT_KEY_ALTERNATIVE, "ZHONG \u4E2D GUO \u56FD DIAN \u7535 XIN \u4FE1"); 2425 assertStoredValues(uri, values); 2426 } 2427 2428 public void testLookupByOrganization() { 2429 long rawContactId = createRawContact(); 2430 long contactId = queryContactId(rawContactId); 2431 ContentValues values = new ContentValues(); 2432 2433 values.clear(); 2434 values.put(Organization.COMPANY, "acmecorp"); 2435 values.put(Organization.TITLE, "president"); 2436 Uri organizationUri = insertOrganization(rawContactId, values); 2437 2438 assertContactFilter(contactId, "acmecorp"); 2439 assertContactFilter(contactId, "president"); 2440 2441 values.clear(); 2442 values.put(Organization.DEPARTMENT, "software"); 2443 mResolver.update(organizationUri, values, null, null); 2444 2445 assertContactFilter(contactId, "acmecorp"); 2446 assertContactFilter(contactId, "president"); 2447 2448 values.clear(); 2449 values.put(Organization.COMPANY, "incredibles"); 2450 mResolver.update(organizationUri, values, null, null); 2451 2452 assertContactFilter(contactId, "incredibles"); 2453 assertContactFilter(contactId, "president"); 2454 2455 values.clear(); 2456 values.put(Organization.TITLE, "director"); 2457 mResolver.update(organizationUri, values, null, null); 2458 2459 assertContactFilter(contactId, "incredibles"); 2460 assertContactFilter(contactId, "director"); 2461 2462 values.clear(); 2463 values.put(Organization.COMPANY, "monsters"); 2464 values.put(Organization.TITLE, "scarer"); 2465 mResolver.update(organizationUri, values, null, null); 2466 2467 assertContactFilter(contactId, "monsters"); 2468 assertContactFilter(contactId, "scarer"); 2469 } 2470 2471 private void assertContactFilter(long contactId, String filter) { 2472 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(filter)); 2473 assertStoredValue(filterUri, Contacts._ID, contactId); 2474 } 2475 2476 private void assertContactFilterNoResult(String filter) { 2477 Uri filterUri4 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, filter); 2478 assertEquals(0, getCount(filterUri4, null, null)); 2479 } 2480 2481 public void testSearchSnippetOrganization() throws Exception { 2482 long rawContactId = createRawContactWithName(); 2483 long contactId = queryContactId(rawContactId); 2484 2485 // Some random data element 2486 insertEmail(rawContactId, "inc@corp.com"); 2487 2488 ContentValues values = new ContentValues(); 2489 values.clear(); 2490 values.put(Organization.COMPANY, "acmecorp"); 2491 values.put(Organization.TITLE, "engineer"); 2492 Uri organizationUri = insertOrganization(rawContactId, values); 2493 2494 // Add another matching organization 2495 values.put(Organization.COMPANY, "acmeinc"); 2496 insertOrganization(rawContactId, values); 2497 2498 // Add another non-matching organization 2499 values.put(Organization.COMPANY, "corpacme"); 2500 insertOrganization(rawContactId, values); 2501 2502 // And another data element 2503 insertEmail(rawContactId, "emca@corp.com", true, Email.TYPE_CUSTOM, "Custom"); 2504 2505 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("acme")); 2506 2507 values.clear(); 2508 values.put(Contacts._ID, contactId); 2509 values.put(SearchSnippetColumns.SNIPPET, "engineer, [acmecorp]"); 2510 assertStoredValues(filterUri, values); 2511 } 2512 2513 public void testSearchSnippetEmail() throws Exception { 2514 long rawContactId = createRawContact(); 2515 long contactId = queryContactId(rawContactId); 2516 ContentValues values = new ContentValues(); 2517 2518 insertStructuredName(rawContactId, "John", "Doe"); 2519 Uri dataUri = insertEmail(rawContactId, "acme@corp.com", true, Email.TYPE_CUSTOM, "Custom"); 2520 2521 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("acme")); 2522 2523 values.clear(); 2524 values.put(Contacts._ID, contactId); 2525 values.put(SearchSnippetColumns.SNIPPET, "[acme@corp.com]"); 2526 assertStoredValues(filterUri, values); 2527 } 2528 2529 public void testSearchSnippetPhone() throws Exception { 2530 long rawContactId = createRawContact(); 2531 long contactId = queryContactId(rawContactId); 2532 ContentValues values = new ContentValues(); 2533 2534 insertStructuredName(rawContactId, "Cave", "Johnson"); 2535 insertPhoneNumber(rawContactId, "(860) 555-1234"); 2536 2537 values.clear(); 2538 values.put(Contacts._ID, contactId); 2539 values.put(SearchSnippetColumns.SNIPPET, "[(860) 555-1234]"); 2540 2541 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2542 Uri.encode("86 (0) 5-55-12-34")), values); 2543 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2544 Uri.encode("860 555-1234")), values); 2545 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2546 Uri.encode("860")), values); 2547 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2548 Uri.encode("8605551234")), values); 2549 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2550 Uri.encode("860555")), values); 2551 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2552 Uri.encode("860 555")), values); 2553 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2554 Uri.encode("860-555")), values); 2555 } 2556 2557 public void testSearchSnippetNickname() throws Exception { 2558 long rawContactId = createRawContactWithName(); 2559 long contactId = queryContactId(rawContactId); 2560 ContentValues values = new ContentValues(); 2561 2562 Uri dataUri = insertNickname(rawContactId, "Incredible"); 2563 2564 Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("inc")); 2565 2566 values.clear(); 2567 values.put(Contacts._ID, contactId); 2568 values.put(SearchSnippetColumns.SNIPPET, "[Incredible]"); 2569 assertStoredValues(filterUri, values); 2570 } 2571 2572 public void testSearchSnippetEmptyForNameInDisplayName() throws Exception { 2573 long rawContactId = createRawContact(); 2574 long contactId = queryContactId(rawContactId); 2575 insertStructuredName(rawContactId, "Cave", "Johnson"); 2576 insertEmail(rawContactId, "cave@aperturescience.com", true); 2577 2578 ContentValues emptySnippet = new ContentValues(); 2579 emptySnippet.clear(); 2580 emptySnippet.put(Contacts._ID, contactId); 2581 emptySnippet.put(SearchSnippetColumns.SNIPPET, (String) null); 2582 2583 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("cave")), 2584 emptySnippet); 2585 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("john")), 2586 emptySnippet); 2587 } 2588 2589 public void testSearchSnippetEmptyForNicknameInDisplayName() throws Exception { 2590 long rawContactId = createRawContact(); 2591 long contactId = queryContactId(rawContactId); 2592 insertNickname(rawContactId, "Caveman"); 2593 insertEmail(rawContactId, "cave@aperturescience.com", true); 2594 2595 ContentValues emptySnippet = new ContentValues(); 2596 emptySnippet.clear(); 2597 emptySnippet.put(Contacts._ID, contactId); 2598 emptySnippet.put(SearchSnippetColumns.SNIPPET, (String) null); 2599 2600 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("cave")), 2601 emptySnippet); 2602 } 2603 2604 public void testSearchSnippetEmptyForCompanyInDisplayName() throws Exception { 2605 long rawContactId = createRawContact(); 2606 long contactId = queryContactId(rawContactId); 2607 ContentValues company = new ContentValues(); 2608 company.clear(); 2609 company.put(Organization.COMPANY, "Aperture Science"); 2610 company.put(Organization.TITLE, "President"); 2611 insertOrganization(rawContactId, company); 2612 insertEmail(rawContactId, "aperturepresident@aperturescience.com", true); 2613 2614 ContentValues emptySnippet = new ContentValues(); 2615 emptySnippet.clear(); 2616 emptySnippet.put(Contacts._ID, contactId); 2617 emptySnippet.put(SearchSnippetColumns.SNIPPET, (String) null); 2618 2619 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 2620 Uri.encode("aperture")), emptySnippet); 2621 } 2622 2623 public void testSearchSnippetEmptyForPhoneInDisplayName() throws Exception { 2624 long rawContactId = createRawContact(); 2625 long contactId = queryContactId(rawContactId); 2626 insertPhoneNumber(rawContactId, "860-555-1234"); 2627 insertEmail(rawContactId, "860@aperturescience.com", true); 2628 2629 ContentValues emptySnippet = new ContentValues(); 2630 emptySnippet.clear(); 2631 emptySnippet.put(Contacts._ID, contactId); 2632 emptySnippet.put(SearchSnippetColumns.SNIPPET, (String) null); 2633 2634 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("860")), 2635 emptySnippet); 2636 } 2637 2638 public void testSearchSnippetEmptyForEmailInDisplayName() throws Exception { 2639 long rawContactId = createRawContact(); 2640 long contactId = queryContactId(rawContactId); 2641 insertEmail(rawContactId, "cave@aperturescience.com", true); 2642 insertNote(rawContactId, "Cave Johnson is president of Aperture Science"); 2643 2644 ContentValues emptySnippet = new ContentValues(); 2645 emptySnippet.clear(); 2646 emptySnippet.put(Contacts._ID, contactId); 2647 emptySnippet.put(SearchSnippetColumns.SNIPPET, (String) null); 2648 2649 assertStoredValues(Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode("cave")), 2650 emptySnippet); 2651 } 2652 2653 public void testDisplayNameUpdateFromStructuredNameUpdate() { 2654 long rawContactId = createRawContact(); 2655 Uri nameUri = insertStructuredName(rawContactId, "Slinky", "Dog"); 2656 2657 long contactId = queryContactId(rawContactId); 2658 2659 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2660 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky Dog"); 2661 2662 ContentValues values = new ContentValues(); 2663 values.putNull(StructuredName.FAMILY_NAME); 2664 2665 mResolver.update(nameUri, values, null, null); 2666 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Slinky"); 2667 2668 values.putNull(StructuredName.GIVEN_NAME); 2669 2670 mResolver.update(nameUri, values, null, null); 2671 assertStoredValue(uri, Contacts.DISPLAY_NAME, null); 2672 2673 values.put(StructuredName.FAMILY_NAME, "Dog"); 2674 mResolver.update(nameUri, values, null, null); 2675 2676 assertStoredValue(uri, Contacts.DISPLAY_NAME, "Dog"); 2677 } 2678 2679 public void testInsertDataWithContentProviderOperations() throws Exception { 2680 ContentProviderOperation cpo1 = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) 2681 .withValues(new ContentValues()) 2682 .build(); 2683 ContentProviderOperation cpo2 = ContentProviderOperation.newInsert(Data.CONTENT_URI) 2684 .withValueBackReference(Data.RAW_CONTACT_ID, 0) 2685 .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) 2686 .withValue(StructuredName.GIVEN_NAME, "John") 2687 .withValue(StructuredName.FAMILY_NAME, "Doe") 2688 .build(); 2689 ContentProviderResult[] results = 2690 mResolver.applyBatch(ContactsContract.AUTHORITY, Lists.newArrayList(cpo1, cpo2)); 2691 long contactId = queryContactId(ContentUris.parseId(results[0].uri)); 2692 Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2693 assertStoredValue(uri, Contacts.DISPLAY_NAME, "John Doe"); 2694 } 2695 2696 public void testSendToVoicemailDefault() { 2697 long rawContactId = createRawContactWithName(); 2698 long contactId = queryContactId(rawContactId); 2699 2700 Cursor c = queryContact(contactId); 2701 assertTrue(c.moveToNext()); 2702 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 2703 assertEquals(0, sendToVoicemail); 2704 c.close(); 2705 } 2706 2707 public void testSetSendToVoicemailAndRingtone() { 2708 long rawContactId = createRawContactWithName(); 2709 long contactId = queryContactId(rawContactId); 2710 2711 updateSendToVoicemailAndRingtone(contactId, true, "foo"); 2712 assertSendToVoicemailAndRingtone(contactId, true, "foo"); 2713 assertNetworkNotified(false); 2714 2715 updateSendToVoicemailAndRingtoneWithSelection(contactId, false, "bar"); 2716 assertSendToVoicemailAndRingtone(contactId, false, "bar"); 2717 assertNetworkNotified(false); 2718 } 2719 2720 public void testSendToVoicemailAndRingtoneAfterAggregation() { 2721 long rawContactId1 = createRawContactWithName("a", "b"); 2722 long contactId1 = queryContactId(rawContactId1); 2723 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 2724 2725 long rawContactId2 = createRawContactWithName("c", "d"); 2726 long contactId2 = queryContactId(rawContactId2); 2727 updateSendToVoicemailAndRingtone(contactId2, true, "bar"); 2728 2729 // Aggregate them 2730 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2731 rawContactId1, rawContactId2); 2732 2733 // Both contacts had "send to VM", the contact now has the same value 2734 assertSendToVoicemailAndRingtone(contactId1, true, "foo,bar"); // Either foo or bar 2735 } 2736 2737 public void testDoNotSendToVoicemailAfterAggregation() { 2738 long rawContactId1 = createRawContactWithName("e", "f"); 2739 long contactId1 = queryContactId(rawContactId1); 2740 updateSendToVoicemailAndRingtone(contactId1, true, null); 2741 2742 long rawContactId2 = createRawContactWithName("g", "h"); 2743 long contactId2 = queryContactId(rawContactId2); 2744 updateSendToVoicemailAndRingtone(contactId2, false, null); 2745 2746 // Aggregate them 2747 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2748 rawContactId1, rawContactId2); 2749 2750 // Since one of the contacts had "don't send to VM" that setting wins for the aggregate 2751 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), false, null); 2752 } 2753 2754 public void testSetSendToVoicemailAndRingtonePreservedAfterJoinAndSplit() { 2755 long rawContactId1 = createRawContactWithName("i", "j"); 2756 long contactId1 = queryContactId(rawContactId1); 2757 updateSendToVoicemailAndRingtone(contactId1, true, "foo"); 2758 2759 long rawContactId2 = createRawContactWithName("k", "l"); 2760 long contactId2 = queryContactId(rawContactId2); 2761 updateSendToVoicemailAndRingtone(contactId2, false, "bar"); 2762 2763 // Aggregate them 2764 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 2765 rawContactId1, rawContactId2); 2766 2767 // Split them 2768 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 2769 rawContactId1, rawContactId2); 2770 2771 assertSendToVoicemailAndRingtone(queryContactId(rawContactId1), true, "foo"); 2772 assertSendToVoicemailAndRingtone(queryContactId(rawContactId2), false, "bar"); 2773 } 2774 2775 public void testStatusUpdateInsert() { 2776 long rawContactId = createRawContact(); 2777 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2778 long dataId = ContentUris.parseId(imUri); 2779 2780 ContentValues values = new ContentValues(); 2781 values.put(StatusUpdates.DATA_ID, dataId); 2782 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 2783 values.putNull(StatusUpdates.CUSTOM_PROTOCOL); 2784 values.put(StatusUpdates.IM_HANDLE, "aim"); 2785 values.put(StatusUpdates.PRESENCE, StatusUpdates.INVISIBLE); 2786 values.put(StatusUpdates.STATUS, "Hiding"); 2787 values.put(StatusUpdates.STATUS_TIMESTAMP, 100); 2788 values.put(StatusUpdates.STATUS_RES_PACKAGE, "a.b.c"); 2789 values.put(StatusUpdates.STATUS_ICON, 1234); 2790 values.put(StatusUpdates.STATUS_LABEL, 2345); 2791 2792 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 2793 2794 assertStoredValues(resultUri, values); 2795 2796 long contactId = queryContactId(rawContactId); 2797 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2798 2799 values.clear(); 2800 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 2801 values.put(Contacts.CONTACT_STATUS, "Hiding"); 2802 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 2803 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "a.b.c"); 2804 values.put(Contacts.CONTACT_STATUS_ICON, 1234); 2805 values.put(Contacts.CONTACT_STATUS_LABEL, 2345); 2806 2807 assertStoredValues(contactUri, values); 2808 2809 values.clear(); 2810 values.put(StatusUpdates.DATA_ID, dataId); 2811 values.put(StatusUpdates.STATUS, "Cloaked"); 2812 values.put(StatusUpdates.STATUS_TIMESTAMP, 200); 2813 values.put(StatusUpdates.STATUS_RES_PACKAGE, "d.e.f"); 2814 values.put(StatusUpdates.STATUS_ICON, 4321); 2815 values.put(StatusUpdates.STATUS_LABEL, 5432); 2816 mResolver.insert(StatusUpdates.CONTENT_URI, values); 2817 2818 values.clear(); 2819 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE); 2820 values.put(Contacts.CONTACT_STATUS, "Cloaked"); 2821 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 200); 2822 values.put(Contacts.CONTACT_STATUS_RES_PACKAGE, "d.e.f"); 2823 values.put(Contacts.CONTACT_STATUS_ICON, 4321); 2824 values.put(Contacts.CONTACT_STATUS_LABEL, 5432); 2825 assertStoredValues(contactUri, values); 2826 } 2827 2828 public void testStatusUpdateInferAttribution() { 2829 long rawContactId = createRawContact(); 2830 Uri imUri = insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2831 long dataId = ContentUris.parseId(imUri); 2832 2833 ContentValues values = new ContentValues(); 2834 values.put(StatusUpdates.DATA_ID, dataId); 2835 values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_AIM); 2836 values.put(StatusUpdates.IM_HANDLE, "aim"); 2837 values.put(StatusUpdates.STATUS, "Hiding"); 2838 2839 Uri resultUri = mResolver.insert(StatusUpdates.CONTENT_URI, values); 2840 2841 values.clear(); 2842 values.put(StatusUpdates.DATA_ID, dataId); 2843 values.put(StatusUpdates.STATUS_LABEL, com.android.internal.R.string.imProtocolAim); 2844 values.put(StatusUpdates.STATUS, "Hiding"); 2845 2846 assertStoredValues(resultUri, values); 2847 } 2848 2849 public void testStatusUpdateMatchingImOrEmail() { 2850 long rawContactId = createRawContact(); 2851 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2852 insertImHandle(rawContactId, Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im"); 2853 insertEmail(rawContactId, "m@acme.com"); 2854 2855 // Match on IM (standard) 2856 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2857 StatusUpdates.CAPABILITY_HAS_CAMERA); 2858 2859 // Match on IM (custom) 2860 insertStatusUpdate(Im.PROTOCOL_CUSTOM, "my_im_proto", "my_im", StatusUpdates.IDLE, "Idle", 2861 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO); 2862 2863 // Match on Email 2864 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "m@acme.com", StatusUpdates.AWAY, "Away", 2865 StatusUpdates.CAPABILITY_HAS_VOICE); 2866 2867 // No match 2868 insertStatusUpdate(Im.PROTOCOL_ICQ, null, "12345", StatusUpdates.DO_NOT_DISTURB, "Go away", 2869 StatusUpdates.CAPABILITY_HAS_CAMERA); 2870 2871 Cursor c = mResolver.query(StatusUpdates.CONTENT_URI, new String[] { 2872 StatusUpdates.DATA_ID, StatusUpdates.PROTOCOL, StatusUpdates.CUSTOM_PROTOCOL, 2873 StatusUpdates.PRESENCE, StatusUpdates.STATUS}, 2874 PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null, StatusUpdates.DATA_ID); 2875 assertTrue(c.moveToNext()); 2876 assertStatusUpdate(c, Im.PROTOCOL_AIM, null, StatusUpdates.AVAILABLE, "Available"); 2877 assertTrue(c.moveToNext()); 2878 assertStatusUpdate(c, Im.PROTOCOL_CUSTOM, "my_im_proto", StatusUpdates.IDLE, "Idle"); 2879 assertTrue(c.moveToNext()); 2880 assertStatusUpdate(c, Im.PROTOCOL_GOOGLE_TALK, null, StatusUpdates.AWAY, "Away"); 2881 assertFalse(c.moveToNext()); 2882 c.close(); 2883 2884 long contactId = queryContactId(rawContactId); 2885 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2886 2887 ContentValues values = new ContentValues(); 2888 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2889 values.put(Contacts.CONTACT_STATUS, "Available"); 2890 assertStoredValuesWithProjection(contactUri, values); 2891 } 2892 2893 public void testStatusUpdateUpdateAndDelete() { 2894 long rawContactId = createRawContact(); 2895 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2896 2897 long contactId = queryContactId(rawContactId); 2898 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2899 2900 ContentValues values = new ContentValues(); 2901 values.putNull(Contacts.CONTACT_PRESENCE); 2902 values.putNull(Contacts.CONTACT_STATUS); 2903 assertStoredValuesWithProjection(contactUri, values); 2904 2905 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AWAY, "BUSY", 2906 StatusUpdates.CAPABILITY_HAS_CAMERA); 2907 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.DO_NOT_DISTURB, "GO AWAY", 2908 StatusUpdates.CAPABILITY_HAS_CAMERA); 2909 Uri statusUri = 2910 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2911 StatusUpdates.CAPABILITY_HAS_CAMERA); 2912 long statusId = ContentUris.parseId(statusUri); 2913 2914 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2915 values.put(Contacts.CONTACT_STATUS, "Available"); 2916 assertStoredValuesWithProjection(contactUri, values); 2917 2918 // update status_updates table to set new values for 2919 // status_updates.status 2920 // status_updates.status_ts 2921 // presence 2922 long updatedTs = 200; 2923 String testUpdate = "test_update"; 2924 String selection = StatusUpdates.DATA_ID + "=" + statusId; 2925 values.clear(); 2926 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2927 values.put(StatusUpdates.STATUS, testUpdate); 2928 values.put(StatusUpdates.PRESENCE, "presence_test"); 2929 mResolver.update(StatusUpdates.CONTENT_URI, values, 2930 StatusUpdates.DATA_ID + "=" + statusId, null); 2931 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2932 2933 // update status_updates table to set new values for columns in status_updates table ONLY 2934 // i.e., no rows in presence table are to be updated. 2935 updatedTs = 300; 2936 testUpdate = "test_update_new"; 2937 selection = StatusUpdates.DATA_ID + "=" + statusId; 2938 values.clear(); 2939 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2940 values.put(StatusUpdates.STATUS, testUpdate); 2941 mResolver.update(StatusUpdates.CONTENT_URI, values, 2942 StatusUpdates.DATA_ID + "=" + statusId, null); 2943 // make sure the presence column value is still the old value 2944 values.put(StatusUpdates.PRESENCE, "presence_test"); 2945 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2946 2947 // update status_updates table to set new values for columns in presence table ONLY 2948 // i.e., no rows in status_updates table are to be updated. 2949 selection = StatusUpdates.DATA_ID + "=" + statusId; 2950 values.clear(); 2951 values.put(StatusUpdates.PRESENCE, "presence_test_new"); 2952 mResolver.update(StatusUpdates.CONTENT_URI, values, 2953 StatusUpdates.DATA_ID + "=" + statusId, null); 2954 // make sure the status_updates table is not updated 2955 values.put(StatusUpdates.STATUS_TIMESTAMP, updatedTs); 2956 values.put(StatusUpdates.STATUS, testUpdate); 2957 assertStoredValuesWithProjection(StatusUpdates.CONTENT_URI, values); 2958 2959 // effect "delete status_updates" operation and expect the following 2960 // data deleted from status_updates table 2961 // presence set to null 2962 mResolver.delete(StatusUpdates.CONTENT_URI, StatusUpdates.DATA_ID + "=" + statusId, null); 2963 values.clear(); 2964 values.putNull(Contacts.CONTACT_PRESENCE); 2965 assertStoredValuesWithProjection(contactUri, values); 2966 } 2967 2968 public void testStatusUpdateUpdateToNull() { 2969 long rawContactId = createRawContact(); 2970 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2971 2972 long contactId = queryContactId(rawContactId); 2973 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 2974 2975 ContentValues values = new ContentValues(); 2976 Uri statusUri = 2977 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", StatusUpdates.AVAILABLE, "Available", 2978 StatusUpdates.CAPABILITY_HAS_CAMERA); 2979 long statusId = ContentUris.parseId(statusUri); 2980 2981 values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.AVAILABLE); 2982 values.put(Contacts.CONTACT_STATUS, "Available"); 2983 assertStoredValuesWithProjection(contactUri, values); 2984 2985 values.clear(); 2986 values.putNull(StatusUpdates.PRESENCE); 2987 mResolver.update(StatusUpdates.CONTENT_URI, values, 2988 StatusUpdates.DATA_ID + "=" + statusId, null); 2989 2990 values.clear(); 2991 values.putNull(Contacts.CONTACT_PRESENCE); 2992 values.put(Contacts.CONTACT_STATUS, "Available"); 2993 assertStoredValuesWithProjection(contactUri, values); 2994 } 2995 2996 public void testStatusUpdateWithTimestamp() { 2997 long rawContactId = createRawContact(); 2998 insertImHandle(rawContactId, Im.PROTOCOL_AIM, null, "aim"); 2999 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "gtalk"); 3000 3001 long contactId = queryContactId(rawContactId); 3002 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 3003 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Offline", 80, 3004 StatusUpdates.CAPABILITY_HAS_CAMERA); 3005 insertStatusUpdate(Im.PROTOCOL_AIM, null, "aim", 0, "Available", 100, 3006 StatusUpdates.CAPABILITY_HAS_CAMERA); 3007 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "gtalk", 0, "Busy", 90, 3008 StatusUpdates.CAPABILITY_HAS_CAMERA); 3009 3010 // Should return the latest status 3011 ContentValues values = new ContentValues(); 3012 values.put(Contacts.CONTACT_STATUS_TIMESTAMP, 100); 3013 values.put(Contacts.CONTACT_STATUS, "Available"); 3014 assertStoredValuesWithProjection(contactUri, values); 3015 } 3016 3017 private void assertStatusUpdate(Cursor c, int protocol, String customProtocol, int presence, 3018 String status) { 3019 ContentValues values = new ContentValues(); 3020 values.put(StatusUpdates.PROTOCOL, protocol); 3021 values.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 3022 values.put(StatusUpdates.PRESENCE, presence); 3023 values.put(StatusUpdates.STATUS, status); 3024 assertCursorValues(c, values); 3025 } 3026 3027 // Stream item query test cases. 3028 3029 public void testQueryStreamItemsByRawContactId() { 3030 long rawContactId = createRawContact(mAccount); 3031 ContentValues values = buildGenericStreamItemValues(); 3032 insertStreamItem(rawContactId, values, mAccount); 3033 assertStoredValues( 3034 Uri.withAppendedPath( 3035 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3036 RawContacts.StreamItems.CONTENT_DIRECTORY), 3037 values); 3038 } 3039 3040 public void testQueryStreamItemsByContactId() { 3041 long rawContactId = createRawContact(); 3042 long contactId = queryContactId(rawContactId); 3043 ContentValues values = buildGenericStreamItemValues(); 3044 insertStreamItem(rawContactId, values, null); 3045 assertStoredValues( 3046 Uri.withAppendedPath( 3047 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 3048 Contacts.StreamItems.CONTENT_DIRECTORY), 3049 values); 3050 } 3051 3052 public void testQueryStreamItemsByLookupKey() { 3053 long rawContactId = createRawContact(); 3054 long contactId = queryContactId(rawContactId); 3055 String lookupKey = queryLookupKey(contactId); 3056 ContentValues values = buildGenericStreamItemValues(); 3057 insertStreamItem(rawContactId, values, null); 3058 assertStoredValues( 3059 Uri.withAppendedPath( 3060 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), 3061 Contacts.StreamItems.CONTENT_DIRECTORY), 3062 values); 3063 } 3064 3065 public void testQueryStreamItemsByLookupKeyAndContactId() { 3066 long rawContactId = createRawContact(); 3067 long contactId = queryContactId(rawContactId); 3068 String lookupKey = queryLookupKey(contactId); 3069 ContentValues values = buildGenericStreamItemValues(); 3070 insertStreamItem(rawContactId, values, null); 3071 assertStoredValues( 3072 Uri.withAppendedPath( 3073 ContentUris.withAppendedId( 3074 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), 3075 contactId), 3076 Contacts.StreamItems.CONTENT_DIRECTORY), 3077 values); 3078 } 3079 3080 public void testQueryStreamItems() { 3081 long rawContactId = createRawContact(); 3082 ContentValues values = buildGenericStreamItemValues(); 3083 insertStreamItem(rawContactId, values, null); 3084 assertStoredValues(StreamItems.CONTENT_URI, values); 3085 } 3086 3087 public void testQueryStreamItemsWithSelection() { 3088 long rawContactId = createRawContact(); 3089 ContentValues firstValues = buildGenericStreamItemValues(); 3090 insertStreamItem(rawContactId, firstValues, null); 3091 3092 ContentValues secondValues = buildGenericStreamItemValues(); 3093 secondValues.put(StreamItems.TEXT, "Goodbye world"); 3094 insertStreamItem(rawContactId, secondValues, null); 3095 3096 // Select only the first stream item. 3097 assertStoredValues(StreamItems.CONTENT_URI, StreamItems.TEXT + "=?", 3098 new String[]{"Hello world"}, firstValues); 3099 3100 // Select only the second stream item. 3101 assertStoredValues(StreamItems.CONTENT_URI, StreamItems.TEXT + "=?", 3102 new String[]{"Goodbye world"}, secondValues); 3103 } 3104 3105 public void testQueryStreamItemById() { 3106 long rawContactId = createRawContact(); 3107 ContentValues firstValues = buildGenericStreamItemValues(); 3108 Uri resultUri = insertStreamItem(rawContactId, firstValues, null); 3109 long firstStreamItemId = ContentUris.parseId(resultUri); 3110 3111 ContentValues secondValues = buildGenericStreamItemValues(); 3112 secondValues.put(StreamItems.TEXT, "Goodbye world"); 3113 resultUri = insertStreamItem(rawContactId, secondValues, null); 3114 long secondStreamItemId = ContentUris.parseId(resultUri); 3115 3116 // Select only the first stream item. 3117 assertStoredValues(ContentUris.withAppendedId(StreamItems.CONTENT_URI, firstStreamItemId), 3118 firstValues); 3119 3120 // Select only the second stream item. 3121 assertStoredValues(ContentUris.withAppendedId(StreamItems.CONTENT_URI, secondStreamItemId), 3122 secondValues); 3123 } 3124 3125 // Stream item photo insertion + query test cases. 3126 3127 public void testQueryStreamItemPhotoWithSelection() { 3128 long rawContactId = createRawContact(); 3129 ContentValues values = buildGenericStreamItemValues(); 3130 Uri resultUri = insertStreamItem(rawContactId, values, null); 3131 long streamItemId = ContentUris.parseId(resultUri); 3132 3133 ContentValues photo1Values = buildGenericStreamItemPhotoValues(1); 3134 insertStreamItemPhoto(streamItemId, photo1Values, null); 3135 photo1Values.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3136 ContentValues photo2Values = buildGenericStreamItemPhotoValues(2); 3137 insertStreamItemPhoto(streamItemId, photo2Values, null); 3138 3139 // Select only the first photo. 3140 assertStoredValues(StreamItems.CONTENT_PHOTO_URI, StreamItemPhotos.SORT_INDEX + "=?", 3141 new String[]{"1"}, photo1Values); 3142 } 3143 3144 public void testQueryStreamItemPhotoByStreamItemId() { 3145 long rawContactId = createRawContact(); 3146 3147 // Insert a first stream item. 3148 ContentValues firstValues = buildGenericStreamItemValues(); 3149 Uri resultUri = insertStreamItem(rawContactId, firstValues, null); 3150 long firstStreamItemId = ContentUris.parseId(resultUri); 3151 3152 // Insert a second stream item. 3153 ContentValues secondValues = buildGenericStreamItemValues(); 3154 resultUri = insertStreamItem(rawContactId, secondValues, null); 3155 long secondStreamItemId = ContentUris.parseId(resultUri); 3156 3157 // Add a photo to the first stream item. 3158 ContentValues photo1Values = buildGenericStreamItemPhotoValues(1); 3159 insertStreamItemPhoto(firstStreamItemId, photo1Values, null); 3160 photo1Values.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3161 3162 // Add a photo to the second stream item. 3163 ContentValues photo2Values = buildGenericStreamItemPhotoValues(1); 3164 photo2Values.put(StreamItemPhotos.PHOTO, loadPhotoFromResource( 3165 R.drawable.nebula, PhotoSize.ORIGINAL)); 3166 insertStreamItemPhoto(secondStreamItemId, photo2Values, null); 3167 photo2Values.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3168 3169 // Select only the photos from the second stream item. 3170 assertStoredValues(Uri.withAppendedPath( 3171 ContentUris.withAppendedId(StreamItems.CONTENT_URI, secondStreamItemId), 3172 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), photo2Values); 3173 } 3174 3175 public void testQueryStreamItemPhotoByStreamItemPhotoId() { 3176 long rawContactId = createRawContact(); 3177 3178 // Insert a first stream item. 3179 ContentValues firstValues = buildGenericStreamItemValues(); 3180 Uri resultUri = insertStreamItem(rawContactId, firstValues, null); 3181 long firstStreamItemId = ContentUris.parseId(resultUri); 3182 3183 // Insert a second stream item. 3184 ContentValues secondValues = buildGenericStreamItemValues(); 3185 resultUri = insertStreamItem(rawContactId, secondValues, null); 3186 long secondStreamItemId = ContentUris.parseId(resultUri); 3187 3188 // Add a photo to the first stream item. 3189 ContentValues photo1Values = buildGenericStreamItemPhotoValues(1); 3190 resultUri = insertStreamItemPhoto(firstStreamItemId, photo1Values, null); 3191 long firstPhotoId = ContentUris.parseId(resultUri); 3192 photo1Values.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3193 3194 // Add a photo to the second stream item. 3195 ContentValues photo2Values = buildGenericStreamItemPhotoValues(1); 3196 photo2Values.put(StreamItemPhotos.PHOTO, loadPhotoFromResource( 3197 R.drawable.galaxy, PhotoSize.ORIGINAL)); 3198 resultUri = insertStreamItemPhoto(secondStreamItemId, photo2Values, null); 3199 long secondPhotoId = ContentUris.parseId(resultUri); 3200 photo2Values.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3201 3202 // Select the first photo. 3203 assertStoredValues(ContentUris.withAppendedId( 3204 Uri.withAppendedPath( 3205 ContentUris.withAppendedId(StreamItems.CONTENT_URI, firstStreamItemId), 3206 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3207 firstPhotoId), 3208 photo1Values); 3209 3210 // Select the second photo. 3211 assertStoredValues(ContentUris.withAppendedId( 3212 Uri.withAppendedPath( 3213 ContentUris.withAppendedId(StreamItems.CONTENT_URI, secondStreamItemId), 3214 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3215 secondPhotoId), 3216 photo2Values); 3217 } 3218 3219 // Stream item insertion test cases. 3220 3221 public void testInsertStreamItemIntoOtherAccount() { 3222 long rawContactId = createRawContact(mAccount); 3223 ContentValues values = buildGenericStreamItemValues(); 3224 try { 3225 insertStreamItem(rawContactId, values, mAccountTwo); 3226 fail("Stream insertion was allowed in another account's raw contact."); 3227 } catch (SecurityException expected) { 3228 // Trying to insert stream items into account one's raw contact is forbidden. 3229 } 3230 } 3231 3232 public void testInsertStreamItemInProfileRequiresWriteProfileAccess() { 3233 long profileRawContactId = createBasicProfileContact(new ContentValues()); 3234 3235 // With our (default) write profile permission, we should be able to insert a stream item. 3236 ContentValues values = buildGenericStreamItemValues(); 3237 insertStreamItem(profileRawContactId, values, null); 3238 3239 // Now take away write profile permission. 3240 mActor.removePermissions("android.permission.WRITE_PROFILE"); 3241 3242 // Try inserting another stream item. 3243 try { 3244 insertStreamItem(profileRawContactId, values, null); 3245 fail("Should require WRITE_PROFILE access to insert a stream item in the profile."); 3246 } catch (SecurityException expected) { 3247 // Trying to insert a stream item in the profile without WRITE_PROFILE permission 3248 // should fail. 3249 } 3250 } 3251 3252 public void testInsertStreamItemWithContentValues() { 3253 long rawContactId = createRawContact(); 3254 ContentValues values = buildGenericStreamItemValues(); 3255 values.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3256 mResolver.insert(StreamItems.CONTENT_URI, values); 3257 assertStoredValues(Uri.withAppendedPath( 3258 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3259 RawContacts.StreamItems.CONTENT_DIRECTORY), values); 3260 } 3261 3262 public void testInsertStreamItemOverLimit() { 3263 long rawContactId = createRawContact(); 3264 ContentValues values = buildGenericStreamItemValues(); 3265 values.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3266 3267 List<Long> streamItemIds = Lists.newArrayList(); 3268 3269 // Insert MAX + 1 stream items. 3270 long baseTime = System.currentTimeMillis(); 3271 for (int i = 0; i < 6; i++) { 3272 values.put(StreamItems.TIMESTAMP, baseTime + i); 3273 Uri resultUri = mResolver.insert(StreamItems.CONTENT_URI, values); 3274 streamItemIds.add(ContentUris.parseId(resultUri)); 3275 } 3276 Long doomedStreamItemId = streamItemIds.get(0); 3277 3278 // There should only be MAX items. The oldest one should have been cleaned up. 3279 Cursor c = mResolver.query( 3280 Uri.withAppendedPath( 3281 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3282 RawContacts.StreamItems.CONTENT_DIRECTORY), 3283 new String[]{StreamItems._ID}, null, null, null); 3284 try { 3285 while(c.moveToNext()) { 3286 long streamItemId = c.getLong(0); 3287 streamItemIds.remove(streamItemId); 3288 } 3289 } finally { 3290 c.close(); 3291 } 3292 3293 assertEquals(1, streamItemIds.size()); 3294 assertEquals(doomedStreamItemId, streamItemIds.get(0)); 3295 } 3296 3297 public void testInsertStreamItemOlderThanOldestInLimit() { 3298 long rawContactId = createRawContact(); 3299 ContentValues values = buildGenericStreamItemValues(); 3300 values.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3301 3302 // Insert MAX stream items. 3303 long baseTime = System.currentTimeMillis(); 3304 for (int i = 0; i < 5; i++) { 3305 values.put(StreamItems.TIMESTAMP, baseTime + i); 3306 Uri resultUri = mResolver.insert(StreamItems.CONTENT_URI, values); 3307 assertNotSame("Expected non-0 stream item ID to be inserted", 3308 0L, ContentUris.parseId(resultUri)); 3309 } 3310 3311 // Now try to insert a stream item that's older. It should be deleted immediately 3312 // and return an ID of 0. 3313 values.put(StreamItems.TIMESTAMP, baseTime - 1); 3314 Uri resultUri = mResolver.insert(StreamItems.CONTENT_URI, values); 3315 assertEquals(0L, ContentUris.parseId(resultUri)); 3316 } 3317 3318 // Stream item photo insertion test cases. 3319 3320 public void testInsertStreamItemsAndPhotosInBatch() throws Exception { 3321 long rawContactId = createRawContact(); 3322 ContentValues streamItemValues = buildGenericStreamItemValues(); 3323 ContentValues streamItemPhotoValues = buildGenericStreamItemPhotoValues(0); 3324 3325 ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 3326 ops.add(ContentProviderOperation.newInsert( 3327 Uri.withAppendedPath( 3328 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3329 RawContacts.StreamItems.CONTENT_DIRECTORY)) 3330 .withValues(streamItemValues).build()); 3331 for (int i = 0; i < 5; i++) { 3332 streamItemPhotoValues.put(StreamItemPhotos.SORT_INDEX, i); 3333 ops.add(ContentProviderOperation.newInsert(StreamItems.CONTENT_PHOTO_URI) 3334 .withValues(streamItemPhotoValues) 3335 .withValueBackReference(StreamItemPhotos.STREAM_ITEM_ID, 0) 3336 .build()); 3337 } 3338 mResolver.applyBatch(ContactsContract.AUTHORITY, ops); 3339 3340 // Check that all five photos were inserted under the raw contact. 3341 Cursor c = mResolver.query(StreamItems.CONTENT_URI, new String[]{StreamItems._ID}, 3342 StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 3343 null); 3344 long streamItemId = 0; 3345 try { 3346 assertEquals(1, c.getCount()); 3347 c.moveToFirst(); 3348 streamItemId = c.getLong(0); 3349 } finally { 3350 c.close(); 3351 } 3352 3353 c = mResolver.query(Uri.withAppendedPath( 3354 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3355 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3356 new String[]{StreamItemPhotos._ID, StreamItemPhotos.PHOTO_URI}, 3357 null, null, null); 3358 try { 3359 assertEquals(5, c.getCount()); 3360 byte[] expectedPhotoBytes = loadPhotoFromResource( 3361 R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO); 3362 while (c.moveToNext()) { 3363 String photoUri = c.getString(1); 3364 assertInputStreamContent(expectedPhotoBytes, 3365 mResolver.openInputStream(Uri.parse(photoUri))); 3366 } 3367 } finally { 3368 c.close(); 3369 } 3370 } 3371 3372 // Stream item update test cases. 3373 3374 public void testUpdateStreamItemById() { 3375 long rawContactId = createRawContact(); 3376 ContentValues values = buildGenericStreamItemValues(); 3377 Uri resultUri = insertStreamItem(rawContactId, values, null); 3378 long streamItemId = ContentUris.parseId(resultUri); 3379 values.put(StreamItems.TEXT, "Goodbye world"); 3380 mResolver.update(ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), values, 3381 null, null); 3382 assertStoredValues(Uri.withAppendedPath( 3383 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3384 RawContacts.StreamItems.CONTENT_DIRECTORY), values); 3385 } 3386 3387 public void testUpdateStreamItemWithContentValues() { 3388 long rawContactId = createRawContact(); 3389 ContentValues values = buildGenericStreamItemValues(); 3390 Uri resultUri = insertStreamItem(rawContactId, values, null); 3391 long streamItemId = ContentUris.parseId(resultUri); 3392 values.put(StreamItems._ID, streamItemId); 3393 values.put(StreamItems.TEXT, "Goodbye world"); 3394 mResolver.update(StreamItems.CONTENT_URI, values, null, null); 3395 assertStoredValues(Uri.withAppendedPath( 3396 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3397 RawContacts.StreamItems.CONTENT_DIRECTORY), values); 3398 } 3399 3400 public void testUpdateStreamItemFromOtherAccount() { 3401 long rawContactId = createRawContact(mAccount); 3402 ContentValues values = buildGenericStreamItemValues(); 3403 Uri resultUri = insertStreamItem(rawContactId, values, mAccount); 3404 long streamItemId = ContentUris.parseId(resultUri); 3405 values.put(StreamItems._ID, streamItemId); 3406 values.put(StreamItems.TEXT, "Goodbye world"); 3407 try { 3408 mResolver.update(maybeAddAccountQueryParameters(StreamItems.CONTENT_URI, mAccountTwo), 3409 values, null, null); 3410 fail("Should not be able to update stream items inserted by another account"); 3411 } catch (SecurityException expected) { 3412 // Can't update the stream items from another account. 3413 } 3414 } 3415 3416 // Stream item photo update test cases. 3417 3418 public void testUpdateStreamItemPhotoById() throws IOException { 3419 long rawContactId = createRawContact(); 3420 ContentValues values = buildGenericStreamItemValues(); 3421 Uri resultUri = insertStreamItem(rawContactId, values, null); 3422 long streamItemId = ContentUris.parseId(resultUri); 3423 ContentValues photoValues = buildGenericStreamItemPhotoValues(1); 3424 resultUri = insertStreamItemPhoto(streamItemId, photoValues, null); 3425 long streamItemPhotoId = ContentUris.parseId(resultUri); 3426 3427 photoValues.put(StreamItemPhotos.PHOTO, loadPhotoFromResource( 3428 R.drawable.nebula, PhotoSize.ORIGINAL)); 3429 Uri photoUri = 3430 ContentUris.withAppendedId( 3431 Uri.withAppendedPath( 3432 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3433 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3434 streamItemPhotoId); 3435 mResolver.update(photoUri, photoValues, null, null); 3436 photoValues.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3437 assertStoredValues(photoUri, photoValues); 3438 3439 // Check that the photo stored is the expected one. 3440 String displayPhotoUri = getStoredValue(photoUri, StreamItemPhotos.PHOTO_URI); 3441 assertInputStreamContent(loadPhotoFromResource(R.drawable.nebula, PhotoSize.DISPLAY_PHOTO), 3442 mResolver.openInputStream(Uri.parse(displayPhotoUri))); 3443 } 3444 3445 public void testUpdateStreamItemPhotoWithContentValues() throws IOException { 3446 long rawContactId = createRawContact(); 3447 ContentValues values = buildGenericStreamItemValues(); 3448 Uri resultUri = insertStreamItem(rawContactId, values, null); 3449 long streamItemId = ContentUris.parseId(resultUri); 3450 ContentValues photoValues = buildGenericStreamItemPhotoValues(1); 3451 resultUri = insertStreamItemPhoto(streamItemId, photoValues, null); 3452 long streamItemPhotoId = ContentUris.parseId(resultUri); 3453 3454 photoValues.put(StreamItemPhotos._ID, streamItemPhotoId); 3455 photoValues.put(StreamItemPhotos.PHOTO, loadPhotoFromResource( 3456 R.drawable.nebula, PhotoSize.ORIGINAL)); 3457 Uri photoUri = 3458 Uri.withAppendedPath( 3459 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3460 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3461 mResolver.update(photoUri, photoValues, null, null); 3462 photoValues.remove(StreamItemPhotos.PHOTO); // Removed during processing. 3463 assertStoredValues(photoUri, photoValues); 3464 3465 // Check that the photo stored is the expected one. 3466 String displayPhotoUri = getStoredValue(photoUri, StreamItemPhotos.PHOTO_URI); 3467 assertInputStreamContent(loadPhotoFromResource(R.drawable.nebula, PhotoSize.DISPLAY_PHOTO), 3468 mResolver.openInputStream(Uri.parse(displayPhotoUri))); 3469 } 3470 3471 public void testUpdateStreamItemPhotoFromOtherAccount() { 3472 long rawContactId = createRawContact(mAccount); 3473 ContentValues values = buildGenericStreamItemValues(); 3474 Uri resultUri = insertStreamItem(rawContactId, values, mAccount); 3475 long streamItemId = ContentUris.parseId(resultUri); 3476 ContentValues photoValues = buildGenericStreamItemPhotoValues(1); 3477 resultUri = insertStreamItemPhoto(streamItemId, photoValues, mAccount); 3478 long streamItemPhotoId = ContentUris.parseId(resultUri); 3479 3480 photoValues.put(StreamItemPhotos._ID, streamItemPhotoId); 3481 photoValues.put(StreamItemPhotos.PHOTO, loadPhotoFromResource( 3482 R.drawable.galaxy, PhotoSize.ORIGINAL)); 3483 Uri photoUri = 3484 maybeAddAccountQueryParameters( 3485 Uri.withAppendedPath( 3486 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3487 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3488 mAccountTwo); 3489 try { 3490 mResolver.update(photoUri, photoValues, null, null); 3491 fail("Should not be able to update stream item photos inserted by another account"); 3492 } catch (SecurityException expected) { 3493 // Can't update a stream item photo inserted by another account. 3494 } 3495 } 3496 3497 // Stream item deletion test cases. 3498 3499 public void testDeleteStreamItemById() { 3500 long rawContactId = createRawContact(); 3501 ContentValues firstValues = buildGenericStreamItemValues(); 3502 Uri resultUri = insertStreamItem(rawContactId, firstValues, null); 3503 long firstStreamItemId = ContentUris.parseId(resultUri); 3504 3505 ContentValues secondValues = buildGenericStreamItemValues(); 3506 secondValues.put(StreamItems.TEXT, "Goodbye world"); 3507 insertStreamItem(rawContactId, secondValues, null); 3508 3509 // Delete the first stream item. 3510 mResolver.delete(ContentUris.withAppendedId(StreamItems.CONTENT_URI, firstStreamItemId), 3511 null, null); 3512 3513 // Check that only the second item remains. 3514 assertStoredValues(Uri.withAppendedPath( 3515 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3516 RawContacts.StreamItems.CONTENT_DIRECTORY), secondValues); 3517 } 3518 3519 public void testDeleteStreamItemWithSelection() { 3520 long rawContactId = createRawContact(); 3521 ContentValues firstValues = buildGenericStreamItemValues(); 3522 insertStreamItem(rawContactId, firstValues, null); 3523 3524 ContentValues secondValues = buildGenericStreamItemValues(); 3525 secondValues.put(StreamItems.TEXT, "Goodbye world"); 3526 insertStreamItem(rawContactId, secondValues, null); 3527 3528 // Delete the first stream item with a custom selection. 3529 mResolver.delete(StreamItems.CONTENT_URI, StreamItems.TEXT + "=?", 3530 new String[]{"Hello world"}); 3531 3532 // Check that only the second item remains. 3533 assertStoredValues(Uri.withAppendedPath( 3534 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 3535 RawContacts.StreamItems.CONTENT_DIRECTORY), secondValues); 3536 } 3537 3538 public void testDeleteStreamItemFromOtherAccount() { 3539 long rawContactId = createRawContact(mAccount); 3540 long streamItemId = ContentUris.parseId( 3541 insertStreamItem(rawContactId, buildGenericStreamItemValues(), mAccount)); 3542 try { 3543 mResolver.delete( 3544 maybeAddAccountQueryParameters( 3545 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3546 mAccountTwo), null, null); 3547 fail("Should not be able to delete stream item inserted by another account"); 3548 } catch (SecurityException expected) { 3549 // Can't delete a stream item from another account. 3550 } 3551 } 3552 3553 // Stream item photo deletion test cases. 3554 3555 public void testDeleteStreamItemPhotoById() { 3556 long rawContactId = createRawContact(); 3557 long streamItemId = ContentUris.parseId( 3558 insertStreamItem(rawContactId, buildGenericStreamItemValues(), null)); 3559 long streamItemPhotoId = ContentUris.parseId( 3560 insertStreamItemPhoto(streamItemId, buildGenericStreamItemPhotoValues(0), null)); 3561 mResolver.delete( 3562 ContentUris.withAppendedId( 3563 Uri.withAppendedPath( 3564 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3565 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3566 streamItemPhotoId), null, null); 3567 3568 Cursor c = mResolver.query(StreamItems.CONTENT_PHOTO_URI, 3569 new String[]{StreamItemPhotos._ID}, 3570 StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{String.valueOf(streamItemId)}, 3571 null); 3572 try { 3573 assertEquals("Expected photo to be deleted.", 0, c.getCount()); 3574 } finally { 3575 c.close(); 3576 } 3577 } 3578 3579 public void testDeleteStreamItemPhotoWithSelection() { 3580 long rawContactId = createRawContact(); 3581 long streamItemId = ContentUris.parseId( 3582 insertStreamItem(rawContactId, buildGenericStreamItemValues(), null)); 3583 ContentValues firstPhotoValues = buildGenericStreamItemPhotoValues(0); 3584 ContentValues secondPhotoValues = buildGenericStreamItemPhotoValues(1); 3585 insertStreamItemPhoto(streamItemId, firstPhotoValues, null); 3586 firstPhotoValues.remove(StreamItemPhotos.PHOTO); // Removed while processing. 3587 insertStreamItemPhoto(streamItemId, secondPhotoValues, null); 3588 Uri photoUri = Uri.withAppendedPath( 3589 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3590 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 3591 mResolver.delete(photoUri, StreamItemPhotos.SORT_INDEX + "=1", null); 3592 3593 assertStoredValues(photoUri, firstPhotoValues); 3594 } 3595 3596 public void testDeleteStreamItemPhotoFromOtherAccount() { 3597 long rawContactId = createRawContact(mAccount); 3598 long streamItemId = ContentUris.parseId( 3599 insertStreamItem(rawContactId, buildGenericStreamItemValues(), mAccount)); 3600 insertStreamItemPhoto(streamItemId, buildGenericStreamItemPhotoValues(0), mAccount); 3601 try { 3602 mResolver.delete(maybeAddAccountQueryParameters( 3603 Uri.withAppendedPath( 3604 ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId), 3605 StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), 3606 mAccountTwo), null, null); 3607 fail("Should not be able to delete stream item photo inserted by another account"); 3608 } catch (SecurityException expected) { 3609 // Can't delete a stream item photo from another account. 3610 } 3611 } 3612 3613 public void testQueryStreamItemLimit() { 3614 ContentValues values = new ContentValues(); 3615 values.put(StreamItems.MAX_ITEMS, 5); 3616 assertStoredValues(StreamItems.CONTENT_LIMIT_URI, values); 3617 } 3618 3619 // Tests for inserting or updating stream items as a side-effect of making status updates 3620 // (forward-compatibility of status updates into the new social stream API). 3621 3622 public void testStreamItemInsertedOnStatusUpdate() { 3623 3624 // This method of creating a raw contact automatically inserts a status update with 3625 // the status message "hacking". 3626 ContentValues values = new ContentValues(); 3627 long rawContactId = createRawContact(values, "18004664411", 3628 "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 3629 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 3630 StatusUpdates.CAPABILITY_HAS_VOICE); 3631 3632 ContentValues expectedValues = new ContentValues(); 3633 expectedValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3634 expectedValues.put(StreamItems.TEXT, "hacking"); 3635 assertStoredValues(RawContacts.CONTENT_URI.buildUpon() 3636 .appendPath(String.valueOf(rawContactId)) 3637 .appendPath(RawContacts.StreamItems.CONTENT_DIRECTORY).build(), 3638 expectedValues); 3639 } 3640 3641 public void testStreamItemUpdatedOnSecondStatusUpdate() { 3642 3643 // This method of creating a raw contact automatically inserts a status update with 3644 // the status message "hacking". 3645 ContentValues values = new ContentValues(); 3646 int chatMode = StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO | 3647 StatusUpdates.CAPABILITY_HAS_VOICE; 3648 long rawContactId = createRawContact(values, "18004664411", 3649 "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, chatMode); 3650 3651 // Insert a new status update for the raw contact. 3652 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "goog411@acme.com", 3653 StatusUpdates.INVISIBLE, "finished hacking", chatMode); 3654 3655 ContentValues expectedValues = new ContentValues(); 3656 expectedValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3657 expectedValues.put(StreamItems.TEXT, "finished hacking"); 3658 assertStoredValues(RawContacts.CONTENT_URI.buildUpon() 3659 .appendPath(String.valueOf(rawContactId)) 3660 .appendPath(RawContacts.StreamItems.CONTENT_DIRECTORY).build(), 3661 expectedValues); 3662 } 3663 3664 private ContentValues buildGenericStreamItemValues() { 3665 ContentValues values = new ContentValues(); 3666 values.put(StreamItems.TEXT, "Hello world"); 3667 values.put(StreamItems.TIMESTAMP, System.currentTimeMillis()); 3668 values.put(StreamItems.COMMENTS, "Reshared by 123 others"); 3669 return values; 3670 } 3671 3672 private ContentValues buildGenericStreamItemPhotoValues(int sortIndex) { 3673 ContentValues values = new ContentValues(); 3674 values.put(StreamItemPhotos.SORT_INDEX, sortIndex); 3675 values.put(StreamItemPhotos.PHOTO, 3676 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.ORIGINAL)); 3677 return values; 3678 } 3679 3680 public void testSingleStatusUpdateRowPerContact() { 3681 int protocol1 = Im.PROTOCOL_GOOGLE_TALK; 3682 String handle1 = "test@gmail.com"; 3683 3684 long rawContactId1 = createRawContact(); 3685 insertImHandle(rawContactId1, protocol1, null, handle1); 3686 3687 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AVAILABLE, "Green", 3688 StatusUpdates.CAPABILITY_HAS_CAMERA); 3689 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.AWAY, "Yellow", 3690 StatusUpdates.CAPABILITY_HAS_CAMERA); 3691 insertStatusUpdate(protocol1, null, handle1, StatusUpdates.INVISIBLE, "Red", 3692 StatusUpdates.CAPABILITY_HAS_CAMERA); 3693 3694 Cursor c = queryContact(queryContactId(rawContactId1), 3695 new String[] {Contacts.CONTACT_PRESENCE, Contacts.CONTACT_STATUS}); 3696 assertEquals(1, c.getCount()); 3697 3698 c.moveToFirst(); 3699 assertEquals(StatusUpdates.INVISIBLE, c.getInt(0)); 3700 assertEquals("Red", c.getString(1)); 3701 c.close(); 3702 } 3703 3704 private void updateSendToVoicemailAndRingtone(long contactId, boolean sendToVoicemail, 3705 String ringtone) { 3706 ContentValues values = new ContentValues(); 3707 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 3708 if (ringtone != null) { 3709 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 3710 } 3711 3712 final Uri uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 3713 int count = mResolver.update(uri, values, null, null); 3714 assertEquals(1, count); 3715 } 3716 3717 private void updateSendToVoicemailAndRingtoneWithSelection(long contactId, 3718 boolean sendToVoicemail, String ringtone) { 3719 ContentValues values = new ContentValues(); 3720 values.put(Contacts.SEND_TO_VOICEMAIL, sendToVoicemail); 3721 if (ringtone != null) { 3722 values.put(Contacts.CUSTOM_RINGTONE, ringtone); 3723 } 3724 3725 int count = mResolver.update(Contacts.CONTENT_URI, values, Contacts._ID + "=" + contactId, 3726 null); 3727 assertEquals(1, count); 3728 } 3729 3730 private void assertSendToVoicemailAndRingtone(long contactId, boolean expectedSendToVoicemail, 3731 String expectedRingtone) { 3732 Cursor c = queryContact(contactId); 3733 assertTrue(c.moveToNext()); 3734 int sendToVoicemail = c.getInt(c.getColumnIndex(Contacts.SEND_TO_VOICEMAIL)); 3735 assertEquals(expectedSendToVoicemail ? 1 : 0, sendToVoicemail); 3736 String ringtone = c.getString(c.getColumnIndex(Contacts.CUSTOM_RINGTONE)); 3737 if (expectedRingtone == null) { 3738 assertNull(ringtone); 3739 } else { 3740 assertTrue(ArrayUtils.contains(expectedRingtone.split(","), ringtone)); 3741 } 3742 c.close(); 3743 } 3744 3745 public void testContactVisibilityUpdateOnMembershipChange() { 3746 long rawContactId = createRawContact(mAccount); 3747 assertVisibility(rawContactId, "0"); 3748 3749 long visibleGroupId = createGroup(mAccount, "123", "Visible", 1); 3750 long invisibleGroupId = createGroup(mAccount, "567", "Invisible", 0); 3751 3752 Uri membership1 = insertGroupMembership(rawContactId, visibleGroupId); 3753 assertVisibility(rawContactId, "1"); 3754 3755 Uri membership2 = insertGroupMembership(rawContactId, invisibleGroupId); 3756 assertVisibility(rawContactId, "1"); 3757 3758 mResolver.delete(membership1, null, null); 3759 assertVisibility(rawContactId, "0"); 3760 3761 ContentValues values = new ContentValues(); 3762 values.put(GroupMembership.GROUP_ROW_ID, visibleGroupId); 3763 3764 mResolver.update(membership2, values, null, null); 3765 assertVisibility(rawContactId, "1"); 3766 } 3767 3768 private void assertVisibility(long rawContactId, String expectedValue) { 3769 assertStoredValue(Contacts.CONTENT_URI, Contacts._ID + "=" + queryContactId(rawContactId), 3770 null, Contacts.IN_VISIBLE_GROUP, expectedValue); 3771 } 3772 3773 public void testSupplyingBothValuesAndParameters() throws Exception { 3774 Account account = new Account("account 1", "type%/:1"); 3775 Uri uri = ContactsContract.Groups.CONTENT_URI.buildUpon() 3776 .appendQueryParameter(ContactsContract.Groups.ACCOUNT_NAME, account.name) 3777 .appendQueryParameter(ContactsContract.Groups.ACCOUNT_TYPE, account.type) 3778 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 3779 .build(); 3780 3781 ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(uri); 3782 builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type); 3783 builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name); 3784 builder.withValue(ContactsContract.Groups.SYSTEM_ID, "some id"); 3785 builder.withValue(ContactsContract.Groups.TITLE, "some name"); 3786 builder.withValue(ContactsContract.Groups.GROUP_VISIBLE, 1); 3787 3788 mResolver.applyBatch(ContactsContract.AUTHORITY, Lists.newArrayList(builder.build())); 3789 3790 builder = ContentProviderOperation.newInsert(uri); 3791 builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type + "diff"); 3792 builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name); 3793 builder.withValue(ContactsContract.Groups.SYSTEM_ID, "some other id"); 3794 builder.withValue(ContactsContract.Groups.TITLE, "some other name"); 3795 builder.withValue(ContactsContract.Groups.GROUP_VISIBLE, 1); 3796 3797 try { 3798 mResolver.applyBatch(ContactsContract.AUTHORITY, Lists.newArrayList(builder.build())); 3799 fail("Expected IllegalArgumentException"); 3800 } catch (IllegalArgumentException ex) { 3801 // Expected 3802 } 3803 } 3804 3805 public void testContentEntityIterator() { 3806 // create multiple contacts and check that the selected ones are returned 3807 long id; 3808 3809 long groupId1 = createGroup(mAccount, "gsid1", "title1"); 3810 long groupId2 = createGroup(mAccount, "gsid2", "title2"); 3811 3812 id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c0"); 3813 insertGroupMembership(id, "gsid1"); 3814 insertEmail(id, "c0@email.com"); 3815 insertPhoneNumber(id, "5551212c0"); 3816 3817 long c1 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c1"); 3818 Uri id_1_0 = insertGroupMembership(id, "gsid1"); 3819 Uri id_1_1 = insertGroupMembership(id, "gsid2"); 3820 Uri id_1_2 = insertEmail(id, "c1@email.com"); 3821 Uri id_1_3 = insertPhoneNumber(id, "5551212c1"); 3822 3823 long c2 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c2"); 3824 Uri id_2_0 = insertGroupMembership(id, "gsid1"); 3825 Uri id_2_1 = insertEmail(id, "c2@email.com"); 3826 Uri id_2_2 = insertPhoneNumber(id, "5551212c2"); 3827 3828 long c3 = id = createRawContact(mAccount, RawContacts.SOURCE_ID, "c3"); 3829 Uri id_3_0 = insertGroupMembership(id, groupId2); 3830 Uri id_3_1 = insertEmail(id, "c3@email.com"); 3831 Uri id_3_2 = insertPhoneNumber(id, "5551212c3"); 3832 3833 EntityIterator iterator = RawContacts.newEntityIterator(mResolver.query( 3834 maybeAddAccountQueryParameters(RawContactsEntity.CONTENT_URI, mAccount), null, 3835 RawContacts.SOURCE_ID + " in ('c1', 'c2', 'c3')", null, null)); 3836 Entity entity; 3837 ContentValues[] subValues; 3838 entity = iterator.next(); 3839 assertEquals(c1, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 3840 subValues = asSortedContentValuesArray(entity.getSubValues()); 3841 assertEquals(4, subValues.length); 3842 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 3843 Data._ID, id_1_0, 3844 GroupMembership.GROUP_ROW_ID, groupId1, 3845 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 3846 assertDataRow(subValues[1], GroupMembership.CONTENT_ITEM_TYPE, 3847 Data._ID, id_1_1, 3848 GroupMembership.GROUP_ROW_ID, groupId2, 3849 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 3850 assertDataRow(subValues[2], Email.CONTENT_ITEM_TYPE, 3851 Data._ID, id_1_2, 3852 Email.DATA, "c1@email.com"); 3853 assertDataRow(subValues[3], Phone.CONTENT_ITEM_TYPE, 3854 Data._ID, id_1_3, 3855 Email.DATA, "5551212c1"); 3856 3857 entity = iterator.next(); 3858 assertEquals(c2, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 3859 subValues = asSortedContentValuesArray(entity.getSubValues()); 3860 assertEquals(3, subValues.length); 3861 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 3862 Data._ID, id_2_0, 3863 GroupMembership.GROUP_ROW_ID, groupId1, 3864 GroupMembership.GROUP_SOURCE_ID, "gsid1"); 3865 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 3866 Data._ID, id_2_1, 3867 Email.DATA, "c2@email.com"); 3868 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 3869 Data._ID, id_2_2, 3870 Email.DATA, "5551212c2"); 3871 3872 entity = iterator.next(); 3873 assertEquals(c3, (long) entity.getEntityValues().getAsLong(RawContacts._ID)); 3874 subValues = asSortedContentValuesArray(entity.getSubValues()); 3875 assertEquals(3, subValues.length); 3876 assertDataRow(subValues[0], GroupMembership.CONTENT_ITEM_TYPE, 3877 Data._ID, id_3_0, 3878 GroupMembership.GROUP_ROW_ID, groupId2, 3879 GroupMembership.GROUP_SOURCE_ID, "gsid2"); 3880 assertDataRow(subValues[1], Email.CONTENT_ITEM_TYPE, 3881 Data._ID, id_3_1, 3882 Email.DATA, "c3@email.com"); 3883 assertDataRow(subValues[2], Phone.CONTENT_ITEM_TYPE, 3884 Data._ID, id_3_2, 3885 Email.DATA, "5551212c3"); 3886 3887 assertFalse(iterator.hasNext()); 3888 iterator.close(); 3889 } 3890 3891 public void testDataCreateUpdateDeleteByMimeType() throws Exception { 3892 long rawContactId = createRawContact(); 3893 3894 ContentValues values = new ContentValues(); 3895 values.put(Data.RAW_CONTACT_ID, rawContactId); 3896 values.put(Data.MIMETYPE, "testmimetype"); 3897 values.put(Data.RES_PACKAGE, "oldpackage"); 3898 values.put(Data.IS_PRIMARY, 1); 3899 values.put(Data.IS_SUPER_PRIMARY, 1); 3900 values.put(Data.DATA1, "old1"); 3901 values.put(Data.DATA2, "old2"); 3902 values.put(Data.DATA3, "old3"); 3903 values.put(Data.DATA4, "old4"); 3904 values.put(Data.DATA5, "old5"); 3905 values.put(Data.DATA6, "old6"); 3906 values.put(Data.DATA7, "old7"); 3907 values.put(Data.DATA8, "old8"); 3908 values.put(Data.DATA9, "old9"); 3909 values.put(Data.DATA10, "old10"); 3910 values.put(Data.DATA11, "old11"); 3911 values.put(Data.DATA12, "old12"); 3912 values.put(Data.DATA13, "old13"); 3913 values.put(Data.DATA14, "old14"); 3914 values.put(Data.DATA15, "old15"); 3915 Uri uri = mResolver.insert(Data.CONTENT_URI, values); 3916 assertStoredValues(uri, values); 3917 assertNetworkNotified(true); 3918 3919 values.clear(); 3920 values.put(Data.RES_PACKAGE, "newpackage"); 3921 values.put(Data.IS_PRIMARY, 0); 3922 values.put(Data.IS_SUPER_PRIMARY, 0); 3923 values.put(Data.DATA1, "new1"); 3924 values.put(Data.DATA2, "new2"); 3925 values.put(Data.DATA3, "new3"); 3926 values.put(Data.DATA4, "new4"); 3927 values.put(Data.DATA5, "new5"); 3928 values.put(Data.DATA6, "new6"); 3929 values.put(Data.DATA7, "new7"); 3930 values.put(Data.DATA8, "new8"); 3931 values.put(Data.DATA9, "new9"); 3932 values.put(Data.DATA10, "new10"); 3933 values.put(Data.DATA11, "new11"); 3934 values.put(Data.DATA12, "new12"); 3935 values.put(Data.DATA13, "new13"); 3936 values.put(Data.DATA14, "new14"); 3937 values.put(Data.DATA15, "new15"); 3938 mResolver.update(Data.CONTENT_URI, values, Data.RAW_CONTACT_ID + "=" + rawContactId + 3939 " AND " + Data.MIMETYPE + "='testmimetype'", null); 3940 assertNetworkNotified(true); 3941 3942 assertStoredValues(uri, values); 3943 3944 int count = mResolver.delete(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 3945 + " AND " + Data.MIMETYPE + "='testmimetype'", null); 3946 assertEquals(1, count); 3947 assertEquals(0, getCount(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId 3948 + " AND " + Data.MIMETYPE + "='testmimetype'", null)); 3949 assertNetworkNotified(true); 3950 } 3951 3952 public void testRawContactQuery() { 3953 Account account1 = new Account("a", "b"); 3954 Account account2 = new Account("c", "d"); 3955 long rawContactId1 = createRawContact(account1); 3956 long rawContactId2 = createRawContact(account2); 3957 3958 Uri uri1 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account1); 3959 Uri uri2 = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, account2); 3960 assertEquals(1, getCount(uri1, null, null)); 3961 assertEquals(1, getCount(uri2, null, null)); 3962 assertStoredValue(uri1, RawContacts._ID, rawContactId1) ; 3963 assertStoredValue(uri2, RawContacts._ID, rawContactId2) ; 3964 3965 Uri rowUri1 = ContentUris.withAppendedId(uri1, rawContactId1); 3966 Uri rowUri2 = ContentUris.withAppendedId(uri2, rawContactId2); 3967 assertStoredValue(rowUri1, RawContacts._ID, rawContactId1) ; 3968 assertStoredValue(rowUri2, RawContacts._ID, rawContactId2) ; 3969 } 3970 3971 public void testRawContactDeletion() { 3972 long rawContactId = createRawContact(mAccount); 3973 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 3974 3975 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 3976 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 3977 StatusUpdates.AVAILABLE, null, 3978 StatusUpdates.CAPABILITY_HAS_CAMERA); 3979 long contactId = queryContactId(rawContactId); 3980 3981 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 3982 null, null)); 3983 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 3984 + rawContactId, null)); 3985 3986 mResolver.delete(uri, null, null); 3987 3988 assertStoredValue(uri, RawContacts.DELETED, "1"); 3989 assertNetworkNotified(true); 3990 3991 Uri permanentDeletionUri = setCallerIsSyncAdapter(uri, mAccount); 3992 mResolver.delete(permanentDeletionUri, null, null); 3993 assertEquals(0, getCount(uri, null, null)); 3994 assertEquals(0, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 3995 null, null)); 3996 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 3997 + rawContactId, null)); 3998 assertEquals(0, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 3999 assertNetworkNotified(false); 4000 } 4001 4002 public void testRawContactDeletionKeepingAggregateContact() { 4003 long rawContactId1 = createRawContactWithName(mAccount); 4004 long rawContactId2 = createRawContactWithName(mAccount); 4005 setAggregationException( 4006 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 4007 4008 long contactId = queryContactId(rawContactId1); 4009 4010 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 4011 Uri permanentDeletionUri = setCallerIsSyncAdapter(uri, mAccount); 4012 mResolver.delete(permanentDeletionUri, null, null); 4013 assertEquals(0, getCount(uri, null, null)); 4014 assertEquals(1, getCount(Contacts.CONTENT_URI, Contacts._ID + "=" + contactId, null)); 4015 } 4016 4017 public void testRawContactDeletionWithAccounts() { 4018 long rawContactId = createRawContact(mAccount); 4019 Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 4020 4021 insertImHandle(rawContactId, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 4022 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 4023 StatusUpdates.AVAILABLE, null, 4024 StatusUpdates.CAPABILITY_HAS_CAMERA); 4025 assertEquals(1, getCount(Uri.withAppendedPath(uri, RawContacts.Data.CONTENT_DIRECTORY), 4026 null, null)); 4027 assertEquals(1, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 4028 + rawContactId, null)); 4029 4030 // Do not delete if we are deleting with wrong account. 4031 Uri deleteWithWrongAccountUri = 4032 RawContacts.CONTENT_URI.buildUpon() 4033 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccountTwo.name) 4034 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccountTwo.type) 4035 .build(); 4036 mResolver.delete(deleteWithWrongAccountUri, null, null); 4037 4038 assertStoredValue(uri, RawContacts.DELETED, "0"); 4039 4040 // Delete if we are deleting with correct account. 4041 Uri deleteWithCorrectAccountUri = 4042 RawContacts.CONTENT_URI.buildUpon() 4043 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccount.name) 4044 .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, mAccount.type) 4045 .build(); 4046 mResolver.delete(deleteWithCorrectAccountUri, null, null); 4047 4048 assertStoredValue(uri, RawContacts.DELETED, "1"); 4049 } 4050 4051 public void testAccountsUpdated() { 4052 // This is to ensure we do not delete contacts with null, null (account name, type) 4053 // accidentally. 4054 long rawContactId3 = createRawContactWithName("James", "Sullivan"); 4055 insertPhoneNumber(rawContactId3, "5234567890"); 4056 Uri rawContact3 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId3); 4057 assertEquals(1, getCount(RawContacts.CONTENT_URI, null, null)); 4058 4059 ContactsProvider2 cp = (ContactsProvider2) getProvider(); 4060 mActor.setAccounts(new Account[]{mAccount, mAccountTwo}); 4061 cp.onAccountsUpdated(new Account[]{mAccount, mAccountTwo}); 4062 assertEquals(1, getCount(RawContacts.CONTENT_URI, null, null)); 4063 assertStoredValue(rawContact3, RawContacts.ACCOUNT_NAME, null); 4064 assertStoredValue(rawContact3, RawContacts.ACCOUNT_TYPE, null); 4065 4066 long rawContactId1 = createRawContact(mAccount); 4067 insertEmail(rawContactId1, "account1@email.com"); 4068 long rawContactId2 = createRawContact(mAccountTwo); 4069 insertEmail(rawContactId2, "account2@email.com"); 4070 insertImHandle(rawContactId2, Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com"); 4071 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, "deleteme@android.com", 4072 StatusUpdates.AVAILABLE, null, 4073 StatusUpdates.CAPABILITY_HAS_CAMERA); 4074 4075 mActor.setAccounts(new Account[]{mAccount}); 4076 cp.onAccountsUpdated(new Account[]{mAccount}); 4077 assertEquals(2, getCount(RawContacts.CONTENT_URI, null, null)); 4078 assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" 4079 + rawContactId2, null)); 4080 } 4081 4082 public void testAccountDeletion() { 4083 Account readOnlyAccount = new Account("act", READ_ONLY_ACCOUNT_TYPE); 4084 ContactsProvider2 cp = (ContactsProvider2) getProvider(); 4085 mActor.setAccounts(new Account[]{readOnlyAccount, mAccount}); 4086 cp.onAccountsUpdated(new Account[]{readOnlyAccount, mAccount}); 4087 4088 long rawContactId1 = createRawContactWithName("John", "Doe", readOnlyAccount); 4089 Uri photoUri1 = insertPhoto(rawContactId1); 4090 long rawContactId2 = createRawContactWithName("john", "doe", mAccount); 4091 Uri photoUri2 = insertPhoto(rawContactId2); 4092 storeValue(photoUri2, Photo.IS_SUPER_PRIMARY, "1"); 4093 4094 assertAggregated(rawContactId1, rawContactId2); 4095 4096 long contactId = queryContactId(rawContactId1); 4097 4098 // The display name should come from the writable account 4099 assertStoredValue(Uri.withAppendedPath( 4100 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4101 Contacts.Data.CONTENT_DIRECTORY), 4102 Contacts.DISPLAY_NAME, "john doe"); 4103 4104 // The photo should be the one we marked as super-primary 4105 assertStoredValue(Contacts.CONTENT_URI, contactId, 4106 Contacts.PHOTO_ID, ContentUris.parseId(photoUri2)); 4107 4108 mActor.setAccounts(new Account[]{readOnlyAccount}); 4109 // Remove the writable account 4110 cp.onAccountsUpdated(new Account[]{readOnlyAccount}); 4111 4112 // The display name should come from the remaining account 4113 assertStoredValue(Uri.withAppendedPath( 4114 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4115 Contacts.Data.CONTENT_DIRECTORY), 4116 Contacts.DISPLAY_NAME, "John Doe"); 4117 4118 // The photo should be the remaining one 4119 assertStoredValue(Contacts.CONTENT_URI, contactId, 4120 Contacts.PHOTO_ID, ContentUris.parseId(photoUri1)); 4121 } 4122 4123 public void testContactDeletion() { 4124 long rawContactId1 = createRawContactWithName("John", "Doe", ACCOUNT_1); 4125 long rawContactId2 = createRawContactWithName("John", "Doe", ACCOUNT_2); 4126 4127 long contactId = queryContactId(rawContactId1); 4128 4129 mResolver.delete(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), null, null); 4130 4131 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1), 4132 RawContacts.DELETED, "1"); 4133 assertStoredValue(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2), 4134 RawContacts.DELETED, "1"); 4135 } 4136 4137 public void testMarkAsDirtyParameter() { 4138 long rawContactId = createRawContact(mAccount); 4139 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 4140 4141 Uri uri = insertStructuredName(rawContactId, "John", "Doe"); 4142 clearDirty(rawContactUri); 4143 Uri updateUri = setCallerIsSyncAdapter(uri, mAccount); 4144 4145 ContentValues values = new ContentValues(); 4146 values.put(StructuredName.FAMILY_NAME, "Dough"); 4147 mResolver.update(updateUri, values, null, null); 4148 assertStoredValue(uri, StructuredName.FAMILY_NAME, "Dough"); 4149 assertDirty(rawContactUri, false); 4150 assertNetworkNotified(false); 4151 } 4152 4153 public void testRawContactDirtyAndVersion() { 4154 final long rawContactId = createRawContact(mAccount); 4155 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); 4156 assertDirty(uri, false); 4157 long version = getVersion(uri); 4158 4159 ContentValues values = new ContentValues(); 4160 values.put(ContactsContract.RawContacts.DIRTY, 0); 4161 values.put(ContactsContract.RawContacts.SEND_TO_VOICEMAIL, 1); 4162 values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 4163 RawContacts.AGGREGATION_MODE_IMMEDIATE); 4164 values.put(ContactsContract.RawContacts.STARRED, 1); 4165 assertEquals(1, mResolver.update(uri, values, null, null)); 4166 assertEquals(version, getVersion(uri)); 4167 4168 assertDirty(uri, false); 4169 assertNetworkNotified(false); 4170 4171 Uri emailUri = insertEmail(rawContactId, "goo@woo.com"); 4172 assertDirty(uri, true); 4173 assertNetworkNotified(true); 4174 ++version; 4175 assertEquals(version, getVersion(uri)); 4176 clearDirty(uri); 4177 4178 values = new ContentValues(); 4179 values.put(Email.DATA, "goo@hoo.com"); 4180 mResolver.update(emailUri, values, null, null); 4181 assertDirty(uri, true); 4182 assertNetworkNotified(true); 4183 ++version; 4184 assertEquals(version, getVersion(uri)); 4185 clearDirty(uri); 4186 4187 mResolver.delete(emailUri, null, null); 4188 assertDirty(uri, true); 4189 assertNetworkNotified(true); 4190 ++version; 4191 assertEquals(version, getVersion(uri)); 4192 } 4193 4194 public void testRawContactClearDirty() { 4195 final long rawContactId = createRawContact(mAccount); 4196 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 4197 rawContactId); 4198 long version = getVersion(uri); 4199 insertEmail(rawContactId, "goo@woo.com"); 4200 assertDirty(uri, true); 4201 version++; 4202 assertEquals(version, getVersion(uri)); 4203 4204 clearDirty(uri); 4205 assertDirty(uri, false); 4206 assertEquals(version, getVersion(uri)); 4207 } 4208 4209 public void testRawContactDeletionSetsDirty() { 4210 final long rawContactId = createRawContact(mAccount); 4211 Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 4212 rawContactId); 4213 long version = getVersion(uri); 4214 clearDirty(uri); 4215 assertDirty(uri, false); 4216 4217 mResolver.delete(uri, null, null); 4218 assertStoredValue(uri, RawContacts.DELETED, "1"); 4219 assertDirty(uri, true); 4220 assertNetworkNotified(true); 4221 version++; 4222 assertEquals(version, getVersion(uri)); 4223 } 4224 4225 public void testDeleteContactWithoutName() { 4226 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()); 4227 long rawContactId = ContentUris.parseId(rawContactUri); 4228 4229 Uri phoneUri = insertPhoneNumber(rawContactId, "555-123-45678", true); 4230 4231 long contactId = queryContactId(rawContactId); 4232 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4233 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 4234 4235 int numDeleted = mResolver.delete(lookupUri, null, null); 4236 assertEquals(1, numDeleted); 4237 } 4238 4239 public void testDeleteContactWithoutAnyData() { 4240 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()); 4241 long rawContactId = ContentUris.parseId(rawContactUri); 4242 4243 long contactId = queryContactId(rawContactId); 4244 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4245 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 4246 4247 int numDeleted = mResolver.delete(lookupUri, null, null); 4248 assertEquals(1, numDeleted); 4249 } 4250 4251 public void testDeleteContactWithEscapedUri() { 4252 ContentValues values = new ContentValues(); 4253 values.put(RawContacts.SOURCE_ID, "!@#$%^&*()_+=-/.,<>?;'\":[]}{\\|`~"); 4254 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 4255 long rawContactId = ContentUris.parseId(rawContactUri); 4256 4257 long contactId = queryContactId(rawContactId); 4258 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4259 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 4260 assertEquals(1, mResolver.delete(lookupUri, null, null)); 4261 } 4262 4263 public void testQueryContactWithEscapedUri() { 4264 ContentValues values = new ContentValues(); 4265 values.put(RawContacts.SOURCE_ID, "!@#$%^&*()_+=-/.,<>?;'\":[]}{\\|`~"); 4266 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 4267 long rawContactId = ContentUris.parseId(rawContactUri); 4268 4269 long contactId = queryContactId(rawContactId); 4270 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4271 Uri lookupUri = Contacts.getLookupUri(mResolver, contactUri); 4272 Cursor c = mResolver.query(lookupUri, null, null, null, ""); 4273 assertEquals(1, c.getCount()); 4274 c.close(); 4275 } 4276 4277 public void testGetPhotoUri() { 4278 ContentValues values = new ContentValues(); 4279 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 4280 long rawContactId = ContentUris.parseId(rawContactUri); 4281 insertStructuredName(rawContactId, "John", "Doe"); 4282 long dataId = ContentUris.parseId(insertPhoto(rawContactId, R.drawable.earth_normal)); 4283 long photoFileId = getStoredLongValue(Data.CONTENT_URI, Data._ID + "=?", 4284 new String[]{String.valueOf(dataId)}, Photo.PHOTO_FILE_ID); 4285 String photoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoFileId) 4286 .toString(); 4287 4288 assertStoredValue( 4289 ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(rawContactId)), 4290 Contacts.PHOTO_URI, photoUri); 4291 } 4292 4293 public void testInputStreamForPhoto() throws Exception { 4294 long rawContactId = createRawContact(); 4295 long contactId = queryContactId(rawContactId); 4296 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4297 insertPhoto(rawContactId); 4298 Uri photoUri = Uri.parse(getStoredValue(contactUri, Contacts.PHOTO_URI)); 4299 Uri photoThumbnailUri = Uri.parse(getStoredValue(contactUri, Contacts.PHOTO_THUMBNAIL_URI)); 4300 4301 assertInputStreamContent(loadTestPhoto(PhotoSize.DISPLAY_PHOTO), 4302 mResolver.openInputStream(photoUri)); 4303 assertInputStreamContent(loadTestPhoto(PhotoSize.THUMBNAIL), 4304 mResolver.openInputStream(photoThumbnailUri)); 4305 } 4306 4307 private static void assertInputStreamContent(byte[] expected, InputStream is) 4308 throws IOException { 4309 try { 4310 byte[] observed = new byte[expected.length]; 4311 int count = is.read(observed); 4312 assertEquals(expected.length, count); 4313 assertEquals(-1, is.read()); 4314 MoreAsserts.assertEquals(expected, observed); 4315 } finally { 4316 is.close(); 4317 } 4318 } 4319 4320 public void testSuperPrimaryPhoto() { 4321 long rawContactId1 = createRawContact(new Account("a", "a")); 4322 Uri photoUri1 = insertPhoto(rawContactId1, R.drawable.earth_normal); 4323 long photoId1 = ContentUris.parseId(photoUri1); 4324 4325 long rawContactId2 = createRawContact(new Account("b", "b")); 4326 Uri photoUri2 = insertPhoto(rawContactId2, R.drawable.earth_normal); 4327 long photoId2 = ContentUris.parseId(photoUri2); 4328 4329 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 4330 rawContactId1, rawContactId2); 4331 4332 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 4333 queryContactId(rawContactId1)); 4334 4335 long photoFileId1 = getStoredLongValue(Data.CONTENT_URI, Data._ID + "=?", 4336 new String[]{String.valueOf(photoId1)}, Photo.PHOTO_FILE_ID); 4337 String photoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoFileId1) 4338 .toString(); 4339 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 4340 assertStoredValue(contactUri, Contacts.PHOTO_URI, photoUri); 4341 4342 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, 4343 rawContactId1, rawContactId2); 4344 4345 ContentValues values = new ContentValues(); 4346 values.put(Data.IS_SUPER_PRIMARY, 1); 4347 mResolver.update(photoUri2, values, null, null); 4348 4349 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 4350 rawContactId1, rawContactId2); 4351 contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 4352 queryContactId(rawContactId1)); 4353 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId2); 4354 4355 mResolver.update(photoUri1, values, null, null); 4356 assertStoredValue(contactUri, Contacts.PHOTO_ID, photoId1); 4357 } 4358 4359 public void testUpdatePhoto() { 4360 ContentValues values = new ContentValues(); 4361 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 4362 long rawContactId = ContentUris.parseId(rawContactUri); 4363 insertStructuredName(rawContactId, "John", "Doe"); 4364 4365 Uri twigUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 4366 queryContactId(rawContactId)), Contacts.Photo.CONTENT_DIRECTORY); 4367 4368 values.clear(); 4369 values.put(Data.RAW_CONTACT_ID, rawContactId); 4370 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 4371 values.putNull(Photo.PHOTO); 4372 Uri dataUri = mResolver.insert(Data.CONTENT_URI, values); 4373 long photoId = ContentUris.parseId(dataUri); 4374 4375 assertEquals(0, getCount(twigUri, null, null)); 4376 4377 values.clear(); 4378 values.put(Photo.PHOTO, loadTestPhoto()); 4379 mResolver.update(dataUri, values, null, null); 4380 assertNetworkNotified(true); 4381 4382 long twigId = getStoredLongValue(twigUri, Data._ID); 4383 assertEquals(photoId, twigId); 4384 } 4385 4386 public void testUpdateRawContactDataPhoto() { 4387 // setup a contact with a null photo 4388 ContentValues values = new ContentValues(); 4389 Uri rawContactUri = mResolver.insert(RawContacts.CONTENT_URI, values); 4390 long rawContactId = ContentUris.parseId(rawContactUri); 4391 4392 // setup a photo 4393 values.put(Data.RAW_CONTACT_ID, rawContactId); 4394 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 4395 values.putNull(Photo.PHOTO); 4396 4397 // try to do an update before insert should return count == 0 4398 Uri dataUri = Uri.withAppendedPath( 4399 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 4400 RawContacts.Data.CONTENT_DIRECTORY); 4401 assertEquals(0, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 4402 new String[] {Photo.CONTENT_ITEM_TYPE})); 4403 4404 mResolver.insert(Data.CONTENT_URI, values); 4405 4406 // save a photo to the db 4407 values.clear(); 4408 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 4409 values.put(Photo.PHOTO, loadTestPhoto()); 4410 assertEquals(1, mResolver.update(dataUri, values, Data.MIMETYPE + "=?", 4411 new String[] {Photo.CONTENT_ITEM_TYPE})); 4412 4413 // verify the photo 4414 Cursor storedPhoto = mResolver.query(dataUri, new String[] {Photo.PHOTO}, 4415 Data.MIMETYPE + "=?", new String[] {Photo.CONTENT_ITEM_TYPE}, null); 4416 storedPhoto.moveToFirst(); 4417 MoreAsserts.assertEquals(loadTestPhoto(PhotoSize.THUMBNAIL), storedPhoto.getBlob(0)); 4418 storedPhoto.close(); 4419 } 4420 4421 public void testOpenDisplayPhotoForContactId() throws IOException { 4422 long rawContactId = createRawContactWithName(); 4423 long contactId = queryContactId(rawContactId); 4424 insertPhoto(rawContactId, R.drawable.earth_normal); 4425 Uri photoUri = Contacts.CONTENT_URI.buildUpon() 4426 .appendPath(String.valueOf(contactId)) 4427 .appendPath(Contacts.Photo.DISPLAY_PHOTO).build(); 4428 assertInputStreamContent( 4429 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO), 4430 mResolver.openInputStream(photoUri)); 4431 } 4432 4433 public void testOpenDisplayPhotoForContactLookupKey() throws IOException { 4434 long rawContactId = createRawContactWithName(); 4435 long contactId = queryContactId(rawContactId); 4436 String lookupKey = queryLookupKey(contactId); 4437 insertPhoto(rawContactId, R.drawable.earth_normal); 4438 Uri photoUri = Contacts.CONTENT_LOOKUP_URI.buildUpon() 4439 .appendPath(lookupKey) 4440 .appendPath(Contacts.Photo.DISPLAY_PHOTO).build(); 4441 assertInputStreamContent( 4442 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO), 4443 mResolver.openInputStream(photoUri)); 4444 } 4445 4446 public void testOpenDisplayPhotoForContactLookupKeyAndId() throws IOException { 4447 long rawContactId = createRawContactWithName(); 4448 long contactId = queryContactId(rawContactId); 4449 String lookupKey = queryLookupKey(contactId); 4450 insertPhoto(rawContactId, R.drawable.earth_normal); 4451 Uri photoUri = Contacts.CONTENT_LOOKUP_URI.buildUpon() 4452 .appendPath(lookupKey) 4453 .appendPath(String.valueOf(contactId)) 4454 .appendPath(Contacts.Photo.DISPLAY_PHOTO).build(); 4455 assertInputStreamContent( 4456 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO), 4457 mResolver.openInputStream(photoUri)); 4458 } 4459 4460 public void testOpenDisplayPhotoForRawContactId() throws IOException { 4461 long rawContactId = createRawContactWithName(); 4462 insertPhoto(rawContactId, R.drawable.earth_normal); 4463 Uri photoUri = RawContacts.CONTENT_URI.buildUpon() 4464 .appendPath(String.valueOf(rawContactId)) 4465 .appendPath(RawContacts.DisplayPhoto.CONTENT_DIRECTORY).build(); 4466 assertInputStreamContent( 4467 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO), 4468 mResolver.openInputStream(photoUri)); 4469 } 4470 4471 public void testOpenDisplayPhotoByPhotoUri() throws IOException { 4472 long rawContactId = createRawContactWithName(); 4473 long contactId = queryContactId(rawContactId); 4474 insertPhoto(rawContactId, R.drawable.earth_normal); 4475 4476 // Get the photo URI out and check the content. 4477 String photoUri = getStoredValue( 4478 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4479 Contacts.PHOTO_URI); 4480 assertInputStreamContent( 4481 loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.DISPLAY_PHOTO), 4482 mResolver.openInputStream(Uri.parse(photoUri))); 4483 } 4484 4485 public void testPhotoUriForDisplayPhoto() { 4486 long rawContactId = createRawContactWithName(); 4487 long contactId = queryContactId(rawContactId); 4488 4489 // Photo being inserted is larger than a thumbnail, so it will be stored as a file. 4490 long dataId = ContentUris.parseId(insertPhoto(rawContactId, R.drawable.earth_normal)); 4491 String photoFileId = getStoredValue(ContentUris.withAppendedId(Data.CONTENT_URI, dataId), 4492 Photo.PHOTO_FILE_ID); 4493 String photoUri = getStoredValue( 4494 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4495 Contacts.PHOTO_URI); 4496 4497 // Check that the photo URI differs from the thumbnail. 4498 String thumbnailUri = getStoredValue( 4499 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4500 Contacts.PHOTO_THUMBNAIL_URI); 4501 assertFalse(photoUri.equals(thumbnailUri)); 4502 4503 // URI should be of the form display_photo/ID 4504 assertEquals(Uri.withAppendedPath(DisplayPhoto.CONTENT_URI, photoFileId).toString(), 4505 photoUri); 4506 } 4507 4508 public void testPhotoUriForThumbnailPhoto() throws IOException { 4509 long rawContactId = createRawContactWithName(); 4510 long contactId = queryContactId(rawContactId); 4511 4512 // Photo being inserted is a thumbnail, so it will only be stored in a BLOB. The photo URI 4513 // will fall back to the thumbnail URI. 4514 insertPhoto(rawContactId, R.drawable.earth_small); 4515 String photoUri = getStoredValue( 4516 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4517 Contacts.PHOTO_URI); 4518 4519 // Check that the photo URI is equal to the thumbnail URI. 4520 String thumbnailUri = getStoredValue( 4521 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4522 Contacts.PHOTO_THUMBNAIL_URI); 4523 assertEquals(photoUri, thumbnailUri); 4524 4525 // URI should be of the form contacts/ID/photo 4526 assertEquals(Uri.withAppendedPath( 4527 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4528 Contacts.Photo.CONTENT_DIRECTORY).toString(), 4529 photoUri); 4530 4531 // Loading the photo URI content should get the thumbnail. 4532 assertInputStreamContent( 4533 loadPhotoFromResource(R.drawable.earth_small, PhotoSize.THUMBNAIL), 4534 mResolver.openInputStream(Uri.parse(photoUri))); 4535 } 4536 4537 public void testWriteNewPhotoToAssetFile() throws IOException { 4538 long rawContactId = createRawContactWithName(); 4539 long contactId = queryContactId(rawContactId); 4540 4541 // Load in a huge photo. 4542 byte[] originalPhoto = loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.ORIGINAL); 4543 4544 // Write it out. 4545 Uri writeablePhotoUri = RawContacts.CONTENT_URI.buildUpon() 4546 .appendPath(String.valueOf(rawContactId)) 4547 .appendPath(RawContacts.DisplayPhoto.CONTENT_DIRECTORY).build(); 4548 OutputStream os = mResolver.openOutputStream(writeablePhotoUri, "rw"); 4549 try { 4550 os.write(originalPhoto); 4551 } finally { 4552 os.close(); 4553 } 4554 4555 // Check that the display photo and thumbnail have been set. 4556 String photoUri = getStoredValue( 4557 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), Contacts.PHOTO_URI); 4558 assertFalse(TextUtils.isEmpty(photoUri)); 4559 String thumbnailUri = getStoredValue( 4560 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4561 Contacts.PHOTO_THUMBNAIL_URI); 4562 assertFalse(TextUtils.isEmpty(thumbnailUri)); 4563 assertFalse(photoUri.equals(thumbnailUri)); 4564 4565 // Check the content of the display photo and thumbnail. 4566 assertInputStreamContent( 4567 loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.DISPLAY_PHOTO), 4568 mResolver.openInputStream(Uri.parse(photoUri))); 4569 assertInputStreamContent( 4570 loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.THUMBNAIL), 4571 mResolver.openInputStream(Uri.parse(thumbnailUri))); 4572 } 4573 4574 public void testWriteUpdatedPhotoToAssetFile() throws IOException { 4575 long rawContactId = createRawContactWithName(); 4576 long contactId = queryContactId(rawContactId); 4577 4578 // Insert a large photo first. 4579 insertPhoto(rawContactId, R.drawable.earth_large); 4580 String largeEarthPhotoUri = getStoredValue( 4581 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), Contacts.PHOTO_URI); 4582 4583 // Load in a huge photo. 4584 byte[] originalPhoto = loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.ORIGINAL); 4585 4586 // Write it out. 4587 Uri writeablePhotoUri = RawContacts.CONTENT_URI.buildUpon() 4588 .appendPath(String.valueOf(rawContactId)) 4589 .appendPath(RawContacts.DisplayPhoto.CONTENT_DIRECTORY).build(); 4590 OutputStream os = mResolver.openOutputStream(writeablePhotoUri, "rw"); 4591 try { 4592 os.write(originalPhoto); 4593 } finally { 4594 os.close(); 4595 } 4596 4597 // Check that the display photo URI has been modified. 4598 String hugeEarthPhotoUri = getStoredValue( 4599 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), Contacts.PHOTO_URI); 4600 assertFalse(hugeEarthPhotoUri.equals(largeEarthPhotoUri)); 4601 4602 // Check the content of the display photo and thumbnail. 4603 String hugeEarthThumbnailUri = getStoredValue( 4604 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 4605 Contacts.PHOTO_THUMBNAIL_URI); 4606 assertInputStreamContent( 4607 loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.DISPLAY_PHOTO), 4608 mResolver.openInputStream(Uri.parse(hugeEarthPhotoUri))); 4609 assertInputStreamContent( 4610 loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.THUMBNAIL), 4611 mResolver.openInputStream(Uri.parse(hugeEarthThumbnailUri))); 4612 4613 } 4614 4615 public void testPhotoDimensionLimits() { 4616 ContentValues values = new ContentValues(); 4617 values.put(DisplayPhoto.DISPLAY_MAX_DIM, 256); 4618 values.put(DisplayPhoto.THUMBNAIL_MAX_DIM, 96); 4619 assertStoredValues(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI, values); 4620 } 4621 4622 public void testPhotoStoreCleanup() throws IOException { 4623 SynchronousContactsProvider2 provider = (SynchronousContactsProvider2) mActor.provider; 4624 4625 // Trigger an initial cleanup so another one won't happen while we're running this test. 4626 provider.cleanupPhotoStore(); 4627 4628 // Insert a couple of contacts with photos. 4629 long rawContactId1 = createRawContactWithName(); 4630 long contactId1 = queryContactId(rawContactId1); 4631 long dataId1 = ContentUris.parseId(insertPhoto(rawContactId1, R.drawable.earth_normal)); 4632 long photoFileId1 = 4633 getStoredLongValue(ContentUris.withAppendedId(Data.CONTENT_URI, dataId1), 4634 Photo.PHOTO_FILE_ID); 4635 4636 long rawContactId2 = createRawContactWithName(); 4637 long contactId2 = queryContactId(rawContactId2); 4638 long dataId2 = ContentUris.parseId(insertPhoto(rawContactId2, R.drawable.earth_normal)); 4639 long photoFileId2 = 4640 getStoredLongValue(ContentUris.withAppendedId(Data.CONTENT_URI, dataId2), 4641 Photo.PHOTO_FILE_ID); 4642 4643 // Update the second raw contact with a different photo. 4644 ContentValues values = new ContentValues(); 4645 values.put(Data.RAW_CONTACT_ID, rawContactId2); 4646 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 4647 values.put(Photo.PHOTO, loadPhotoFromResource(R.drawable.earth_huge, PhotoSize.ORIGINAL)); 4648 assertEquals(1, mResolver.update(Data.CONTENT_URI, values, Data._ID + "=?", 4649 new String[]{String.valueOf(dataId2)})); 4650 long replacementPhotoFileId = 4651 getStoredLongValue(ContentUris.withAppendedId(Data.CONTENT_URI, dataId2), 4652 Photo.PHOTO_FILE_ID); 4653 4654 // Insert a third raw contact that has a bogus photo file ID. 4655 long bogusFileId = 1234567; 4656 long rawContactId3 = createRawContactWithName(); 4657 long contactId3 = queryContactId(rawContactId3); 4658 values.clear(); 4659 values.put(Data.RAW_CONTACT_ID, rawContactId3); 4660 values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 4661 values.put(Photo.PHOTO, loadPhotoFromResource(R.drawable.earth_normal, 4662 PhotoSize.THUMBNAIL)); 4663 values.put(Photo.PHOTO_FILE_ID, bogusFileId); 4664 values.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 4665 mResolver.insert(Data.CONTENT_URI, values); 4666 4667 // Also insert a bogus photo that nobody is using. 4668 PhotoStore photoStore = provider.getPhotoStore(); 4669 long bogusPhotoId = photoStore.insert(new PhotoProcessor(loadPhotoFromResource( 4670 R.drawable.earth_huge, PhotoSize.ORIGINAL), 256, 96)); 4671 4672 // Manually trigger another cleanup in the provider. 4673 provider.cleanupPhotoStore(); 4674 4675 // The following things should have happened. 4676 4677 // 1. Raw contact 1 and its photo remain unaffected. 4678 assertEquals(photoFileId1, (long) getStoredLongValue( 4679 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1), 4680 Contacts.PHOTO_FILE_ID)); 4681 4682 // 2. Raw contact 2 retains its new photo. The old one is deleted from the photo store. 4683 assertEquals(replacementPhotoFileId, (long) getStoredLongValue( 4684 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2), 4685 Contacts.PHOTO_FILE_ID)); 4686 assertNull(photoStore.get(photoFileId2)); 4687 4688 // 3. Raw contact 3 should have its photo file reference cleared. 4689 assertNull(getStoredValue( 4690 ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId3), 4691 Contacts.PHOTO_FILE_ID)); 4692 4693 // 4. The bogus photo that nobody was using should be cleared from the photo store. 4694 assertNull(photoStore.get(bogusPhotoId)); 4695 } 4696 4697 public void testOverwritePhotoWithThumbnail() throws IOException { 4698 long rawContactId = createRawContactWithName(); 4699 long contactId = queryContactId(rawContactId); 4700 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4701 4702 // Write a regular-size photo. 4703 long dataId = ContentUris.parseId(insertPhoto(rawContactId, R.drawable.earth_normal)); 4704 Long photoFileId = getStoredLongValue(contactUri, Contacts.PHOTO_FILE_ID); 4705 assertTrue(photoFileId != null && photoFileId > 0); 4706 4707 // Now overwrite the photo with a thumbnail-sized photo. 4708 ContentValues update = new ContentValues(); 4709 update.put(Photo.PHOTO, loadPhotoFromResource(R.drawable.earth_small, PhotoSize.ORIGINAL)); 4710 mResolver.update(ContentUris.withAppendedId(Data.CONTENT_URI, dataId), update, null, null); 4711 4712 // Photo file ID should have been nulled out, and the photo URI should be the same as the 4713 // thumbnail URI. 4714 assertNull(getStoredValue(contactUri, Contacts.PHOTO_FILE_ID)); 4715 String photoUri = getStoredValue(contactUri, Contacts.PHOTO_URI); 4716 String thumbnailUri = getStoredValue(contactUri, Contacts.PHOTO_THUMBNAIL_URI); 4717 assertEquals(photoUri, thumbnailUri); 4718 4719 // Retrieving the photo URI should get the thumbnail content. 4720 assertInputStreamContent(loadPhotoFromResource(R.drawable.earth_small, PhotoSize.THUMBNAIL), 4721 mResolver.openInputStream(Uri.parse(photoUri))); 4722 } 4723 4724 public void testUpdateRawContactSetStarred() { 4725 long rawContactId1 = createRawContactWithName(); 4726 Uri rawContactUri1 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 4727 long rawContactId2 = createRawContactWithName(); 4728 Uri rawContactUri2 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2); 4729 setAggregationException( 4730 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 4731 4732 long contactId = queryContactId(rawContactId1); 4733 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4734 assertStoredValue(contactUri, Contacts.STARRED, "0"); 4735 4736 ContentValues values = new ContentValues(); 4737 values.put(RawContacts.STARRED, "1"); 4738 4739 mResolver.update(rawContactUri1, values, null, null); 4740 4741 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 4742 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 4743 assertStoredValue(contactUri, Contacts.STARRED, "1"); 4744 4745 values.put(RawContacts.STARRED, "0"); 4746 mResolver.update(rawContactUri1, values, null, null); 4747 4748 assertStoredValue(rawContactUri1, RawContacts.STARRED, "0"); 4749 assertStoredValue(rawContactUri2, RawContacts.STARRED, "0"); 4750 assertStoredValue(contactUri, Contacts.STARRED, "0"); 4751 4752 values.put(Contacts.STARRED, "1"); 4753 mResolver.update(contactUri, values, null, null); 4754 4755 assertStoredValue(rawContactUri1, RawContacts.STARRED, "1"); 4756 assertStoredValue(rawContactUri2, RawContacts.STARRED, "1"); 4757 assertStoredValue(contactUri, Contacts.STARRED, "1"); 4758 } 4759 4760 public void testSetAndClearSuperPrimaryEmail() { 4761 long rawContactId1 = createRawContact(new Account("a", "a")); 4762 Uri mailUri11 = insertEmail(rawContactId1, "test1@domain1.com"); 4763 Uri mailUri12 = insertEmail(rawContactId1, "test2@domain1.com"); 4764 4765 long rawContactId2 = createRawContact(new Account("b", "b")); 4766 Uri mailUri21 = insertEmail(rawContactId2, "test1@domain2.com"); 4767 Uri mailUri22 = insertEmail(rawContactId2, "test2@domain2.com"); 4768 4769 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 4770 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 4771 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 4772 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 4773 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4774 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4775 assertStoredValue(mailUri22, Data.IS_PRIMARY, 0); 4776 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); 4777 4778 // Set super primary on the first pair, primary on the second 4779 { 4780 ContentValues values = new ContentValues(); 4781 values.put(Data.IS_SUPER_PRIMARY, 1); 4782 mResolver.update(mailUri11, values, null, null); 4783 } 4784 { 4785 ContentValues values = new ContentValues(); 4786 values.put(Data.IS_SUPER_PRIMARY, 1); 4787 mResolver.update(mailUri22, values, null, null); 4788 } 4789 4790 assertStoredValue(mailUri11, Data.IS_PRIMARY, 1); 4791 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 1); 4792 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 4793 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 4794 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4795 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4796 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 4797 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 4798 4799 // Clear primary on the first pair, make sure second is not affected and super_primary is 4800 // also cleared 4801 { 4802 ContentValues values = new ContentValues(); 4803 values.put(Data.IS_PRIMARY, 0); 4804 mResolver.update(mailUri11, values, null, null); 4805 } 4806 4807 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 4808 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 4809 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 4810 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 4811 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4812 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4813 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 4814 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 4815 4816 // Ensure that we can only clear super_primary, if we specify the correct data row 4817 { 4818 ContentValues values = new ContentValues(); 4819 values.put(Data.IS_SUPER_PRIMARY, 0); 4820 mResolver.update(mailUri21, values, null, null); 4821 } 4822 4823 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4824 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4825 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 4826 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 4827 4828 // Ensure that we can only clear primary, if we specify the correct data row 4829 { 4830 ContentValues values = new ContentValues(); 4831 values.put(Data.IS_PRIMARY, 0); 4832 mResolver.update(mailUri21, values, null, null); 4833 } 4834 4835 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4836 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4837 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 4838 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); 4839 4840 // Now clear super-primary for real 4841 { 4842 ContentValues values = new ContentValues(); 4843 values.put(Data.IS_SUPER_PRIMARY, 0); 4844 mResolver.update(mailUri22, values, null, null); 4845 } 4846 4847 assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); 4848 assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); 4849 assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); 4850 assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); 4851 assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); 4852 assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); 4853 assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); 4854 assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); 4855 } 4856 4857 /** 4858 * Common function for the testNewPrimaryIn* functions. Its four configurations 4859 * are each called from its own test 4860 */ 4861 public void testChangingPrimary(boolean inUpdate, boolean withSuperPrimary) { 4862 long rawContactId = createRawContact(new Account("a", "a")); 4863 Uri mailUri1 = insertEmail(rawContactId, "test1@domain1.com", true); 4864 4865 if (withSuperPrimary) { 4866 final ContentValues values = new ContentValues(); 4867 values.put(Data.IS_SUPER_PRIMARY, 1); 4868 mResolver.update(mailUri1, values, null, null); 4869 } 4870 4871 assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); 4872 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 4873 4874 // Insert another item 4875 final Uri mailUri2; 4876 if (inUpdate) { 4877 mailUri2 = insertEmail(rawContactId, "test2@domain1.com"); 4878 4879 assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); 4880 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 4881 assertStoredValue(mailUri2, Data.IS_PRIMARY, 0); 4882 assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, 0); 4883 4884 final ContentValues values = new ContentValues(); 4885 values.put(Data.IS_PRIMARY, 1); 4886 mResolver.update(mailUri2, values, null, null); 4887 } else { 4888 // directly add as default 4889 mailUri2 = insertEmail(rawContactId, "test2@domain1.com", true); 4890 } 4891 4892 // Ensure that primary has been unset on the first 4893 // If withSuperPrimary is set, also ensure that is has been moved to the new item 4894 assertStoredValue(mailUri1, Data.IS_PRIMARY, 0); 4895 assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, 0); 4896 assertStoredValue(mailUri2, Data.IS_PRIMARY, 1); 4897 assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); 4898 } 4899 4900 public void testNewPrimaryInInsert() { 4901 testChangingPrimary(false, false); 4902 } 4903 4904 public void testNewPrimaryInInsertWithSuperPrimary() { 4905 testChangingPrimary(false, true); 4906 } 4907 4908 public void testNewPrimaryInUpdate() { 4909 testChangingPrimary(true, false); 4910 } 4911 4912 public void testNewPrimaryInUpdateWithSuperPrimary() { 4913 testChangingPrimary(true, true); 4914 } 4915 4916 public void testLiveFolders() { 4917 long rawContactId1 = createRawContactWithName("James", "Sullivan"); 4918 insertPhoneNumber(rawContactId1, "5234567890"); 4919 long contactId1 = queryContactId(rawContactId1); 4920 4921 long rawContactId2 = createRawContactWithName("Mike", "Wazowski"); 4922 long contactId2 = queryContactId(rawContactId2); 4923 storeValue(Contacts.CONTENT_URI, contactId2, Contacts.STARRED, "1"); 4924 4925 long rawContactId3 = createRawContactWithName("Randall", "Boggs"); 4926 long contactId3 = queryContactId(rawContactId3); 4927 long groupId = createGroup(NO_ACCOUNT, "src1", "VIP"); 4928 insertGroupMembership(rawContactId3, groupId); 4929 4930 assertLiveFolderContents( 4931 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 4932 "live_folders/contacts"), 4933 contactId1, "James Sullivan", 4934 contactId2, "Mike Wazowski", 4935 contactId3, "Randall Boggs"); 4936 4937 assertLiveFolderContents( 4938 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 4939 "live_folders/contacts_with_phones"), 4940 contactId1, "James Sullivan"); 4941 4942 assertLiveFolderContents( 4943 Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 4944 "live_folders/favorites"), 4945 contactId2, "Mike Wazowski"); 4946 4947 assertLiveFolderContents( 4948 Uri.withAppendedPath(Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, 4949 "live_folders/contacts"), Uri.encode("VIP")), 4950 contactId3, "Randall Boggs"); 4951 } 4952 4953 private void assertLiveFolderContents(Uri uri, Object... expected) { 4954 Cursor c = mResolver.query(uri, new String[]{LiveFolders._ID, LiveFolders.NAME}, 4955 null, null, LiveFolders._ID); 4956 assertEquals(expected.length/2, c.getCount()); 4957 for (int i = 0; i < expected.length/2; i++) { 4958 assertTrue(c.moveToNext()); 4959 assertEquals(((Long)expected[i * 2]).longValue(), c.getLong(0)); 4960 assertEquals(expected[i * 2 + 1], c.getString(1)); 4961 } 4962 c.close(); 4963 } 4964 4965 public void testContactCounts() { 4966 Uri uri = Contacts.CONTENT_URI.buildUpon() 4967 .appendQueryParameter(ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, "true").build(); 4968 4969 createRawContact(); 4970 createRawContactWithName("James", "Sullivan"); 4971 createRawContactWithName("The Abominable", "Snowman"); 4972 createRawContactWithName("Mike", "Wazowski"); 4973 createRawContactWithName("randall", "boggs"); 4974 createRawContactWithName("Boo", null); 4975 createRawContactWithName("Mary", null); 4976 createRawContactWithName("Roz", null); 4977 4978 Cursor cursor = mResolver.query(uri, 4979 new String[]{Contacts.DISPLAY_NAME}, 4980 null, null, Contacts.SORT_KEY_PRIMARY + " COLLATE LOCALIZED"); 4981 4982 assertFirstLetterValues(cursor, null, "B", "J", "M", "R", "T"); 4983 assertFirstLetterCounts(cursor, 1, 1, 1, 2, 2, 1); 4984 cursor.close(); 4985 4986 cursor = mResolver.query(uri, 4987 new String[]{Contacts.DISPLAY_NAME}, 4988 null, null, Contacts.SORT_KEY_ALTERNATIVE + " COLLATE LOCALIZED DESC"); 4989 4990 assertFirstLetterValues(cursor, "W", "S", "R", "M", "B", null); 4991 assertFirstLetterCounts(cursor, 1, 2, 1, 1, 2, 1); 4992 cursor.close(); 4993 } 4994 4995 private void assertFirstLetterValues(Cursor cursor, String... expected) { 4996 String[] actual = cursor.getExtras() 4997 .getStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES); 4998 MoreAsserts.assertEquals(expected, actual); 4999 } 5000 5001 private void assertFirstLetterCounts(Cursor cursor, int... expected) { 5002 int[] actual = cursor.getExtras() 5003 .getIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS); 5004 MoreAsserts.assertEquals(expected, actual); 5005 } 5006 5007 public void testReadBooleanQueryParameter() { 5008 assertBooleanUriParameter("foo:bar", "bool", true, true); 5009 assertBooleanUriParameter("foo:bar", "bool", false, false); 5010 assertBooleanUriParameter("foo:bar?bool=0", "bool", true, false); 5011 assertBooleanUriParameter("foo:bar?bool=1", "bool", false, true); 5012 assertBooleanUriParameter("foo:bar?bool=false", "bool", true, false); 5013 assertBooleanUriParameter("foo:bar?bool=true", "bool", false, true); 5014 assertBooleanUriParameter("foo:bar?bool=FaLsE", "bool", true, false); 5015 assertBooleanUriParameter("foo:bar?bool=false&some=some", "bool", true, false); 5016 assertBooleanUriParameter("foo:bar?bool=1&some=some", "bool", false, true); 5017 assertBooleanUriParameter("foo:bar?some=bool", "bool", true, true); 5018 assertBooleanUriParameter("foo:bar?bool", "bool", true, true); 5019 } 5020 5021 private void assertBooleanUriParameter(String uriString, String parameter, 5022 boolean defaultValue, boolean expectedValue) { 5023 assertEquals(expectedValue, ContactsProvider2.readBooleanQueryParameter( 5024 Uri.parse(uriString), parameter, defaultValue)); 5025 } 5026 5027 public void testGetQueryParameter() { 5028 assertQueryParameter("foo:bar", "param", null); 5029 assertQueryParameter("foo:bar?param", "param", null); 5030 assertQueryParameter("foo:bar?param=", "param", ""); 5031 assertQueryParameter("foo:bar?param=val", "param", "val"); 5032 assertQueryParameter("foo:bar?param=val&some=some", "param", "val"); 5033 assertQueryParameter("foo:bar?some=some¶m=val", "param", "val"); 5034 assertQueryParameter("foo:bar?some=some¶m=val&else=else", "param", "val"); 5035 assertQueryParameter("foo:bar?param=john%40doe.com", "param", "john@doe.com"); 5036 assertQueryParameter("foo:bar?some_param=val", "param", null); 5037 assertQueryParameter("foo:bar?some_param=val1¶m=val2", "param", "val2"); 5038 assertQueryParameter("foo:bar?some_param=val1¶m=", "param", ""); 5039 assertQueryParameter("foo:bar?some_param=val1¶m", "param", null); 5040 assertQueryParameter("foo:bar?some_param=val1&another_param=val2¶m=val3", 5041 "param", "val3"); 5042 assertQueryParameter("foo:bar?some_param=val1¶m=val2&some_param=val3", 5043 "param", "val2"); 5044 assertQueryParameter("foo:bar?param=val1&some_param=val2", "param", "val1"); 5045 assertQueryParameter("foo:bar?p=val1&pp=val2", "p", "val1"); 5046 assertQueryParameter("foo:bar?pp=val1&p=val2", "p", "val2"); 5047 assertQueryParameter("foo:bar?ppp=val1&pp=val2&p=val3", "p", "val3"); 5048 assertQueryParameter("foo:bar?ppp=val&", "p", null); 5049 } 5050 5051 public void testMissingAccountTypeParameter() { 5052 // Try querying for RawContacts only using ACCOUNT_NAME 5053 final Uri queryUri = RawContacts.CONTENT_URI.buildUpon().appendQueryParameter( 5054 RawContacts.ACCOUNT_NAME, "lolwut").build(); 5055 try { 5056 final Cursor cursor = mResolver.query(queryUri, null, null, null, null); 5057 fail("Able to query with incomplete account query parameters"); 5058 } catch (IllegalArgumentException e) { 5059 // Expected behavior. 5060 } 5061 } 5062 5063 public void testInsertInconsistentAccountType() { 5064 // Try inserting RawContact with inconsistent Accounts 5065 final Account red = new Account("red", "red"); 5066 final Account blue = new Account("blue", "blue"); 5067 5068 final ContentValues values = new ContentValues(); 5069 values.put(RawContacts.ACCOUNT_NAME, red.name); 5070 values.put(RawContacts.ACCOUNT_TYPE, red.type); 5071 5072 final Uri insertUri = maybeAddAccountQueryParameters(RawContacts.CONTENT_URI, blue); 5073 try { 5074 mResolver.insert(insertUri, values); 5075 fail("Able to insert RawContact with inconsistent account details"); 5076 } catch (IllegalArgumentException e) { 5077 // Expected behavior. 5078 } 5079 } 5080 5081 public void testProviderStatusNoContactsNoAccounts() throws Exception { 5082 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 5083 } 5084 5085 public void testProviderStatusOnlyLocalContacts() throws Exception { 5086 long rawContactId = createRawContact(); 5087 assertProviderStatus(ProviderStatus.STATUS_NORMAL); 5088 mResolver.delete( 5089 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), null, null); 5090 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 5091 } 5092 5093 public void testProviderStatusWithAccounts() throws Exception { 5094 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 5095 mActor.setAccounts(new Account[]{ACCOUNT_1}); 5096 ((ContactsProvider2)getProvider()).onAccountsUpdated(new Account[]{ACCOUNT_1}); 5097 assertProviderStatus(ProviderStatus.STATUS_NORMAL); 5098 mActor.setAccounts(new Account[0]); 5099 ((ContactsProvider2)getProvider()).onAccountsUpdated(new Account[0]); 5100 assertProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 5101 } 5102 5103 private void assertProviderStatus(int expectedProviderStatus) { 5104 Cursor cursor = mResolver.query(ProviderStatus.CONTENT_URI, 5105 new String[]{ProviderStatus.DATA1, ProviderStatus.STATUS}, null, null, null); 5106 assertTrue(cursor.moveToFirst()); 5107 assertEquals(0, cursor.getLong(0)); 5108 assertEquals(expectedProviderStatus, cursor.getInt(1)); 5109 cursor.close(); 5110 } 5111 5112 public void testProperties() throws Exception { 5113 ContactsProvider2 provider = (ContactsProvider2)getProvider(); 5114 ContactsDatabaseHelper helper = (ContactsDatabaseHelper)provider.getDatabaseHelper(); 5115 assertNull(helper.getProperty("non-existent", null)); 5116 assertEquals("default", helper.getProperty("non-existent", "default")); 5117 5118 helper.setProperty("existent1", "string1"); 5119 helper.setProperty("existent2", "string2"); 5120 assertEquals("string1", helper.getProperty("existent1", "default")); 5121 assertEquals("string2", helper.getProperty("existent2", "default")); 5122 helper.setProperty("existent1", null); 5123 assertEquals("default", helper.getProperty("existent1", "default")); 5124 } 5125 5126 private class VCardTestUriCreator { 5127 private String mLookup1; 5128 private String mLookup2; 5129 5130 public VCardTestUriCreator(String lookup1, String lookup2) { 5131 super(); 5132 mLookup1 = lookup1; 5133 mLookup2 = lookup2; 5134 } 5135 5136 public Uri getUri1() { 5137 return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1); 5138 } 5139 5140 public Uri getUri2() { 5141 return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2); 5142 } 5143 5144 public Uri getCombinedUri() { 5145 return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI, 5146 Uri.encode(mLookup1 + ":" + mLookup2)); 5147 } 5148 } 5149 5150 private VCardTestUriCreator createVCardTestContacts() { 5151 final long rawContactId1 = createRawContact(mAccount, RawContacts.SOURCE_ID, "4:12"); 5152 insertStructuredName(rawContactId1, "John", "Doe"); 5153 5154 final long rawContactId2 = createRawContact(mAccount, RawContacts.SOURCE_ID, "3:4%121"); 5155 insertStructuredName(rawContactId2, "Jane", "Doh"); 5156 5157 final long contactId1 = queryContactId(rawContactId1); 5158 final long contactId2 = queryContactId(rawContactId2); 5159 final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1); 5160 final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2); 5161 final String lookup1 = 5162 Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2)); 5163 final String lookup2 = 5164 Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2)); 5165 return new VCardTestUriCreator(lookup1, lookup2); 5166 } 5167 5168 public void testQueryMultiVCard() { 5169 // No need to create any contacts here, because the query for multiple vcards 5170 // does not go into the database at all 5171 Uri uri = Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI, Uri.encode("123:456")); 5172 Cursor cursor = mResolver.query(uri, null, null, null, null); 5173 assertEquals(1, cursor.getCount()); 5174 assertTrue(cursor.moveToFirst()); 5175 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 5176 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 5177 5178 // The resulting name contains date and time. Ensure that before and after are correct 5179 assertTrue(filename.startsWith("vcards_")); 5180 assertTrue(filename.endsWith(".vcf")); 5181 cursor.close(); 5182 } 5183 5184 public void testQueryFileSingleVCard() { 5185 final VCardTestUriCreator contacts = createVCardTestContacts(); 5186 5187 { 5188 Cursor cursor = mResolver.query(contacts.getUri1(), null, null, null, null); 5189 assertEquals(1, cursor.getCount()); 5190 assertTrue(cursor.moveToFirst()); 5191 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 5192 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 5193 assertEquals("John Doe.vcf", filename); 5194 cursor.close(); 5195 } 5196 5197 { 5198 Cursor cursor = mResolver.query(contacts.getUri2(), null, null, null, null); 5199 assertEquals(1, cursor.getCount()); 5200 assertTrue(cursor.moveToFirst()); 5201 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 5202 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 5203 assertEquals("Jane Doh.vcf", filename); 5204 cursor.close(); 5205 } 5206 } 5207 5208 public void testQueryFileProfileVCard() { 5209 createBasicProfileContact(new ContentValues()); 5210 Cursor cursor = mResolver.query(Profile.CONTENT_VCARD_URI, null, null, null, null); 5211 assertEquals(1, cursor.getCount()); 5212 assertTrue(cursor.moveToFirst()); 5213 assertTrue(cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))); 5214 String filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 5215 assertEquals("Mia Prophyl.vcf", filename); 5216 cursor.close(); 5217 } 5218 5219 public void testOpenAssetFileMultiVCard() throws IOException { 5220 final VCardTestUriCreator contacts = createVCardTestContacts(); 5221 5222 final AssetFileDescriptor descriptor = 5223 mResolver.openAssetFileDescriptor(contacts.getCombinedUri(), "r"); 5224 final FileInputStream inputStream = descriptor.createInputStream(); 5225 String data = readToEnd(inputStream); 5226 inputStream.close(); 5227 descriptor.close(); 5228 5229 // Ensure that the resulting VCard has both contacts 5230 assertTrue(data.contains("N:Doe;John;;;")); 5231 assertTrue(data.contains("N:Doh;Jane;;;")); 5232 } 5233 5234 public void testOpenAssetFileSingleVCard() throws IOException { 5235 final VCardTestUriCreator contacts = createVCardTestContacts(); 5236 5237 // Ensure that the right VCard is being created in each case 5238 { 5239 final AssetFileDescriptor descriptor = 5240 mResolver.openAssetFileDescriptor(contacts.getUri1(), "r"); 5241 final FileInputStream inputStream = descriptor.createInputStream(); 5242 final String data = readToEnd(inputStream); 5243 inputStream.close(); 5244 descriptor.close(); 5245 5246 assertTrue(data.contains("N:Doe;John;;;")); 5247 assertFalse(data.contains("N:Doh;Jane;;;")); 5248 } 5249 5250 { 5251 final AssetFileDescriptor descriptor = 5252 mResolver.openAssetFileDescriptor(contacts.getUri2(), "r"); 5253 final FileInputStream inputStream = descriptor.createInputStream(); 5254 final String data = readToEnd(inputStream); 5255 inputStream.close(); 5256 descriptor.close(); 5257 5258 assertFalse(data.contains("N:Doe;John;;;")); 5259 assertTrue(data.contains("N:Doh;Jane;;;")); 5260 } 5261 } 5262 5263 public void testAutoGroupMembership() { 5264 long g1 = createGroup(mAccount, "g1", "t1", 0, true /* autoAdd */, false /* favorite */); 5265 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 5266 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, true /* autoAdd */, false /* favorite */); 5267 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, false/* favorite */); 5268 long r1 = createRawContact(mAccount); 5269 long r2 = createRawContact(mAccountTwo); 5270 long r3 = createRawContact(null); 5271 5272 Cursor c = queryGroupMemberships(mAccount); 5273 try { 5274 assertTrue(c.moveToNext()); 5275 assertEquals(g1, c.getLong(0)); 5276 assertEquals(r1, c.getLong(1)); 5277 assertFalse(c.moveToNext()); 5278 } finally { 5279 c.close(); 5280 } 5281 5282 c = queryGroupMemberships(mAccountTwo); 5283 try { 5284 assertTrue(c.moveToNext()); 5285 assertEquals(g3, c.getLong(0)); 5286 assertEquals(r2, c.getLong(1)); 5287 assertFalse(c.moveToNext()); 5288 } finally { 5289 c.close(); 5290 } 5291 } 5292 5293 public void testNoAutoAddMembershipAfterGroupCreation() { 5294 long r1 = createRawContact(mAccount); 5295 long r2 = createRawContact(mAccount); 5296 long r3 = createRawContact(mAccount); 5297 long r4 = createRawContact(mAccountTwo); 5298 long r5 = createRawContact(mAccountTwo); 5299 long r6 = createRawContact(null); 5300 5301 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5302 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5303 5304 long g1 = createGroup(mAccount, "g1", "t1", 0, true /* autoAdd */, false /* favorite */); 5305 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 5306 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, true /* autoAdd */, false/* favorite */); 5307 5308 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5309 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5310 } 5311 5312 // create some starred and non-starred contacts, some associated with account, some not 5313 // favorites group created 5314 // the starred contacts should be added to group 5315 // favorites group removed 5316 // no change to starred status 5317 public void testFavoritesMembershipAfterGroupCreation() { 5318 long r1 = createRawContact(mAccount, RawContacts.STARRED, "1"); 5319 long r2 = createRawContact(mAccount); 5320 long r3 = createRawContact(mAccount, RawContacts.STARRED, "1"); 5321 long r4 = createRawContact(mAccountTwo, RawContacts.STARRED, "1"); 5322 long r5 = createRawContact(mAccountTwo); 5323 long r6 = createRawContact(null, RawContacts.STARRED, "1"); 5324 long r7 = createRawContact(null); 5325 5326 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5327 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5328 5329 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 5330 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false /* favorite */); 5331 long g3 = createGroup(mAccountTwo, "g3", "t3", 0, false /* autoAdd */, false/* favorite */); 5332 5333 assertTrue(queryRawContactIsStarred(r1)); 5334 assertFalse(queryRawContactIsStarred(r2)); 5335 assertTrue(queryRawContactIsStarred(r3)); 5336 assertTrue(queryRawContactIsStarred(r4)); 5337 assertFalse(queryRawContactIsStarred(r5)); 5338 assertTrue(queryRawContactIsStarred(r6)); 5339 assertFalse(queryRawContactIsStarred(r7)); 5340 5341 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5342 Cursor c = queryGroupMemberships(mAccount); 5343 try { 5344 assertTrue(c.moveToNext()); 5345 assertEquals(g1, c.getLong(0)); 5346 assertEquals(r1, c.getLong(1)); 5347 assertTrue(c.moveToNext()); 5348 assertEquals(g1, c.getLong(0)); 5349 assertEquals(r3, c.getLong(1)); 5350 assertFalse(c.moveToNext()); 5351 } finally { 5352 c.close(); 5353 } 5354 5355 updateItem(RawContacts.CONTENT_URI, r6, 5356 RawContacts.ACCOUNT_NAME, mAccount.name, 5357 RawContacts.ACCOUNT_TYPE, mAccount.type); 5358 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5359 c = queryGroupMemberships(mAccount); 5360 try { 5361 assertTrue(c.moveToNext()); 5362 assertEquals(g1, c.getLong(0)); 5363 assertEquals(r1, c.getLong(1)); 5364 assertTrue(c.moveToNext()); 5365 assertEquals(g1, c.getLong(0)); 5366 assertEquals(r3, c.getLong(1)); 5367 assertTrue(c.moveToNext()); 5368 assertEquals(g1, c.getLong(0)); 5369 assertEquals(r6, c.getLong(1)); 5370 assertFalse(c.moveToNext()); 5371 } finally { 5372 c.close(); 5373 } 5374 5375 mResolver.delete(ContentUris.withAppendedId(Groups.CONTENT_URI, g1), null, null); 5376 5377 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5378 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5379 5380 assertTrue(queryRawContactIsStarred(r1)); 5381 assertFalse(queryRawContactIsStarred(r2)); 5382 assertTrue(queryRawContactIsStarred(r3)); 5383 assertTrue(queryRawContactIsStarred(r4)); 5384 assertFalse(queryRawContactIsStarred(r5)); 5385 assertTrue(queryRawContactIsStarred(r6)); 5386 assertFalse(queryRawContactIsStarred(r7)); 5387 } 5388 5389 public void testFavoritesGroupMembershipChangeAfterStarChange() { 5390 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 5391 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false/* favorite */); 5392 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, true /* favorite */); 5393 long g5 = createGroup(mAccountTwo, "g5", "t5", 0, false /* autoAdd */, false/* favorite */); 5394 long r1 = createRawContact(mAccount, RawContacts.STARRED, "1"); 5395 long r2 = createRawContact(mAccount); 5396 long r3 = createRawContact(mAccountTwo); 5397 5398 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5399 Cursor c = queryGroupMemberships(mAccount); 5400 try { 5401 assertTrue(c.moveToNext()); 5402 assertEquals(g1, c.getLong(0)); 5403 assertEquals(r1, c.getLong(1)); 5404 assertFalse(c.moveToNext()); 5405 } finally { 5406 c.close(); 5407 } 5408 5409 // remove the star from r1 5410 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "0")); 5411 5412 // Since no raw contacts are starred, there should be no group memberships. 5413 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5414 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5415 5416 // mark r1 as starred 5417 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "1")); 5418 // Now that r1 is starred it should have a membership in the one groups from mAccount 5419 // that is marked as a favorite. 5420 // There should be no memberships in mAccountTwo since it has no starred raw contacts. 5421 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5422 c = queryGroupMemberships(mAccount); 5423 try { 5424 assertTrue(c.moveToNext()); 5425 assertEquals(g1, c.getLong(0)); 5426 assertEquals(r1, c.getLong(1)); 5427 assertFalse(c.moveToNext()); 5428 } finally { 5429 c.close(); 5430 } 5431 5432 // remove the star from r1 5433 assertEquals(1, updateItem(RawContacts.CONTENT_URI, r1, RawContacts.STARRED, "0")); 5434 // Since no raw contacts are starred, there should be no group memberships. 5435 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5436 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5437 5438 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(r1)); 5439 assertNotNull(contactUri); 5440 5441 // mark r1 as starred via its contact lookup uri 5442 assertEquals(1, updateItem(contactUri, Contacts.STARRED, "1")); 5443 // Now that r1 is starred it should have a membership in the one groups from mAccount 5444 // that is marked as a favorite. 5445 // There should be no memberships in mAccountTwo since it has no starred raw contacts. 5446 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5447 c = queryGroupMemberships(mAccount); 5448 try { 5449 assertTrue(c.moveToNext()); 5450 assertEquals(g1, c.getLong(0)); 5451 assertEquals(r1, c.getLong(1)); 5452 assertFalse(c.moveToNext()); 5453 } finally { 5454 c.close(); 5455 } 5456 5457 // remove the star from r1 5458 updateItem(contactUri, Contacts.STARRED, "0"); 5459 // Since no raw contacts are starred, there should be no group memberships. 5460 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5461 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5462 } 5463 5464 public void testStarChangedAfterGroupMembershipChange() { 5465 long g1 = createGroup(mAccount, "g1", "t1", 0, false /* autoAdd */, true /* favorite */); 5466 long g2 = createGroup(mAccount, "g2", "t2", 0, false /* autoAdd */, false/* favorite */); 5467 long g4 = createGroup(mAccountTwo, "g4", "t4", 0, false /* autoAdd */, true /* favorite */); 5468 long g5 = createGroup(mAccountTwo, "g5", "t5", 0, false /* autoAdd */, false/* favorite */); 5469 long r1 = createRawContact(mAccount); 5470 long r2 = createRawContact(mAccount); 5471 long r3 = createRawContact(mAccountTwo); 5472 5473 assertFalse(queryRawContactIsStarred(r1)); 5474 assertFalse(queryRawContactIsStarred(r2)); 5475 assertFalse(queryRawContactIsStarred(r3)); 5476 5477 Cursor c; 5478 5479 // add r1 to one favorites group 5480 // r1's star should automatically be set 5481 // r1 should automatically be added to the other favorites group 5482 Uri urir1g1 = insertGroupMembership(r1, g1); 5483 assertTrue(queryRawContactIsStarred(r1)); 5484 assertFalse(queryRawContactIsStarred(r2)); 5485 assertFalse(queryRawContactIsStarred(r3)); 5486 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5487 c = queryGroupMemberships(mAccount); 5488 try { 5489 assertTrue(c.moveToNext()); 5490 assertEquals(g1, c.getLong(0)); 5491 assertEquals(r1, c.getLong(1)); 5492 assertFalse(c.moveToNext()); 5493 } finally { 5494 c.close(); 5495 } 5496 5497 // remove r1 from one favorites group 5498 mResolver.delete(urir1g1, null, null); 5499 // r1's star should no longer be set 5500 assertFalse(queryRawContactIsStarred(r1)); 5501 assertFalse(queryRawContactIsStarred(r2)); 5502 assertFalse(queryRawContactIsStarred(r3)); 5503 // there should be no membership rows 5504 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5505 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5506 5507 // add r3 to the one favorites group for that account 5508 // r3's star should automatically be set 5509 Uri urir3g4 = insertGroupMembership(r3, g4); 5510 assertFalse(queryRawContactIsStarred(r1)); 5511 assertFalse(queryRawContactIsStarred(r2)); 5512 assertTrue(queryRawContactIsStarred(r3)); 5513 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5514 c = queryGroupMemberships(mAccountTwo); 5515 try { 5516 assertTrue(c.moveToNext()); 5517 assertEquals(g4, c.getLong(0)); 5518 assertEquals(r3, c.getLong(1)); 5519 assertFalse(c.moveToNext()); 5520 } finally { 5521 c.close(); 5522 } 5523 5524 // remove r3 from the favorites group 5525 mResolver.delete(urir3g4, null, null); 5526 // r3's star should automatically be cleared 5527 assertFalse(queryRawContactIsStarred(r1)); 5528 assertFalse(queryRawContactIsStarred(r2)); 5529 assertFalse(queryRawContactIsStarred(r3)); 5530 assertNoRowsAndClose(queryGroupMemberships(mAccount)); 5531 assertNoRowsAndClose(queryGroupMemberships(mAccountTwo)); 5532 } 5533 5534 public void testReadOnlyRawContact() { 5535 long rawContactId = createRawContact(); 5536 Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 5537 storeValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "first"); 5538 storeValue(rawContactUri, RawContacts.RAW_CONTACT_IS_READ_ONLY, 1); 5539 5540 storeValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "second"); 5541 assertStoredValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "first"); 5542 5543 Uri syncAdapterUri = rawContactUri.buildUpon() 5544 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "1") 5545 .build(); 5546 storeValue(syncAdapterUri, RawContacts.CUSTOM_RINGTONE, "third"); 5547 assertStoredValue(rawContactUri, RawContacts.CUSTOM_RINGTONE, "third"); 5548 } 5549 5550 public void testReadOnlyDataRow() { 5551 long rawContactId = createRawContact(); 5552 Uri emailUri = insertEmail(rawContactId, "email"); 5553 Uri phoneUri = insertPhoneNumber(rawContactId, "555-1111"); 5554 5555 storeValue(emailUri, Data.IS_READ_ONLY, "1"); 5556 storeValue(emailUri, Email.ADDRESS, "changed"); 5557 storeValue(phoneUri, Phone.NUMBER, "555-2222"); 5558 assertStoredValue(emailUri, Email.ADDRESS, "email"); 5559 assertStoredValue(phoneUri, Phone.NUMBER, "555-2222"); 5560 5561 Uri syncAdapterUri = emailUri.buildUpon() 5562 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "1") 5563 .build(); 5564 storeValue(syncAdapterUri, Email.ADDRESS, "changed"); 5565 assertStoredValue(emailUri, Email.ADDRESS, "changed"); 5566 } 5567 5568 public void testContactWithReadOnlyRawContact() { 5569 long rawContactId1 = createRawContact(); 5570 Uri rawContactUri1 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId1); 5571 storeValue(rawContactUri1, RawContacts.CUSTOM_RINGTONE, "first"); 5572 5573 long rawContactId2 = createRawContact(); 5574 Uri rawContactUri2 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId2); 5575 storeValue(rawContactUri2, RawContacts.CUSTOM_RINGTONE, "second"); 5576 storeValue(rawContactUri2, RawContacts.RAW_CONTACT_IS_READ_ONLY, 1); 5577 5578 setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, 5579 rawContactId1, rawContactId2); 5580 5581 long contactId = queryContactId(rawContactId1); 5582 5583 Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 5584 storeValue(contactUri, Contacts.CUSTOM_RINGTONE, "rt"); 5585 assertStoredValue(contactUri, Contacts.CUSTOM_RINGTONE, "rt"); 5586 assertStoredValue(rawContactUri1, RawContacts.CUSTOM_RINGTONE, "rt"); 5587 assertStoredValue(rawContactUri2, RawContacts.CUSTOM_RINGTONE, "second"); 5588 } 5589 5590 public void testNameParsingQuery() { 5591 Uri uri = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name") 5592 .appendQueryParameter(StructuredName.DISPLAY_NAME, "Mr. John Q. Doe Jr.").build(); 5593 Cursor cursor = mResolver.query(uri, null, null, null, null); 5594 ContentValues values = new ContentValues(); 5595 values.put(StructuredName.DISPLAY_NAME, "Mr. John Q. Doe Jr."); 5596 values.put(StructuredName.PREFIX, "Mr."); 5597 values.put(StructuredName.GIVEN_NAME, "John"); 5598 values.put(StructuredName.MIDDLE_NAME, "Q."); 5599 values.put(StructuredName.FAMILY_NAME, "Doe"); 5600 values.put(StructuredName.SUFFIX, "Jr."); 5601 values.put(StructuredName.FULL_NAME_STYLE, FullNameStyle.WESTERN); 5602 assertTrue(cursor.moveToFirst()); 5603 assertCursorValues(cursor, values); 5604 cursor.close(); 5605 } 5606 5607 public void testNameConcatenationQuery() { 5608 Uri uri = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name") 5609 .appendQueryParameter(StructuredName.PREFIX, "Mr") 5610 .appendQueryParameter(StructuredName.GIVEN_NAME, "John") 5611 .appendQueryParameter(StructuredName.MIDDLE_NAME, "Q.") 5612 .appendQueryParameter(StructuredName.FAMILY_NAME, "Doe") 5613 .appendQueryParameter(StructuredName.SUFFIX, "Jr.") 5614 .build(); 5615 Cursor cursor = mResolver.query(uri, null, null, null, null); 5616 ContentValues values = new ContentValues(); 5617 values.put(StructuredName.DISPLAY_NAME, "Mr John Q. Doe, Jr."); 5618 values.put(StructuredName.PREFIX, "Mr"); 5619 values.put(StructuredName.GIVEN_NAME, "John"); 5620 values.put(StructuredName.MIDDLE_NAME, "Q."); 5621 values.put(StructuredName.FAMILY_NAME, "Doe"); 5622 values.put(StructuredName.SUFFIX, "Jr."); 5623 values.put(StructuredName.FULL_NAME_STYLE, FullNameStyle.WESTERN); 5624 assertTrue(cursor.moveToFirst()); 5625 assertCursorValues(cursor, values); 5626 cursor.close(); 5627 } 5628 5629 private Cursor queryGroupMemberships(Account account) { 5630 Cursor c = mResolver.query(maybeAddAccountQueryParameters(Data.CONTENT_URI, account), 5631 new String[]{GroupMembership.GROUP_ROW_ID, GroupMembership.RAW_CONTACT_ID}, 5632 Data.MIMETYPE + "=?", new String[]{GroupMembership.CONTENT_ITEM_TYPE}, 5633 GroupMembership.GROUP_SOURCE_ID); 5634 return c; 5635 } 5636 5637 private String readToEnd(FileInputStream inputStream) { 5638 try { 5639 System.out.println("DECLARED INPUT STREAM LENGTH: " + inputStream.available()); 5640 int ch; 5641 StringBuilder stringBuilder = new StringBuilder(); 5642 int index = 0; 5643 while (true) { 5644 ch = inputStream.read(); 5645 System.out.println("READ CHARACTER: " + index + " " + ch); 5646 if (ch == -1) { 5647 break; 5648 } 5649 stringBuilder.append((char)ch); 5650 index++; 5651 } 5652 return stringBuilder.toString(); 5653 } catch (IOException e) { 5654 return null; 5655 } 5656 } 5657 5658 private void assertQueryParameter(String uriString, String parameter, String expectedValue) { 5659 assertEquals(expectedValue, ContactsProvider2.getQueryParameter( 5660 Uri.parse(uriString), parameter)); 5661 } 5662 5663 private long createContact(ContentValues values, String firstName, String givenName, 5664 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 5665 long groupId, int chatMode) { 5666 return createContact(values, firstName, givenName, phoneNumber, email, presenceStatus, 5667 timesContacted, starred, groupId, chatMode, false); 5668 } 5669 5670 private long createContact(ContentValues values, String firstName, String givenName, 5671 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 5672 long groupId, int chatMode, boolean isUserProfile) { 5673 return queryContactId(createRawContact(values, firstName, givenName, phoneNumber, email, 5674 presenceStatus, timesContacted, starred, groupId, chatMode, isUserProfile)); 5675 } 5676 5677 private long createRawContact(ContentValues values, String firstName, String givenName, 5678 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 5679 long groupId, int chatMode) { 5680 long rawContactId = createRawContact(values, phoneNumber, email, presenceStatus, 5681 timesContacted, starred, groupId, chatMode); 5682 insertStructuredName(rawContactId, firstName, givenName); 5683 return rawContactId; 5684 } 5685 5686 private long createRawContact(ContentValues values, String firstName, String givenName, 5687 String phoneNumber, String email, int presenceStatus, int timesContacted, int starred, 5688 long groupId, int chatMode, boolean isUserProfile) { 5689 long rawContactId = createRawContact(values, phoneNumber, email, presenceStatus, 5690 timesContacted, starred, groupId, chatMode, isUserProfile); 5691 insertStructuredName(rawContactId, firstName, givenName); 5692 return rawContactId; 5693 } 5694 5695 private long createRawContact(ContentValues values, String phoneNumber, String email, 5696 int presenceStatus, int timesContacted, int starred, long groupId, int chatMode) { 5697 return createRawContact(values, phoneNumber, email, presenceStatus, timesContacted, starred, 5698 groupId, chatMode, false); 5699 } 5700 5701 private long createRawContact(ContentValues values, String phoneNumber, String email, 5702 int presenceStatus, int timesContacted, int starred, long groupId, int chatMode, 5703 boolean isUserProfile) { 5704 values.put(RawContacts.STARRED, starred); 5705 values.put(RawContacts.SEND_TO_VOICEMAIL, 1); 5706 values.put(RawContacts.CUSTOM_RINGTONE, "beethoven5"); 5707 values.put(RawContacts.TIMES_CONTACTED, timesContacted); 5708 5709 Uri insertionUri = isUserProfile 5710 ? Profile.CONTENT_RAW_CONTACTS_URI 5711 : RawContacts.CONTENT_URI; 5712 Uri rawContactUri = mResolver.insert(insertionUri, values); 5713 long rawContactId = ContentUris.parseId(rawContactUri); 5714 Uri photoUri = insertPhoto(rawContactId); 5715 long photoId = ContentUris.parseId(photoUri); 5716 values.put(Contacts.PHOTO_ID, photoId); 5717 insertPhoneNumber(rawContactId, phoneNumber); 5718 insertEmail(rawContactId, email); 5719 5720 insertStatusUpdate(Im.PROTOCOL_GOOGLE_TALK, null, email, presenceStatus, "hacking", 5721 chatMode); 5722 5723 if (groupId != 0) { 5724 insertGroupMembership(rawContactId, groupId); 5725 } 5726 5727 return rawContactId; 5728 } 5729 5730 /** 5731 * Creates a raw contact with pre-set values under the user's profile. 5732 * @param profileValues Values to be used to create the entry (common values will be 5733 * automatically populated in createRawContact()). 5734 * @return the raw contact ID that was created. 5735 */ 5736 private long createBasicProfileContact(ContentValues profileValues) { 5737 long profileRawContactId = createRawContact(profileValues, "Mia", "Prophyl", 5738 "18005554411", "mia.prophyl@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 5739 StatusUpdates.CAPABILITY_HAS_CAMERA, true); 5740 profileValues.put(Contacts.DISPLAY_NAME, "Mia Prophyl"); 5741 return profileRawContactId; 5742 } 5743 5744 /** 5745 * Creates a raw contact with pre-set values that is not under the user's profile. 5746 * @param nonProfileValues Values to be used to create the entry (common values will be 5747 * automatically populated in createRawContact()). 5748 * @return the raw contact ID that was created. 5749 */ 5750 private long createBasicNonProfileContact(ContentValues nonProfileValues) { 5751 long nonProfileRawContactId = createRawContact(nonProfileValues, "John", "Doe", 5752 "18004664411", "goog411@acme.com", StatusUpdates.INVISIBLE, 4, 1, 0, 5753 StatusUpdates.CAPABILITY_HAS_CAMERA, false); 5754 nonProfileValues.put(Contacts.DISPLAY_NAME, "John Doe"); 5755 return nonProfileRawContactId; 5756 } 5757 5758 private void putDataValues(ContentValues values, long rawContactId) { 5759 values.put(Data.RAW_CONTACT_ID, rawContactId); 5760 values.put(Data.MIMETYPE, "testmimetype"); 5761 values.put(Data.RES_PACKAGE, "oldpackage"); 5762 values.put(Data.IS_PRIMARY, 1); 5763 values.put(Data.IS_SUPER_PRIMARY, 1); 5764 values.put(Data.DATA1, "one"); 5765 values.put(Data.DATA2, "two"); 5766 values.put(Data.DATA3, "three"); 5767 values.put(Data.DATA4, "four"); 5768 values.put(Data.DATA5, "five"); 5769 values.put(Data.DATA6, "six"); 5770 values.put(Data.DATA7, "seven"); 5771 values.put(Data.DATA8, "eight"); 5772 values.put(Data.DATA9, "nine"); 5773 values.put(Data.DATA10, "ten"); 5774 values.put(Data.DATA11, "eleven"); 5775 values.put(Data.DATA12, "twelve"); 5776 values.put(Data.DATA13, "thirteen"); 5777 values.put(Data.DATA14, "fourteen"); 5778 values.put(Data.DATA15, "fifteen"); 5779 values.put(Data.SYNC1, "sync1"); 5780 values.put(Data.SYNC2, "sync2"); 5781 values.put(Data.SYNC3, "sync3"); 5782 values.put(Data.SYNC4, "sync4"); 5783 } 5784 5785 /** 5786 * @param data1 email address or phone number 5787 * @param usageType One of {@link DataUsageFeedback#USAGE_TYPE} 5788 * @param values ContentValues for this feedback. Useful for incrementing 5789 * {Contacts#TIMES_CONTACTED} in the ContentValue. Can be null. 5790 */ 5791 private void sendFeedback(String data1, String usageType, ContentValues values) { 5792 final long dataId = getStoredLongValue(Data.CONTENT_URI, 5793 Data.DATA1 + "=?", new String[] { data1 }, Data._ID); 5794 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 5795 .appendPath(String.valueOf(dataId)) 5796 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType) 5797 .build(); 5798 assertNotSame(0, mResolver.update(feedbackUri, new ContentValues(), null, null)); 5799 if (values != null && values.containsKey(Contacts.TIMES_CONTACTED)) { 5800 values.put(Contacts.TIMES_CONTACTED, values.getAsInteger(Contacts.TIMES_CONTACTED) + 1); 5801 } 5802 } 5803} 5804 5805